feat: scroll DataGrid buttons logic
This commit is contained in:
parent
89d44b64fd
commit
b1b267fdb7
@ -1,6 +1,12 @@
|
|||||||
import { Box } from "@mui/material";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { Box, useTheme, useMediaQuery } from "@mui/material";
|
||||||
import { DataGrid } from "@mui/x-data-grid";
|
import { DataGrid } from "@mui/x-data-grid";
|
||||||
|
|
||||||
|
import { scrollBlock } from "@root/utils/scrollBlock";
|
||||||
|
|
||||||
|
import forwardIcon from "@root/assets/icons/forward.svg";
|
||||||
|
|
||||||
|
import type { ChangeEvent } from "react";
|
||||||
import type { GridColDef } from "@mui/x-data-grid";
|
import type { GridColDef } from "@mui/x-data-grid";
|
||||||
|
|
||||||
const COLUMNS: GridColDef[] = [
|
const COLUMNS: GridColDef[] = [
|
||||||
@ -62,63 +68,174 @@ const ROWS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const PurchaseTab = () => (
|
export const PurchaseTab = () => {
|
||||||
<Box
|
const [canScrollToRight, setCanScrollToRight] = useState<boolean>(true);
|
||||||
sx={{
|
const [canScrollToLeft, setCanScrollToLeft] = useState<boolean>(false);
|
||||||
height: "100%",
|
const theme = useTheme();
|
||||||
padding: "0 25px",
|
const smallScreen = useMediaQuery(theme.breakpoints.down(830));
|
||||||
"&:before": {
|
const gridContainer = useRef<HTMLDivElement>(null);
|
||||||
content: '""',
|
|
||||||
height: "50px",
|
useEffect(() => {
|
||||||
width: "100%",
|
const handleScroll = (nativeEvent: unknown) => {
|
||||||
position: "absolute",
|
const { target } = nativeEvent as ChangeEvent<HTMLDivElement>;
|
||||||
left: "0",
|
|
||||||
top: "0",
|
if (target.scrollLeft > 0) {
|
||||||
background: "#F2F3F7",
|
setCanScrollToLeft(true);
|
||||||
},
|
} else {
|
||||||
}}
|
setCanScrollToLeft(false);
|
||||||
>
|
}
|
||||||
<DataGrid
|
|
||||||
rows={ROWS}
|
if (target.clientWidth + target.scrollLeft >= target.scrollWidth - 1) {
|
||||||
columns={COLUMNS}
|
setCanScrollToRight(false);
|
||||||
pageSize={5}
|
} else {
|
||||||
rowsPerPageOptions={[5]}
|
setCanScrollToRight(true);
|
||||||
hideFooter
|
}
|
||||||
disableColumnMenu
|
};
|
||||||
disableSelectionOnClick
|
|
||||||
rowHeight={50}
|
const addScrollEvent = () => {
|
||||||
headerHeight={50}
|
const grid = gridContainer.current?.querySelector(
|
||||||
experimentalFeatures={{ newEditingApi: true }}
|
".MuiDataGrid-virtualScroller"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (grid) {
|
||||||
|
grid.addEventListener("scroll", handleScroll);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(addScrollEvent, 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
addScrollEvent();
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const grid = gridContainer.current?.querySelector(
|
||||||
|
".MuiDataGrid-virtualScroller"
|
||||||
|
);
|
||||||
|
|
||||||
|
grid?.removeEventListener("scroll", handleScroll);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const scrollDataGrid = (toStart = false) => {
|
||||||
|
const grid = gridContainer.current?.querySelector(
|
||||||
|
".MuiDataGrid-virtualScroller"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (grid) {
|
||||||
|
scrollBlock(grid, { left: toStart ? 0 : grid.scrollWidth });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
ref={gridContainer}
|
||||||
sx={{
|
sx={{
|
||||||
borderRadius: "0",
|
height: "100%",
|
||||||
border: "none",
|
padding: "0 25px",
|
||||||
"& .MuiDataGrid-columnHeaders": {
|
"&:before": {
|
||||||
|
content: '""',
|
||||||
|
height: "50px",
|
||||||
|
width: "100%",
|
||||||
|
position: "absolute",
|
||||||
|
left: "0",
|
||||||
|
top: "0",
|
||||||
background: "#F2F3F7",
|
background: "#F2F3F7",
|
||||||
borderBottom: "none",
|
|
||||||
},
|
|
||||||
"& .MuiDataGrid-main .MuiDataGrid-columnHeader": {
|
|
||||||
outline: "none",
|
|
||||||
},
|
|
||||||
"& .MuiDataGrid-columnHeaderTitle": {
|
|
||||||
fontWeight: "bold",
|
|
||||||
userSelect: "none",
|
|
||||||
},
|
|
||||||
"& .MuiDataGrid-virtualScrollerRenderZone": {
|
|
||||||
width: "100%",
|
|
||||||
},
|
|
||||||
"& .MuiDataGrid-iconSeparator": { display: "none" },
|
|
||||||
"& .MuiDataGrid-main .MuiDataGrid-cell": {
|
|
||||||
outline: "none",
|
|
||||||
border: "none",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
},
|
|
||||||
"& .MuiDataGrid-row": {
|
|
||||||
width: "100%",
|
|
||||||
"&:hover": {
|
|
||||||
background: "#F2F3F7",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
</Box>
|
<DataGrid
|
||||||
);
|
rows={ROWS}
|
||||||
|
columns={COLUMNS}
|
||||||
|
pageSize={5}
|
||||||
|
rowsPerPageOptions={[5]}
|
||||||
|
hideFooter
|
||||||
|
disableColumnMenu
|
||||||
|
disableSelectionOnClick
|
||||||
|
rowHeight={50}
|
||||||
|
headerHeight={50}
|
||||||
|
experimentalFeatures={{ newEditingApi: true }}
|
||||||
|
sx={{
|
||||||
|
borderRadius: "0",
|
||||||
|
border: "none",
|
||||||
|
"& .MuiDataGrid-columnHeaders": {
|
||||||
|
background: "#F2F3F7",
|
||||||
|
borderBottom: "none",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-main .MuiDataGrid-columnHeader": {
|
||||||
|
outline: "none",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderTitle": {
|
||||||
|
fontWeight: "bold",
|
||||||
|
userSelect: "none",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-virtualScrollerRenderZone": {
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-iconSeparator": { display: "none" },
|
||||||
|
"& .MuiDataGrid-main .MuiDataGrid-cell": {
|
||||||
|
outline: "none",
|
||||||
|
border: "none",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-row": {
|
||||||
|
width: "100%",
|
||||||
|
"&:hover": {
|
||||||
|
background: "#F2F3F7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{smallScreen && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
right: "15px",
|
||||||
|
bottom: "50px",
|
||||||
|
display: "flex",
|
||||||
|
columnGap: "5px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{canScrollToLeft && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "30px",
|
||||||
|
height: "30px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
border: "1px solid #7E2AEA",
|
||||||
|
background: "rgba(126, 42, 234, 0.07)",
|
||||||
|
}}
|
||||||
|
onClick={() => scrollDataGrid(true)}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={forwardIcon}
|
||||||
|
alt="forward"
|
||||||
|
style={{ transform: "rotate(180deg)" }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{canScrollToRight && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "30px",
|
||||||
|
height: "30px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
border: "1px solid #7E2AEA",
|
||||||
|
background: "rgba(126, 42, 234, 0.07)",
|
||||||
|
}}
|
||||||
|
onClick={() => scrollDataGrid(false)}
|
||||||
|
>
|
||||||
|
<img src={forwardIcon} alt="forward" />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import { Typography, Box, useTheme, useMediaQuery } from "@mui/material";
|
||||||
import { DataGrid } from "@mui/x-data-grid";
|
import { DataGrid } from "@mui/x-data-grid";
|
||||||
import { Typography } from "@mui/material";
|
|
||||||
|
|
||||||
|
import { scrollBlock } from "@root/utils/scrollBlock";
|
||||||
|
|
||||||
|
import forwardIcon from "@root/assets/icons/forward.svg";
|
||||||
|
|
||||||
|
import type { ChangeEvent } from "react";
|
||||||
import type { GridColDef } from "@mui/x-data-grid";
|
import type { GridColDef } from "@mui/x-data-grid";
|
||||||
|
|
||||||
const COLUMNS: GridColDef[] = [
|
const COLUMNS: GridColDef[] = [
|
||||||
@ -86,49 +92,161 @@ const ROWS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const TransactionsTab = () => (
|
export const TransactionsTab = () => {
|
||||||
<DataGrid
|
const [canScrollToRight, setCanScrollToRight] = useState<boolean>(true);
|
||||||
rows={ROWS}
|
const [canScrollToLeft, setCanScrollToLeft] = useState<boolean>(false);
|
||||||
columns={COLUMNS}
|
const theme = useTheme();
|
||||||
pageSize={5}
|
const smallScreen = useMediaQuery(theme.breakpoints.down(1070));
|
||||||
rowsPerPageOptions={[5]}
|
const gridContainer = useRef<HTMLDivElement>(null);
|
||||||
hideFooter
|
|
||||||
disableColumnMenu
|
useEffect(() => {
|
||||||
disableSelectionOnClick
|
const handleScroll = (nativeEvent: unknown) => {
|
||||||
rowHeight={50}
|
const { target } = nativeEvent as ChangeEvent<HTMLDivElement>;
|
||||||
headerHeight={50}
|
|
||||||
experimentalFeatures={{ newEditingApi: true }}
|
if (target.scrollLeft > 0) {
|
||||||
sx={{
|
setCanScrollToLeft(true);
|
||||||
borderRadius: "0",
|
} else {
|
||||||
border: "none",
|
setCanScrollToLeft(false);
|
||||||
"& .MuiDataGrid-columnHeaders": {
|
}
|
||||||
padding: "0 25px",
|
|
||||||
background: "#F2F3F7",
|
if (target.clientWidth + target.scrollLeft >= target.scrollWidth - 1) {
|
||||||
borderBottom: "none",
|
setCanScrollToRight(false);
|
||||||
},
|
} else {
|
||||||
"& .MuiDataGrid-main .MuiDataGrid-columnHeader": {
|
setCanScrollToRight(true);
|
||||||
outline: "none",
|
}
|
||||||
},
|
};
|
||||||
"& .MuiDataGrid-columnHeaderTitle": {
|
|
||||||
fontWeight: "bold",
|
const addScrollEvent = () => {
|
||||||
userSelect: "none",
|
const grid = gridContainer.current?.querySelector(
|
||||||
},
|
".MuiDataGrid-virtualScroller"
|
||||||
"& .MuiDataGrid-virtualScrollerRenderZone": {
|
);
|
||||||
width: "100%",
|
|
||||||
},
|
if (grid) {
|
||||||
"& .MuiDataGrid-iconSeparator": { display: "none" },
|
grid.addEventListener("scroll", handleScroll);
|
||||||
"& .MuiDataGrid-main .MuiDataGrid-cell": {
|
|
||||||
outline: "none",
|
return;
|
||||||
border: "none",
|
}
|
||||||
justifyContent: "flex-start",
|
|
||||||
},
|
setTimeout(addScrollEvent, 100);
|
||||||
"& .MuiDataGrid-row": {
|
};
|
||||||
padding: "0 25px",
|
|
||||||
width: "100%",
|
addScrollEvent();
|
||||||
"&:hover": {
|
|
||||||
background: "#F2F3F7",
|
return () => {
|
||||||
},
|
const grid = gridContainer.current?.querySelector(
|
||||||
},
|
".MuiDataGrid-virtualScroller"
|
||||||
}}
|
);
|
||||||
/>
|
|
||||||
);
|
grid?.removeEventListener("scroll", handleScroll);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const scrollDataGrid = (toStart = false) => {
|
||||||
|
const grid = gridContainer.current?.querySelector(
|
||||||
|
".MuiDataGrid-virtualScroller"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (grid) {
|
||||||
|
scrollBlock(grid, { left: toStart ? 0 : grid.scrollWidth });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ height: "100%" }} ref={gridContainer}>
|
||||||
|
<DataGrid
|
||||||
|
rows={ROWS}
|
||||||
|
columns={COLUMNS}
|
||||||
|
pageSize={5}
|
||||||
|
rowsPerPageOptions={[5]}
|
||||||
|
hideFooter
|
||||||
|
disableColumnMenu
|
||||||
|
disableSelectionOnClick
|
||||||
|
rowHeight={50}
|
||||||
|
headerHeight={50}
|
||||||
|
experimentalFeatures={{ newEditingApi: true }}
|
||||||
|
sx={{
|
||||||
|
borderRadius: "0",
|
||||||
|
border: "none",
|
||||||
|
"& .MuiDataGrid-columnHeaders": {
|
||||||
|
padding: "0 25px",
|
||||||
|
background: "#F2F3F7",
|
||||||
|
borderBottom: "none",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-main .MuiDataGrid-columnHeader": {
|
||||||
|
outline: "none",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-columnHeaderTitle": {
|
||||||
|
fontWeight: "bold",
|
||||||
|
userSelect: "none",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-virtualScrollerRenderZone": {
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-iconSeparator": { display: "none" },
|
||||||
|
"& .MuiDataGrid-main .MuiDataGrid-cell": {
|
||||||
|
outline: "none",
|
||||||
|
border: "none",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
},
|
||||||
|
"& .MuiDataGrid-row": {
|
||||||
|
padding: "0 25px",
|
||||||
|
width: "100%",
|
||||||
|
"&:hover": {
|
||||||
|
background: "#F2F3F7",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{smallScreen && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
position: "absolute",
|
||||||
|
right: "15px",
|
||||||
|
bottom: "50px",
|
||||||
|
display: "flex",
|
||||||
|
columnGap: "5px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{canScrollToLeft && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "30px",
|
||||||
|
height: "30px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
border: "1px solid #7E2AEA",
|
||||||
|
background: "rgba(126, 42, 234, 0.07)",
|
||||||
|
}}
|
||||||
|
onClick={() => scrollDataGrid(true)}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={forwardIcon}
|
||||||
|
alt="forward"
|
||||||
|
style={{ transform: "rotate(180deg)" }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
{canScrollToRight && (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "30px",
|
||||||
|
height: "30px",
|
||||||
|
borderRadius: "8px",
|
||||||
|
border: "1px solid #7E2AEA",
|
||||||
|
background: "rgba(126, 42, 234, 0.07)",
|
||||||
|
}}
|
||||||
|
onClick={() => scrollDataGrid(false)}
|
||||||
|
>
|
||||||
|
<img src={forwardIcon} alt="forward" />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -1,18 +1,6 @@
|
|||||||
import { Box, Typography, useTheme, useMediaQuery } from "@mui/material";
|
import { Box, Typography, useTheme, useMediaQuery } from "@mui/material";
|
||||||
|
|
||||||
type UserTabProps = {
|
export const UserTab = () => {
|
||||||
user: {
|
|
||||||
id: number;
|
|
||||||
registrationDate: string;
|
|
||||||
email: string;
|
|
||||||
phone: string;
|
|
||||||
type: string;
|
|
||||||
fullname: string;
|
|
||||||
walletBalance: string;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const UserTab = ({ user }: UserTabProps) => {
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const mobile = useMediaQuery(theme.breakpoints.down(700));
|
const mobile = useMediaQuery(theme.breakpoints.down(700));
|
||||||
|
|
||||||
@ -29,31 +17,31 @@ export const UserTab = ({ user }: UserTabProps) => {
|
|||||||
<Typography sx={{ lineHeight: "20px" }}>ID</Typography>
|
<Typography sx={{ lineHeight: "20px" }}>ID</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{" "}
|
{" "}
|
||||||
{user.id}
|
2810
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ marginBottom: "25px" }}>
|
<Box sx={{ marginBottom: "25px" }}>
|
||||||
<Typography sx={{ lineHeight: "20px" }}>Дата регистрации</Typography>
|
<Typography sx={{ lineHeight: "20px" }}>Дата регистрации</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{user.registrationDate}
|
17.02.2023
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ marginBottom: "25px" }}>
|
<Box sx={{ marginBottom: "25px" }}>
|
||||||
<Typography sx={{ lineHeight: "20px" }}>Email</Typography>
|
<Typography sx={{ lineHeight: "20px" }}>Email</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{user.email}
|
emailexamle@gmail.com
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ marginBottom: "25px" }}>
|
<Box sx={{ marginBottom: "25px" }}>
|
||||||
<Typography sx={{ lineHeight: "20px" }}>Телефон</Typography>
|
<Typography sx={{ lineHeight: "20px" }}>Телефон</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{user.phone}
|
+7 123 456 78 90
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ marginBottom: "25px" }}>
|
<Box sx={{ marginBottom: "25px" }}>
|
||||||
<Typography sx={{ lineHeight: "20px" }}>Тип:</Typography>
|
<Typography sx={{ lineHeight: "20px" }}>Тип:</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{user.type}
|
НКО
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -61,7 +49,7 @@ export const UserTab = ({ user }: UserTabProps) => {
|
|||||||
<Box sx={{ marginBottom: "25px" }}>
|
<Box sx={{ marginBottom: "25px" }}>
|
||||||
<Typography sx={{ lineHeight: "20px" }}>ФИО:</Typography>
|
<Typography sx={{ lineHeight: "20px" }}>ФИО:</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{user.fullname}
|
Куликов Геннадий Викторович
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ marginBottom: "25px" }}>
|
<Box sx={{ marginBottom: "25px" }}>
|
||||||
@ -69,7 +57,7 @@ export const UserTab = ({ user }: UserTabProps) => {
|
|||||||
Внутренний кошелек
|
Внутренний кошелек
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
<Typography sx={{ lineHeight: "20px", fontWeight: "bold" }}>
|
||||||
{user.walletBalance}
|
2 096 руб.
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,38 +1,155 @@
|
|||||||
import { Box, Typography } from "@mui/material";
|
import { useState, useEffect } from "react";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { Box, Typography, TextField, Button } from "@mui/material";
|
||||||
|
|
||||||
import type { File } from "./index";
|
import { authStore } from "@root/stores/auth";
|
||||||
|
|
||||||
type VerificationTabProps = {
|
import type { ChangeEvent } from "react";
|
||||||
|
|
||||||
|
type File = {
|
||||||
|
name: "inn" | "rule" | "egrule" | "certificate";
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Verification = {
|
||||||
|
_id: string;
|
||||||
|
accepted: boolean;
|
||||||
|
status: "org" | "nko";
|
||||||
|
updated_at: string;
|
||||||
|
comment: string;
|
||||||
files: File[];
|
files: File[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VerificationTab = ({ files }: VerificationTabProps) => (
|
type PatchVerificationBody = {
|
||||||
<Box sx={{ padding: "25px" }}>
|
id: string;
|
||||||
{files.map(({ name, url }, index) => (
|
status: "org" | "nko";
|
||||||
<Box sx={{ marginBottom: "25px" }}>
|
comment: string;
|
||||||
<Typography sx={{ fontWeight: "bold", fontSize: "18px" }}>
|
accepted: boolean;
|
||||||
{index + 1}.{" "}
|
};
|
||||||
{name === "inn"
|
|
||||||
? "Скан ИНН организации (выписка из ЕГЮРЛ)"
|
const baseUrl =
|
||||||
: name === "rule"
|
process.env.NODE_ENV === "production" ? "" : "https://hub.pena.digital";
|
||||||
? "Устав организации"
|
|
||||||
: name === "certificate"
|
export const VerificationTab = () => {
|
||||||
? "Свидетельство о регистрации НКО"
|
const [user, setUser] = useState<Verification | null>(null);
|
||||||
: `Скан документа ${index + 1}`}
|
const [comment, setComment] = useState<string>("");
|
||||||
</Typography>
|
const { userId } = useParams();
|
||||||
<Typography>
|
const { makeRequest } = authStore();
|
||||||
<a
|
|
||||||
style={{
|
const requestVefification = async () =>
|
||||||
color: "#7E2AEA",
|
makeRequest<never, Verification>({
|
||||||
textDecoration: "none",
|
method: "get",
|
||||||
fontSize: "18px",
|
url: baseUrl + `/verification/verification/${userId}`,
|
||||||
}}
|
}).then((verification) => {
|
||||||
href={url}
|
setUser(verification);
|
||||||
|
setComment(verification.comment);
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
requestVefification();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const verify = async (accepted: boolean) => {
|
||||||
|
if (!user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await makeRequest<PatchVerificationBody, never>({
|
||||||
|
method: "patch",
|
||||||
|
useToken: true,
|
||||||
|
url: baseUrl + `/verification/verification`,
|
||||||
|
body: {
|
||||||
|
accepted,
|
||||||
|
comment,
|
||||||
|
id: user._id,
|
||||||
|
status: user.status,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await requestVefification();
|
||||||
|
} catch {}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box sx={{ padding: "25px" }}>
|
||||||
|
<Typography
|
||||||
|
sx={{
|
||||||
|
marginBottom: "10px",
|
||||||
|
fontWeight: "bold",
|
||||||
|
color: user?.accepted ? "#0D9F00" : "#E02C2C",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{user?.accepted ? "Верификация пройдена" : "Не верифицирован"}
|
||||||
|
</Typography>
|
||||||
|
{user?.files?.map(({ name, url }, index) => (
|
||||||
|
<Box sx={{ marginBottom: "25px" }} key={name + url}>
|
||||||
|
<Typography sx={{ fontWeight: "bold", fontSize: "18px" }}>
|
||||||
|
{index + 1}.{" "}
|
||||||
|
{name === "inn"
|
||||||
|
? "Скан ИНН организации (выписка из ЕГЮРЛ)"
|
||||||
|
: name === "rule"
|
||||||
|
? "Устав организации"
|
||||||
|
: name === "certificate"
|
||||||
|
? "Свидетельство о регистрации НКО"
|
||||||
|
: `Скан документа ${index + 1}`}
|
||||||
|
</Typography>
|
||||||
|
<Typography>
|
||||||
|
<a
|
||||||
|
style={{
|
||||||
|
color: "#7E2AEA",
|
||||||
|
textDecoration: "none",
|
||||||
|
fontSize: "18px",
|
||||||
|
}}
|
||||||
|
href={url}
|
||||||
|
>
|
||||||
|
{url.split("/").pop()?.split(".")?.[0]}
|
||||||
|
</a>
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
{user?.comment && (
|
||||||
|
<Box sx={{ marginBottom: "15px" }}>
|
||||||
|
<Typography
|
||||||
|
component="span"
|
||||||
|
sx={{ fontWeight: "bold", marginBottom: "10px" }}
|
||||||
>
|
>
|
||||||
{url.split("/").pop()?.split(".")?.[0]}
|
Комментарий:
|
||||||
</a>
|
</Typography>
|
||||||
</Typography>
|
<Typography component="span"> {user.comment}</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<TextField
|
||||||
|
multiline
|
||||||
|
value={comment}
|
||||||
|
rows={4}
|
||||||
|
label="Комментарий"
|
||||||
|
type=""
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
maxWidth: "500px",
|
||||||
|
marginBottom: "10px",
|
||||||
|
}}
|
||||||
|
onChange={(event: ChangeEvent<HTMLTextAreaElement>) =>
|
||||||
|
setComment(event.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<Box sx={{ display: "flex", columnGap: "10px" }}>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
sx={{ background: "#9A9AAF" }}
|
||||||
|
onClick={() => verify(false)}
|
||||||
|
>
|
||||||
|
Отклонить
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="text"
|
||||||
|
sx={{ background: "#9A9AAF" }}
|
||||||
|
onClick={() => verify(true)}
|
||||||
|
>
|
||||||
|
Подтвердить
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
</Box>
|
||||||
</Box>
|
);
|
||||||
);
|
};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useState } from "react";
|
||||||
import { useLinkClickHandler, useParams } from "react-router-dom";
|
import { useLinkClickHandler } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Modal,
|
Modal,
|
||||||
@ -17,8 +17,6 @@ import { PurchaseTab } from "./PurchaseTab";
|
|||||||
import { TransactionsTab } from "./TransactionsTab";
|
import { TransactionsTab } from "./TransactionsTab";
|
||||||
import { VerificationTab } from "./VerificationTab";
|
import { VerificationTab } from "./VerificationTab";
|
||||||
|
|
||||||
import { authStore } from "@root/stores/auth";
|
|
||||||
|
|
||||||
import userIcon from "@root/assets/icons/user.svg";
|
import userIcon from "@root/assets/icons/user.svg";
|
||||||
import packageIcon from "@root/assets/icons/package.svg";
|
import packageIcon from "@root/assets/icons/package.svg";
|
||||||
import transactionsIcon from "@root/assets/icons/transactions.svg";
|
import transactionsIcon from "@root/assets/icons/transactions.svg";
|
||||||
@ -34,40 +32,13 @@ const TABS = [
|
|||||||
{ name: "Верификация", icon: checkIcon },
|
{ name: "Верификация", icon: checkIcon },
|
||||||
];
|
];
|
||||||
|
|
||||||
const baseUrl =
|
|
||||||
process.env.NODE_ENV === "production" ? "" : "https://hub.pena.digital";
|
|
||||||
|
|
||||||
export type File = {
|
|
||||||
name: "inn" | "rule" | "egrule" | "certificate";
|
|
||||||
url: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Verification = {
|
|
||||||
_id: string;
|
|
||||||
accepted: boolean;
|
|
||||||
status: "org" | "nko";
|
|
||||||
updated_at: string;
|
|
||||||
comment: string;
|
|
||||||
files: File[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const ModalUser = () => {
|
const ModalUser = () => {
|
||||||
const [user, setUser] = useState<Verification | null>(null);
|
|
||||||
const [value, setValue] = useState<number>(0);
|
const [value, setValue] = useState<number>(0);
|
||||||
const [openNavigation, setOpenNavigation] = useState<boolean>(false);
|
const [openNavigation, setOpenNavigation] = useState<boolean>(false);
|
||||||
const { userId } = useParams();
|
|
||||||
const { makeRequest } = authStore();
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const tablet = useMediaQuery(theme.breakpoints.down(1070));
|
const tablet = useMediaQuery(theme.breakpoints.down(1070));
|
||||||
const mobile = useMediaQuery(theme.breakpoints.down(700));
|
const mobile = useMediaQuery(theme.breakpoints.down(700));
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
makeRequest<never, Verification>({
|
|
||||||
method: "get",
|
|
||||||
url: baseUrl + `/verification/verification/${userId}`,
|
|
||||||
}).then(setUser);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal
|
<Modal
|
||||||
@ -98,7 +69,7 @@ const ModalUser = () => {
|
|||||||
boxShadow: 24,
|
boxShadow: 24,
|
||||||
borderRadius: mobile ? "0" : "12px",
|
borderRadius: mobile ? "0" : "12px",
|
||||||
outline: "none",
|
outline: "none",
|
||||||
overflow: "hidden",
|
overflowX: "hidden",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography
|
<Typography
|
||||||
@ -192,22 +163,10 @@ const ModalUser = () => {
|
|||||||
boxShadow: "inset 30px 0px 40px 0px rgba(210, 208, 225, 0.2)",
|
boxShadow: "inset 30px 0px 40px 0px rgba(210, 208, 225, 0.2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{value === 0 && (
|
{value === 0 && <UserTab />}
|
||||||
<UserTab
|
|
||||||
user={{
|
|
||||||
id: 2810,
|
|
||||||
registrationDate: "17.02.2023",
|
|
||||||
email: "emailexamle@gmail.com",
|
|
||||||
phone: "+7 123 456 78 90",
|
|
||||||
type: "НКО",
|
|
||||||
fullname: "Куликов Геннадий Викторович",
|
|
||||||
walletBalance: "2 096 руб.",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{value === 1 && <PurchaseTab />}
|
{value === 1 && <PurchaseTab />}
|
||||||
{value === 2 && <TransactionsTab />}
|
{value === 2 && <TransactionsTab />}
|
||||||
{value === 3 && <VerificationTab files={user?.files || []} />}
|
{value === 3 && <VerificationTab />}
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
10
src/utils/scrollBlock.ts
Normal file
10
src/utils/scrollBlock.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
type Coordinates = {
|
||||||
|
top?: number;
|
||||||
|
left?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const scrollBlock = (
|
||||||
|
block: Element,
|
||||||
|
coordinates: Coordinates,
|
||||||
|
smooth = true
|
||||||
|
) => block.scroll({ ...coordinates, behavior: smooth ? "smooth" : "auto" });
|
Loading…
Reference in New Issue
Block a user