✨ UserDetail and UserList views
This commit is contained in:
1 parent
ec0549154d
commit
e2a84c25a6
16 files changed
+201
-22
No files matched your search
@@ -1,14 +1,12 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import clsx from "clsx";
|
||||
import { parseISO, format } from "date-fns";
|
||||
import React from "react";
|
||||
import { useUrlSearchParams } from "use-url-search-params";
|
||||
|
||||
import { Order, OrderLine, OrderListDocument, Transaction, TransactionListDocument } from "../../types";
|
||||
import { formatTime } from "../../utils/time";
|
||||
import styles from "./Log.module.css";
|
||||
|
||||
const formatTime = (isoDateTime: string): string => format(parseISO(isoDateTime), "yyyy-MM-dd HH:mm");
|
||||
|
||||
const PAGE_SIZE = 10;
|
||||
|
||||
export const Log = () => {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import { parseISO, subDays } from "date-fns";
|
||||
import { useState } from "react";
|
||||
|
||||
import { User, Product, AllProductsDocument, AllUsersDocument } from "../../types";
|
||||
|
||||
const activeLimitDays = 365 / 2;
|
||||
import { activeUserFilter } from "../../utils/users";
|
||||
|
||||
type useRegisterType = {
|
||||
users: User[];
|
||||
@@ -20,13 +18,7 @@ export const useRegister = (): useRegisterType => {
|
||||
const { data: usersData, loading: usersLoading } = useQuery(AllUsersDocument);
|
||||
|
||||
const allUsers = usersData?.allUsers || [];
|
||||
const users = showAll
|
||||
? allUsers
|
||||
: allUsers.filter((user: User) => {
|
||||
const balance = user.profile?.balance || 0;
|
||||
const active = parseISO(user.profile?.lastPurchaseDate) >= subDays(new Date(), activeLimitDays);
|
||||
return balance >= 15 && active;
|
||||
});
|
||||
const users = showAll ? allUsers : allUsers.filter(activeUserFilter);
|
||||
|
||||
return { loading: loading || usersLoading, users, products: data?.allProducts || [], showAll, setShowAll };
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
.userDetail {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import React from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { User, UserDetailDocument, UserProfile } from "../../types";
|
||||
import { formatMonth, formatTime } from "../../utils/time";
|
||||
import styles from "./UserDetail.module.css";
|
||||
|
||||
export const UserDetail = () => {
|
||||
const { userId } = useParams();
|
||||
const { data, loading } = useQuery(UserDetailDocument, { variables: { userId: userId || "" }, skip: !userId });
|
||||
|
||||
if (loading) return <div>Loading...</div>;
|
||||
|
||||
const user = data?.user as User;
|
||||
const profile = user?.profile as UserProfile;
|
||||
return (
|
||||
<div className={styles.userDetail}>
|
||||
<div>
|
||||
<h1>
|
||||
{profile.image && <img src={profile.image} alt={`${user.firstName}s profile picture`} />} {user.firstName}
|
||||
</h1>
|
||||
<div className="card">
|
||||
<div className="card-header">Stats</div>
|
||||
<ul className="list-group list-group-flush">
|
||||
<li className="list-group-item">Saldo: {profile.balance}</li>
|
||||
<li className="list-group-item">Siste kjøp: {formatTime(profile.lastPurchaseDate)}</li>
|
||||
<li className="list-group-item">Kjøp totalt: {profile.orderSumTotal.toLocaleString()}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<br />
|
||||
<div className="card">
|
||||
<div className="card-header">Top 5 måneder</div>
|
||||
<ul className="list-group list-group-flush">
|
||||
{profile.topMonths.map((topMonth) => (
|
||||
<li key={topMonth.period} className="list-group-item">
|
||||
{formatMonth(topMonth.period)}: <strong>{topMonth.count}</strong> kjøp på totalt{" "}
|
||||
<strong>{topMonth.sum} kr</strong>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div>TODO: produktgraf</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useQuery } from "@apollo/client";
|
||||
import React, { useState } from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { AllUsersDocument } from "../../types";
|
||||
import { activeUserFilter } from "../../utils/users";
|
||||
|
||||
export const UserList = () => {
|
||||
const { data, loading } = useQuery(AllUsersDocument);
|
||||
const [showAll, setShowAll] = useState(false);
|
||||
|
||||
if (loading) return <div>Loading...</div>;
|
||||
|
||||
const allUsers = data?.allUsers || [];
|
||||
const users = showAll ? allUsers : allUsers.filter(activeUserFilter);
|
||||
return (
|
||||
<div>
|
||||
<button type="button" className="btn btn-link" onClick={() => setShowAll(!showAll)}>
|
||||
{showAll ? "Skjul gamliser" : "Vis alle"}
|
||||
</button>
|
||||
<ul>
|
||||
{(users || []).map((user) => (
|
||||
<li key={user.id}>
|
||||
<Link to={`/user/${user.id}`}>
|
||||
{user.firstName} {user.lastName}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
query userDetail($userId: ID!) {
|
||||
user(userId: $userId) {
|
||||
id
|
||||
firstName
|
||||
lastName
|
||||
profile {
|
||||
id
|
||||
balance
|
||||
image
|
||||
lastPurchaseDate
|
||||
topMonths {
|
||||
period
|
||||
sum
|
||||
count
|
||||
}
|
||||
orderSumTotal
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user