feat: user history

This commit is contained in:
IlyaDoronin 2024-03-11 09:55:29 +03:00
parent 13ec627b31
commit 71102972cd
7 changed files with 184 additions and 12 deletions

@ -26,6 +26,7 @@
"axios": "^1.4.0", "axios": "^1.4.0",
"craco": "^0.0.3", "craco": "^0.0.3",
"cypress": "^12.17.2", "cypress": "^12.17.2",
"date-fns": "^3.3.1",
"dayjs": "^1.11.5", "dayjs": "^1.11.5",
"formik": "^2.2.9", "formik": "^2.2.9",
"immer": "^10.0.2", "immer": "^10.0.2",

@ -0,0 +1,50 @@
import { makeRequest } from "@frontend/kitui";
import { parseAxiosError } from "@root/utils/parse-error";
type RawDetail = {
Key: string;
Value: number | string | RawDetail[];
};
type History = {
id: string;
userId: string;
comment: string;
key: string;
rawDetails: RawDetail[];
isDeleted: boolean;
createdAt: string;
updatedAt: string;
};
type HistoryResponse = {
records: History[];
totalPages: number;
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/customer";
const getUserHistory = async (
accountId: string,
page: number
): Promise<[HistoryResponse | null, string?]> => {
try {
const historyResponse = await makeRequest<never, HistoryResponse>({
method: "GET",
url:
baseUrl +
`/history?page=${page}&limit=${100}&accountID=${accountId}&type=payCart`,
});
return [historyResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении пользователей. ${error}`];
}
};
export const historyApi = {
getUserHistory,
};

43
src/api/history/swr.ts Normal file

@ -0,0 +1,43 @@
import { useState } from "react";
import useSWRInfinite from "swr/infinite";
import { enqueueSnackbar } from "notistack";
import { historyApi } from "./requests";
export function useHistory(accountId: string) {
const [currentPage, setCurrentPage] = useState<number>(1);
const swrResponse = useSWRInfinite(
() => `history-${currentPage}`,
async () => {
const [historyResponse, error] = await historyApi.getUserHistory(
accountId,
currentPage
);
if (error) {
throw new Error(error);
}
if (!historyResponse) {
throw new Error("Empty history data");
}
if (currentPage < historyResponse.totalPages) {
setCurrentPage((page) => page + 1);
}
return historyResponse;
},
{
onError(err) {
console.log("Error fetching users", err);
enqueueSnackbar(err.message, { variant: "error" });
},
focusThrottleInterval: 60e3,
keepPreviousData: true,
}
);
return swrResponse;
}

@ -4,7 +4,7 @@ import { parseAxiosError } from "@root/utils/parse-error";
import type { UserType } from "@root/api/roles"; import type { UserType } from "@root/api/roles";
export type RegisteredUsersResponse = { export type UsersListResponse = {
totalPages: number; totalPages: number;
users: UserType[]; users: UserType[];
}; };
@ -30,9 +30,9 @@ const getUserInfo = async (id: string): Promise<[UserType | null, string?]> => {
const getUserList = async ( const getUserList = async (
page = 1, page = 1,
limit = 10 limit = 10
): Promise<[RegisteredUsersResponse | null, string?]> => { ): Promise<[UsersListResponse | null, string?]> => {
try { try {
const userResponse = await makeRequest<never, RegisteredUsersResponse>({ const userResponse = await makeRequest<never, UsersListResponse>({
method: "get", method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`, url: baseUrl + `/?page=${page}&limit=${limit}`,
}); });
@ -48,9 +48,9 @@ const getUserList = async (
const getManagerList = async ( const getManagerList = async (
page = 1, page = 1,
limit = 10 limit = 10
): Promise<[RegisteredUsersResponse | null, string?]> => { ): Promise<[UsersListResponse | null, string?]> => {
try { try {
const managerResponse = await makeRequest<never, RegisteredUsersResponse>({ const managerResponse = await makeRequest<never, UsersListResponse>({
method: "get", method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`, url: baseUrl + `/?page=${page}&limit=${limit}`,
}); });
@ -66,9 +66,9 @@ const getManagerList = async (
const getAdminList = async ( const getAdminList = async (
page = 1, page = 1,
limit = 10 limit = 10
): Promise<[RegisteredUsersResponse | null, string?]> => { ): Promise<[UsersListResponse | null, string?]> => {
try { try {
const adminResponse = await makeRequest<never, RegisteredUsersResponse>({ const adminResponse = await makeRequest<never, UsersListResponse>({
method: "get", method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`, url: baseUrl + `/?page=${page}&limit=${limit}`,
}); });

@ -1,7 +1,9 @@
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { Box, useTheme, useMediaQuery } from "@mui/material"; import { Box, useTheme, useMediaQuery } from "@mui/material";
import { DataGrid } from "@mui/x-data-grid"; import { DataGrid } from "@mui/x-data-grid";
import { format } from "date-fns";
import { useHistory } from "@root/api/history/swr";
import { scrollBlock } from "@root/utils/scrollBlock"; import { scrollBlock } from "@root/utils/scrollBlock";
import forwardIcon from "@root/assets/icons/forward.svg"; import forwardIcon from "@root/assets/icons/forward.svg";
@ -9,6 +11,10 @@ import forwardIcon from "@root/assets/icons/forward.svg";
import type { ChangeEvent } from "react"; import type { ChangeEvent } from "react";
import type { GridColDef } from "@mui/x-data-grid"; import type { GridColDef } from "@mui/x-data-grid";
type PurchaseTabProps = {
userId: string;
};
const COLUMNS: GridColDef[] = [ const COLUMNS: GridColDef[] = [
{ {
field: "date", field: "date",
@ -68,12 +74,22 @@ const ROWS = [
}, },
]; ];
export const PurchaseTab = () => { export const PurchaseTab = ({ userId }: PurchaseTabProps) => {
const [canScrollToRight, setCanScrollToRight] = useState<boolean>(true); const [canScrollToRight, setCanScrollToRight] = useState<boolean>(true);
const [canScrollToLeft, setCanScrollToLeft] = useState<boolean>(false); const [canScrollToLeft, setCanScrollToLeft] = useState<boolean>(false);
const theme = useTheme(); const theme = useTheme();
const smallScreen = useMediaQuery(theme.breakpoints.down(830)); const smallScreen = useMediaQuery(theme.breakpoints.down(830));
const gridContainer = useRef<HTMLDivElement>(null); const gridContainer = useRef<HTMLDivElement>(null);
const { data: historyData } = useHistory(userId);
const rows =
historyData?.[0].records.map((history) => ({
id: history.id,
date: format(history.updatedAt, "dd.MM.yyyy"),
time: format(history.updatedAt, "HH:mm"),
product: "",
amount: "",
})) ?? [];
useEffect(() => { useEffect(() => {
const handleScroll = (nativeEvent: unknown) => { const handleScroll = (nativeEvent: unknown) => {
@ -145,10 +161,8 @@ export const PurchaseTab = () => {
}} }}
> >
<DataGrid <DataGrid
rows={ROWS} rows={rows}
columns={COLUMNS} columns={COLUMNS}
pageSize={5}
rowsPerPageOptions={[5]}
hideFooter hideFooter
disableColumnMenu disableColumnMenu
disableSelectionOnClick disableSelectionOnClick
@ -239,3 +253,62 @@ export const PurchaseTab = () => {
</Box> </Box>
); );
}; };
const a = {
id: "65e4f1b157004756bc5bb15c",
userId: "64eb6ce57047f28fdabf69ec",
comment: "Успешная оплата корзины",
key: "payCart",
rawDetails: [
[
{ Key: "id", Value: "65e4f1881747c1eea8007d3b" },
{
Key: "name",
Value:
"Количество Заявок, Скрытие шильдика в опроснике, 2024-03-03T21:54:16.434Z",
},
{ Key: "price", Value: 0 },
{ Key: "iscustom", Value: true },
{
Key: "privileges",
Value: [
[
{ Key: "id", Value: "" },
{ Key: "name", Value: "Количество Заявок" },
{ Key: "privilegeid", Value: "quizCnt" },
{ Key: "servicekey", Value: "squiz" },
{
Key: "description",
Value: "Количество полных прохождений опросов",
},
{ Key: "amount", Value: 100 },
{ Key: "type", Value: "count" },
{ Key: "value", Value: "заявка" },
{ Key: "price", Value: 2000 },
],
[
{ Key: "id", Value: "" },
{ Key: "name", Value: "Скрытие шильдика в опроснике" },
{ Key: "privilegeid", Value: "squizHideBadge" },
{ Key: "servicekey", Value: "squiz" },
{
Key: "description",
Value: "Количество дней скрытия шильдика в опроснике",
},
{ Key: "amount", Value: 30 },
{ Key: "type", Value: "day" },
{ Key: "value", Value: "день" },
{ Key: "price", Value: 0 },
],
],
},
{ Key: "deleted", Value: false },
{ Key: "createdat", Value: "2024-03-03T21:54:16.825Z" },
{ Key: "updatedat", Value: "2024-03-03T21:54:16.825Z" },
{ Key: "deletedat", Value: null },
],
],
isDeleted: false,
createdAt: "2024-03-03T21:54:57.433Z",
updatedAt: "2024-03-03T21:54:57.433Z",
};

@ -191,7 +191,7 @@ const ModalUser = ({ open, onClose, userId }: ModalUserProps) => {
}} }}
> >
{value === 0 && <UserTab userId={userId} />} {value === 0 && <UserTab userId={userId} />}
{value === 1 && <PurchaseTab />} {value === 1 && <PurchaseTab userId={userId} />}
{value === 2 && <TransactionsTab />} {value === 2 && <TransactionsTab />}
{value === 3 && <VerificationTab userId={userId} />} {value === 3 && <VerificationTab userId={userId} />}
</Box> </Box>

@ -5028,6 +5028,11 @@ data-urls@^2.0.0:
whatwg-mimetype "^2.3.0" whatwg-mimetype "^2.3.0"
whatwg-url "^8.0.0" whatwg-url "^8.0.0"
date-fns@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.3.1.tgz#7581daca0892d139736697717a168afbb908cfed"
integrity sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==
dayjs@^1.10.4: dayjs@^1.10.4:
version "1.11.9" version "1.11.9"
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a"