add prettier for formatting to project

This commit is contained in:
2025-07-28 12:18:27 +03:30
parent 1a6cb32528
commit 3a36561ab0
180 changed files with 15437 additions and 14748 deletions

View File

@@ -5,56 +5,49 @@ import { LocalizationProvider, MobileDatePicker } from "@mui/x-date-pickers";
import { IconButton, InputAdornment } from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
const CustomDatePicker = ({
dateValue,
setDateValue,
placeholder = "انتخاب تاریخ",
size = "small",
}) => {
const handleDateChange = (newValue) => {
setDateValue(newValue);
};
const CustomDatePicker = ({ dateValue, setDateValue, placeholder = "انتخاب تاریخ", size = "small" }) => {
const handleDateChange = (newValue) => {
setDateValue(newValue);
};
return (
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={
faIR.components.MuiLocalizationProvider.defaultProps.localeText
}
>
<MobileDatePicker
value={dateValue || null}
onChange={handleDateChange}
slotProps={{
textField: {
size: size,
placeholder: placeholder,
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size={size}
onClick={(event) => {
event.stopPropagation();
setDateValue(null);
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
},
}}
>
<ClearIcon />
</IconButton>
</InputAdornment>
),
},
},
}}
></MobileDatePicker>
</LocalizationProvider>
);
return (
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
>
<MobileDatePicker
value={dateValue || null}
onChange={handleDateChange}
slotProps={{
textField: {
size: size,
placeholder: placeholder,
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size={size}
onClick={(event) => {
event.stopPropagation();
setDateValue(null);
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
},
}}
>
<ClearIcon />
</IconButton>
</InputAdornment>
),
},
},
}}
></MobileDatePicker>
</LocalizationProvider>
);
};
export default CustomDatePicker;

View File

@@ -11,189 +11,169 @@ import { FA_DATATABLE_LOCALIZATION } from "./localization/fa/datatable";
import DataTable_Paper from "./table/Paper";
const rowSelectionReducer = (state, action) => {
switch (action.type) {
case "TOGGLE_ROW":
return { [action.payload]: true };
case "RESET":
return {};
default:
return state;
}
switch (action.type) {
case "TOGGLE_ROW":
return { [action.payload]: true };
case "RESET":
return {};
default:
return state;
}
};
const DataTable_Main = (props) => {
const request = useRequest();
const [rowSelection, dispatchRowSelection] = useReducer(
rowSelectionReducer,
{},
);
const { filterData, sortData, setSortData, hideData } = useDataTable();
const {
need_filter,
table_url,
user_id,
page_name,
table_name,
columns,
initialStateProps,
TableToolbar,
table_title,
RowActions,
specific_data,
specialFilter,
} = props;
const flatColumns = flattenArrayOfObjects(columns, "columns");
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
const [totalRowCount, setTotalRowCount] = useState(0);
const flattenHideData = flattenObjectOfObjects(hideData);
const onSortingChange = (event) => {
setSortData(event);
};
const request = useRequest();
const [rowSelection, dispatchRowSelection] = useReducer(rowSelectionReducer, {});
const { filterData, sortData, setSortData, hideData } = useDataTable();
const {
need_filter,
table_url,
user_id,
page_name,
table_name,
columns,
initialStateProps,
TableToolbar,
table_title,
RowActions,
specific_data,
specialFilter,
} = props;
const flatColumns = flattenArrayOfObjects(columns, "columns");
const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 });
const [totalRowCount, setTotalRowCount] = useState(0);
const flattenHideData = flattenObjectOfObjects(hideData);
const onSortingChange = (event) => {
setSortData(event);
};
const fetchUrl = useCallback(() => {
const params = new URLSearchParams();
params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
params.set("size", pagination.pageSize);
if (specialFilter) {
const filteredSpecialFilterData = Object.values(specialFilter).filter(
(filter) => !isArrayEmpty(filter.value),
);
params.set("filters", JSON.stringify(filteredSpecialFilterData || []));
} else {
const filteredFilterData = DataTableFilterDataStructure(
filterData,
isArrayEmpty,
);
params.set(
"filters",
JSON.stringify(
filteredFilterData.length === 0 ? [] : filteredFilterData,
const fetchUrl = useCallback(() => {
const params = new URLSearchParams();
params.set("start", `${pagination.pageIndex * pagination.pageSize}`);
params.set("size", pagination.pageSize);
if (specialFilter) {
const filteredSpecialFilterData = Object.values(specialFilter).filter(
(filter) => !isArrayEmpty(filter.value)
);
params.set("filters", JSON.stringify(filteredSpecialFilterData || []));
} else {
const filteredFilterData = DataTableFilterDataStructure(filterData, isArrayEmpty);
params.set("filters", JSON.stringify(filteredFilterData.length === 0 ? [] : filteredFilterData));
}
params.set(
"sorting",
JSON.stringify(
Object.values(sortData).map(({ id, ...rest }) => ({
...rest,
id: id.replace(/__/g, "."),
}))
)
);
return `${table_url}?${params}`;
}, [table_url, filterData, pagination, sortData, specialFilter]);
const fetcher = async (url) => {
try {
const response = await request(url);
setTotalRowCount(response.data?.meta?.totalRowCount);
if (specific_data) {
return specific_data(response.data);
} else {
return response.data?.data;
}
} catch (error) {
throw error;
}
};
const { data, isValidating, mutate } = useSWR(props.data ? "" : fetchUrl(), fetcher, {
revalidateIfStale: true,
revalidateOnFocus: false,
revalidateOnReconnect: true,
keepPreviousData: true,
});
useEffect(() => {
if (!isValidating) return;
dispatchRowSelection({ type: "RESET" });
}, [isValidating]);
const table = useMaterialReactTable({
localization: FA_DATATABLE_LOCALIZATION,
columns,
data: data ?? [],
muiTableBodyRowProps: ({ row }) => ({
onClick: () => dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }),
selected: !!rowSelection[row.id],
}),
initialState: {
density: "compact",
columnVisibility: flattenHideData,
sorting: sortData,
...initialStateProps,
},
state: {
showProgressBars: isValidating || props.loading,
columnVisibility: flattenHideData,
sorting: sortData,
pagination,
rowSelection,
},
muiTableHeadProps: {
sx: {
borderTop: "1px solid #e1e1e1",
borderBottom: "2px solid #e1e1e1",
},
},
muiTableHeadCellProps: {
sx: {
color: "primary.main",
borderLeft: "1px solid #e1e1e1",
"&:first-of-type": {
borderLeft: "unset",
},
},
},
muiTableBodyCellProps: {
sx: {
borderLeft: "1px solid #e1e1e1",
"&:first-of-type": {
borderLeft: "unset",
},
},
},
manualFiltering: true,
manualPagination: true,
manualSorting: true,
onPaginationChange: setPagination,
onSortingChange: onSortingChange,
rowCount: totalRowCount,
renderTopToolbarCustomActions: ({ table }) => (
<>
{TableToolbar && (
<TableToolbar table={table} mutate={mutate} filterData={specialFilter || filterData} />
)}
</>
),
);
}
params.set(
"sorting",
JSON.stringify(
Object.values(sortData).map(({ id, ...rest }) => ({
...rest,
id: id.replace(/__/g, "."),
})),
),
);
return `${table_url}?${params}`;
}, [table_url, filterData, pagination, sortData, specialFilter]);
renderRowActions: ({ row }) => <RowActions row={row} mutate={mutate} />,
...props,
});
const fetcher = async (url) => {
try {
const response = await request(url);
setTotalRowCount(response.data?.meta?.totalRowCount);
if (specific_data) {
return specific_data(response.data);
} else {
return response.data?.data;
}
} catch (error) {
throw error;
}
};
const { data, isValidating, mutate } = useSWR(
props.data ? "" : fetchUrl(),
fetcher,
{
revalidateIfStale: true,
revalidateOnFocus: false,
revalidateOnReconnect: true,
keepPreviousData: true,
},
);
useEffect(() => {
if (!isValidating) return;
dispatchRowSelection({ type: "RESET" });
}, [isValidating]);
const table = useMaterialReactTable({
localization: FA_DATATABLE_LOCALIZATION,
columns,
data: data ?? [],
muiTableBodyRowProps: ({ row }) => ({
onClick: () =>
dispatchRowSelection({ type: "TOGGLE_ROW", payload: row.id }),
selected: !!rowSelection[row.id],
}),
initialState: {
density: "compact",
columnVisibility: flattenHideData,
sorting: sortData,
...initialStateProps,
},
state: {
showProgressBars: isValidating || props.loading,
columnVisibility: flattenHideData,
sorting: sortData,
pagination,
rowSelection,
},
muiTableHeadProps: {
sx: {
borderTop: "1px solid #e1e1e1",
borderBottom: "2px solid #e1e1e1",
},
},
muiTableHeadCellProps: {
sx: {
color: "primary.main",
borderLeft: "1px solid #e1e1e1",
"&:first-of-type": {
borderLeft: "unset",
},
},
},
muiTableBodyCellProps: {
sx: {
borderLeft: "1px solid #e1e1e1",
"&:first-of-type": {
borderLeft: "unset",
},
},
},
manualFiltering: true,
manualPagination: true,
manualSorting: true,
onPaginationChange: setPagination,
onSortingChange: onSortingChange,
rowCount: totalRowCount,
renderTopToolbarCustomActions: ({ table }) => (
<>
{TableToolbar && (
<TableToolbar
return (
<DataTable_Paper
table={table}
table_title={table_title}
need_filter={need_filter}
mutate={mutate}
filterData={specialFilter || filterData}
/>
)}
</>
),
renderRowActions: ({ row }) => <RowActions row={row} mutate={mutate} />,
...props,
});
return (
<DataTable_Paper
table={table}
table_title={table_title}
need_filter={need_filter}
mutate={mutate}
table_url={table_url}
columns={flatColumns}
user_id={user_id}
page_name={page_name}
table_name={table_name}
special_data={props.data}
special_filter={specialFilter}
setFilterData={props.setFilterData}
/>
);
table_url={table_url}
columns={flatColumns}
user_id={user_id}
page_name={page_name}
table_name={table_name}
special_data={props.data}
special_filter={specialFilter}
setFilterData={props.setFilterData}
/>
);
};
export default DataTable_Main;

View File

@@ -2,200 +2,190 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils";
import { TableBody, Typography } from "@mui/material";
import { useMRT_RowVirtualizer, useMRT_Rows } from "material-react-table";
import { memo, useMemo } from "react";
import DataTable_TableBodyRow, {
Memo_DataTable_TableBodyRow,
} from "./TableBodyRow";
import DataTable_TableBodyRow, { Memo_DataTable_TableBodyRow } from "./TableBodyRow";
const DataTable_TableBody = ({ columnVirtualizer, table, ...rest }) => {
const {
getBottomRows,
getIsSomeRowsPinned,
getRowModel,
getState,
getTopRows,
options: {
enableStickyFooter,
enableStickyHeader,
layoutMode,
localization,
memoMode,
muiTableBodyProps,
renderDetailPanel,
renderEmptyRowsFallback,
rowPinningDisplayMode,
},
refs: { tableFooterRef, tableHeadRef, tablePaperRef },
} = table;
const { columnFilters, globalFilter, isFullScreen, rowPinning } = getState();
const {
getBottomRows,
getIsSomeRowsPinned,
getRowModel,
getState,
getTopRows,
options: {
enableStickyFooter,
enableStickyHeader,
layoutMode,
localization,
memoMode,
muiTableBodyProps,
renderDetailPanel,
renderEmptyRowsFallback,
rowPinningDisplayMode,
},
refs: { tableFooterRef, tableHeadRef, tablePaperRef },
} = table;
const { columnFilters, globalFilter, isFullScreen, rowPinning } = getState();
const tableBodyProps = {
...parseFromValuesOrFunc(muiTableBodyProps, { table }),
...rest,
};
const tableBodyProps = {
...parseFromValuesOrFunc(muiTableBodyProps, { table }),
...rest,
};
const tableHeadHeight =
((enableStickyHeader || isFullScreen) &&
tableHeadRef.current?.clientHeight) ||
0;
const tableFooterHeight =
(enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0;
const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
const pinnedRowIds = useMemo(() => {
if (!rowPinning.bottom?.length && !rowPinning.top?.length) return [];
return getRowModel()
.rows.filter((row) => row.getIsPinned())
.map((r) => r.id);
}, [rowPinning, getRowModel().rows]);
const pinnedRowIds = useMemo(() => {
if (!rowPinning.bottom?.length && !rowPinning.top?.length) return [];
return getRowModel()
.rows.filter((row) => row.getIsPinned())
.map((r) => r.id);
}, [rowPinning, getRowModel().rows]);
const rows = useMRT_Rows(table);
const rows = useMRT_Rows(table);
const rowVirtualizer = useMRT_RowVirtualizer(table, rows);
const rowVirtualizer = useMRT_RowVirtualizer(table, rows);
const { virtualRows } = rowVirtualizer ?? {};
const { virtualRows } = rowVirtualizer ?? {};
const commonRowProps = {
columnVirtualizer,
numRows: rows.length,
table,
};
const commonRowProps = {
columnVirtualizer,
numRows: rows.length,
table,
};
return (
<>
{!rowPinningDisplayMode?.includes("sticky") &&
getIsSomeRowsPinned("top") && (
<TableBody
{...tableBodyProps}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
position: "sticky",
top: tableHeadHeight - 1,
zIndex: 1,
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
})}
>
{getTopRows().map((row, staticRowIndex) => {
const props = {
...commonRowProps,
row,
staticRowIndex,
};
return memoMode === "rows" ? (
<Memo_DataTable_TableBodyRow key={row.id} {...props} />
) : (
<DataTable_TableBodyRow key={row.id} {...props} />
);
})}
</TableBody>
)}
<TableBody
{...tableBodyProps}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
height: rowVirtualizer
? `${rowVirtualizer.getTotalSize()}px`
: undefined,
minHeight: !rows.length ? "100px" : undefined,
position: "relative",
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
})}
>
{tableBodyProps?.children ??
(!rows.length ? (
<tr
style={{
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
}}
return (
<>
{!rowPinningDisplayMode?.includes("sticky") && getIsSomeRowsPinned("top") && (
<TableBody
{...tableBodyProps}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
position: "sticky",
top: tableHeadHeight - 1,
zIndex: 1,
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
})}
>
{getTopRows().map((row, staticRowIndex) => {
const props = {
...commonRowProps,
row,
staticRowIndex,
};
return memoMode === "rows" ? (
<Memo_DataTable_TableBodyRow key={row.id} {...props} />
) : (
<DataTable_TableBodyRow key={row.id} {...props} />
);
})}
</TableBody>
)}
<TableBody
{...tableBodyProps}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
height: rowVirtualizer ? `${rowVirtualizer.getTotalSize()}px` : undefined,
minHeight: !rows.length ? "100px" : undefined,
position: "relative",
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
})}
>
<td
colSpan={table.getVisibleLeafColumns().length}
style={{
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
}}
>
{renderEmptyRowsFallback?.({ table }) ?? (
<Typography
sx={{
color: "text.secondary",
fontStyle: "italic",
maxWidth: `min(100vw, ${tablePaperRef.current?.clientWidth ?? 360}px)`,
py: "2rem",
textAlign: "center",
width: "100%",
}}
>
{globalFilter || columnFilters.length
? localization.noResultsFound
: localization.noRecordsToDisplay}
</Typography>
)}
</td>
</tr>
) : (
<>
{(virtualRows ?? rows).map((rowOrVirtualRow, staticRowIndex) => {
let row = rowOrVirtualRow;
if (rowVirtualizer) {
if (renderDetailPanel) {
if (rowOrVirtualRow.index % 2 === 1) {
return null;
} else {
staticRowIndex = rowOrVirtualRow.index / 2;
}
} else {
staticRowIndex = rowOrVirtualRow.index;
}
row = rows[staticRowIndex];
}
const props = {
...commonRowProps,
pinnedRowIds,
row,
rowVirtualizer,
staticRowIndex,
virtualRow: rowVirtualizer ? rowOrVirtualRow : undefined,
};
const key = `${row.id}-${row.index}`;
return memoMode === "rows" ? (
<Memo_DataTable_TableBodyRow key={key} {...props} />
) : (
<DataTable_TableBodyRow key={key} {...props} />
);
})}
</>
))}
</TableBody>
{!rowPinningDisplayMode?.includes("sticky") &&
getIsSomeRowsPinned("bottom") && (
<TableBody
{...tableBodyProps}
sx={(theme) => ({
bottom: tableFooterHeight - 1,
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
position: "sticky",
zIndex: 1,
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
})}
>
{getBottomRows().map((row, staticRowIndex) => {
const props = {
...commonRowProps,
row,
staticRowIndex,
};
return memoMode === "rows" ? (
<Memo_DataTable_TableBodyRow key={row.id} {...props} />
) : (
<DataTable_TableBodyRow key={row.id} {...props} />
);
})}
</TableBody>
)}
</>
);
{tableBodyProps?.children ??
(!rows.length ? (
<tr
style={{
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
}}
>
<td
colSpan={table.getVisibleLeafColumns().length}
style={{
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
}}
>
{renderEmptyRowsFallback?.({ table }) ?? (
<Typography
sx={{
color: "text.secondary",
fontStyle: "italic",
maxWidth: `min(100vw, ${tablePaperRef.current?.clientWidth ?? 360}px)`,
py: "2rem",
textAlign: "center",
width: "100%",
}}
>
{globalFilter || columnFilters.length
? localization.noResultsFound
: localization.noRecordsToDisplay}
</Typography>
)}
</td>
</tr>
) : (
<>
{(virtualRows ?? rows).map((rowOrVirtualRow, staticRowIndex) => {
let row = rowOrVirtualRow;
if (rowVirtualizer) {
if (renderDetailPanel) {
if (rowOrVirtualRow.index % 2 === 1) {
return null;
} else {
staticRowIndex = rowOrVirtualRow.index / 2;
}
} else {
staticRowIndex = rowOrVirtualRow.index;
}
row = rows[staticRowIndex];
}
const props = {
...commonRowProps,
pinnedRowIds,
row,
rowVirtualizer,
staticRowIndex,
virtualRow: rowVirtualizer ? rowOrVirtualRow : undefined,
};
const key = `${row.id}-${row.index}`;
return memoMode === "rows" ? (
<Memo_DataTable_TableBodyRow key={key} {...props} />
) : (
<DataTable_TableBodyRow key={key} {...props} />
);
})}
</>
))}
</TableBody>
{!rowPinningDisplayMode?.includes("sticky") && getIsSomeRowsPinned("bottom") && (
<TableBody
{...tableBodyProps}
sx={(theme) => ({
bottom: tableFooterHeight - 1,
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
position: "sticky",
zIndex: 1,
...parseFromValuesOrFunc(tableBodyProps?.sx, theme),
})}
>
{getBottomRows().map((row, staticRowIndex) => {
const props = {
...commonRowProps,
row,
staticRowIndex,
};
return memoMode === "rows" ? (
<Memo_DataTable_TableBodyRow key={row.id} {...props} />
) : (
<DataTable_TableBodyRow key={row.id} {...props} />
);
})}
</TableBody>
)}
</>
);
};
export default DataTable_TableBody;
export const Memo_DataTable_TableBody = memo(
DataTable_TableBody,
(prev, next) => prev.table.options.data === next.table.options.data,
DataTable_TableBody,
(prev, next) => prev.table.options.data === next.table.options.data
);

View File

@@ -1,7 +1,4 @@
import {
getCommonMRTCellStyles,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
import { useTheme } from "@emotion/react";
import { Skeleton, TableCell } from "@mui/material";
import { isCellEditable, openEditingCell } from "material-react-table";
@@ -9,300 +6,250 @@ import { memo, useEffect, useMemo, useState } from "react";
import DataTable_CopyButton from "../buttons/CopyButton";
import DataTable_TableBodyCellValue from "./TableBodyCellValue";
const DataTable_TableBodyCell = ({
cell,
numRows,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
...rest
}) => {
const theme = useTheme();
const {
getState,
options: {
columnResizeDirection,
columnResizeMode,
createDisplayMode,
editDisplayMode,
enableCellActions,
enableClickToCopy,
enableColumnOrdering,
enableColumnPinning,
enableGrouping,
layoutMode,
mrtTheme: { draggingBorderColor, baseBackgroundColor },
muiSkeletonProps,
muiTableBodyCellProps,
},
setHoveredColumn,
} = table;
const {
actionCell,
columnSizingInfo,
creatingRow,
density,
draggingColumn,
draggingRow,
editingCell,
editingRow,
hoveredColumn,
hoveredRow,
isLoading,
showSkeletons,
} = getState();
const { column, row } = cell;
const { columnDef } = column;
const { columnDefType } = columnDef;
const args = { cell, column, row, table };
const tableCellProps = {
...parseFromValuesOrFunc(muiTableBodyCellProps, args),
...parseFromValuesOrFunc(columnDef.muiTableBodyCellProps, args),
...rest,
};
const skeletonProps = parseFromValuesOrFunc(muiSkeletonProps, {
cell,
column,
row,
table,
});
const [skeletonWidth, setSkeletonWidth] = useState(100);
useEffect(() => {
if ((!isLoading && !showSkeletons) || skeletonWidth !== 100) return;
const size = column.getSize();
setSkeletonWidth(
columnDefType === "display"
? size / 2
: Math.round(Math.random() * (size - size / 3) + size / 3),
);
}, [isLoading, showSkeletons]);
const draggingBorders = useMemo(() => {
const isDraggingColumn = draggingColumn?.id === column.id;
const isHoveredColumn = hoveredColumn?.id === column.id;
const isDraggingRow = draggingRow?.id === row.id;
const isHoveredRow = hoveredRow?.id === row.id;
const isFirstColumn = column.getIsFirstColumn();
const isLastColumn = column.getIsLastColumn();
const isLastRow = numRows && staticRowIndex === numRows - 1;
const isResizingColumn = columnSizingInfo.isResizingColumn === column.id;
const showResizeBorder =
isResizingColumn && columnResizeMode === "onChange";
const borderStyle = showResizeBorder
? `2px solid ${draggingBorderColor} !important`
: isDraggingColumn || isDraggingRow
? `1px dashed ${theme.palette.grey[500]} !important`
: isHoveredColumn || isHoveredRow || isResizingColumn
? `2px dashed ${draggingBorderColor} !important`
: undefined;
if (showResizeBorder) {
return columnResizeDirection === "ltr"
? { borderRight: borderStyle }
: { borderLeft: borderStyle };
}
return borderStyle
? {
borderBottom:
isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn)
? borderStyle
: undefined,
borderLeft:
isDraggingColumn ||
isHoveredColumn ||
((isDraggingRow || isHoveredRow) && isFirstColumn)
? borderStyle
: undefined,
borderRight:
isDraggingColumn ||
isHoveredColumn ||
((isDraggingRow || isHoveredRow) && isLastColumn)
? borderStyle
: undefined,
borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined,
}
: undefined;
}, [
columnSizingInfo.isResizingColumn,
draggingColumn,
draggingRow,
hoveredColumn,
hoveredRow,
staticRowIndex,
]);
const isColumnPinned =
enableColumnPinning &&
columnDef.columnDefType !== "group" &&
column.getIsPinned();
const isEditable = isCellEditable({ cell, table });
const isEditing =
isEditable &&
!["custom", "modal"].includes(editDisplayMode) &&
(editDisplayMode === "table" ||
editingRow?.id === row.id ||
editingCell?.id === cell.id) &&
!row.getIsGrouped();
const isCreating =
isEditable && createDisplayMode === "row" && creatingRow?.id === row.id;
const showClickToCopyButton =
(parseFromValuesOrFunc(enableClickToCopy, cell) === true ||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === true) &&
!["context-menu", false].includes(
// @ts-ignore
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell),
);
const isRightClickable = parseFromValuesOrFunc(enableCellActions, cell);
const cellValueProps = {
cell,
table,
};
const handleDoubleClick = (event) => {
tableCellProps?.onDoubleClick?.(event);
openEditingCell({ cell, table });
};
const handleDragEnter = (e) => {
tableCellProps?.onDragEnter?.(e);
if (enableGrouping && hoveredColumn?.id === "drop-zone") {
setHoveredColumn(null);
}
if (enableColumnOrdering && draggingColumn) {
setHoveredColumn(
columnDef.enableColumnOrdering !== false ? column : null,
);
}
};
const handleDragOver = (e) => {
if (columnDef.enableColumnOrdering !== false) {
e.preventDefault();
}
};
const handleContextMenu = (e) => {
tableCellProps?.onContextMenu?.(e);
if (isRightClickable) {
e.preventDefault();
table.setActionCell(cell);
table.refs.actionCellRef.current = e.currentTarget;
}
};
return (
<TableCell
data-index={staticColumnIndex}
data-pinned={!!isColumnPinned || undefined}
{...tableCellProps}
onContextMenu={handleContextMenu}
onDoubleClick={handleDoubleClick}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
sx={(theme) => ({
"&:hover": {
outline:
actionCell?.id === cell.id ||
(editDisplayMode === "cell" && isEditable) ||
(editDisplayMode === "table" && (isCreating || isEditing))
? `1px solid ${theme.palette.grey[500]}`
: undefined,
textOverflow: "clip",
const DataTable_TableBodyCell = ({ cell, numRows, rowRef, staticColumnIndex, staticRowIndex, table, ...rest }) => {
const theme = useTheme();
const {
getState,
options: {
columnResizeDirection,
columnResizeMode,
createDisplayMode,
editDisplayMode,
enableCellActions,
enableClickToCopy,
enableColumnOrdering,
enableColumnPinning,
enableGrouping,
layoutMode,
mrtTheme: { draggingBorderColor, baseBackgroundColor },
muiSkeletonProps,
muiTableBodyCellProps,
},
alignItems: layoutMode?.startsWith("grid") ? "center" : undefined,
cursor: isRightClickable
? "context-menu"
: isEditable && editDisplayMode === "cell"
? "pointer"
: "inherit",
outline:
actionCell?.id === cell.id
? `1px solid ${theme.palette.grey[500]}`
: undefined,
outlineOffset: "-1px",
overflow: "hidden",
p:
density === "compact"
? columnDefType === "display"
? "0 0.5rem"
: "0.5rem"
: density === "comfortable"
? columnDefType === "display"
? "0.5rem 0.75rem"
: "1rem"
: columnDefType === "display"
? "1rem 1.25rem"
: "1.5rem",
setHoveredColumn,
} = table;
const {
actionCell,
columnSizingInfo,
creatingRow,
density,
draggingColumn,
draggingRow,
editingCell,
editingRow,
hoveredColumn,
hoveredRow,
isLoading,
showSkeletons,
} = getState();
const { column, row } = cell;
const { columnDef } = column;
const { columnDefType } = columnDef;
textOverflow: columnDefType !== "display" ? "ellipsis" : undefined,
whiteSpace:
row.getIsPinned() || density === "compact" ? "nowrap" : "normal",
...getCommonMRTCellStyles({
column,
table,
tableCellProps,
theme,
}),
...draggingBorders,
backgroundColor: baseBackgroundColor,
})}
>
{tableCellProps.children ?? (
<>
{cell.getIsPlaceholder() ? (
(columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null)
) : showSkeletons !== false && (isLoading || showSkeletons) ? (
<Skeleton
animation="wave"
height={20}
width={skeletonWidth}
{...skeletonProps}
/>
) : columnDefType === "display" &&
(["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(
column.id,
) ||
!row.getIsGrouped()) ? (
columnDef.Cell?.({
cell,
column,
renderedCellValue: cell.renderValue(),
row,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
})
) : showClickToCopyButton && columnDef.enableClickToCopy !== false ? (
<DataTable_CopyButton cell={cell} table={table}>
<DataTable_TableBodyCellValue {...cellValueProps} />
</DataTable_CopyButton>
) : (
<DataTable_TableBodyCellValue {...cellValueProps} />
)}
{cell.getIsGrouped() && !columnDef.GroupedCell && (
<> ({row.subRows?.length})</>
)}
</>
)}
</TableCell>
);
const args = { cell, column, row, table };
const tableCellProps = {
...parseFromValuesOrFunc(muiTableBodyCellProps, args),
...parseFromValuesOrFunc(columnDef.muiTableBodyCellProps, args),
...rest,
};
const skeletonProps = parseFromValuesOrFunc(muiSkeletonProps, {
cell,
column,
row,
table,
});
const [skeletonWidth, setSkeletonWidth] = useState(100);
useEffect(() => {
if ((!isLoading && !showSkeletons) || skeletonWidth !== 100) return;
const size = column.getSize();
setSkeletonWidth(
columnDefType === "display" ? size / 2 : Math.round(Math.random() * (size - size / 3) + size / 3)
);
}, [isLoading, showSkeletons]);
const draggingBorders = useMemo(() => {
const isDraggingColumn = draggingColumn?.id === column.id;
const isHoveredColumn = hoveredColumn?.id === column.id;
const isDraggingRow = draggingRow?.id === row.id;
const isHoveredRow = hoveredRow?.id === row.id;
const isFirstColumn = column.getIsFirstColumn();
const isLastColumn = column.getIsLastColumn();
const isLastRow = numRows && staticRowIndex === numRows - 1;
const isResizingColumn = columnSizingInfo.isResizingColumn === column.id;
const showResizeBorder = isResizingColumn && columnResizeMode === "onChange";
const borderStyle = showResizeBorder
? `2px solid ${draggingBorderColor} !important`
: isDraggingColumn || isDraggingRow
? `1px dashed ${theme.palette.grey[500]} !important`
: isHoveredColumn || isHoveredRow || isResizingColumn
? `2px dashed ${draggingBorderColor} !important`
: undefined;
if (showResizeBorder) {
return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle };
}
return borderStyle
? {
borderBottom:
isDraggingRow || isHoveredRow || (isLastRow && !isResizingColumn) ? borderStyle : undefined,
borderLeft:
isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isFirstColumn)
? borderStyle
: undefined,
borderRight:
isDraggingColumn || isHoveredColumn || ((isDraggingRow || isHoveredRow) && isLastColumn)
? borderStyle
: undefined,
borderTop: isDraggingRow || isHoveredRow ? borderStyle : undefined,
}
: undefined;
}, [columnSizingInfo.isResizingColumn, draggingColumn, draggingRow, hoveredColumn, hoveredRow, staticRowIndex]);
const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== "group" && column.getIsPinned();
const isEditable = isCellEditable({ cell, table });
const isEditing =
isEditable &&
!["custom", "modal"].includes(editDisplayMode) &&
(editDisplayMode === "table" || editingRow?.id === row.id || editingCell?.id === cell.id) &&
!row.getIsGrouped();
const isCreating = isEditable && createDisplayMode === "row" && creatingRow?.id === row.id;
const showClickToCopyButton =
(parseFromValuesOrFunc(enableClickToCopy, cell) === true ||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === true) &&
!["context-menu", false].includes(
// @ts-ignore
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell)
);
const isRightClickable = parseFromValuesOrFunc(enableCellActions, cell);
const cellValueProps = {
cell,
table,
};
const handleDoubleClick = (event) => {
tableCellProps?.onDoubleClick?.(event);
openEditingCell({ cell, table });
};
const handleDragEnter = (e) => {
tableCellProps?.onDragEnter?.(e);
if (enableGrouping && hoveredColumn?.id === "drop-zone") {
setHoveredColumn(null);
}
if (enableColumnOrdering && draggingColumn) {
setHoveredColumn(columnDef.enableColumnOrdering !== false ? column : null);
}
};
const handleDragOver = (e) => {
if (columnDef.enableColumnOrdering !== false) {
e.preventDefault();
}
};
const handleContextMenu = (e) => {
tableCellProps?.onContextMenu?.(e);
if (isRightClickable) {
e.preventDefault();
table.setActionCell(cell);
table.refs.actionCellRef.current = e.currentTarget;
}
};
return (
<TableCell
data-index={staticColumnIndex}
data-pinned={!!isColumnPinned || undefined}
{...tableCellProps}
onContextMenu={handleContextMenu}
onDoubleClick={handleDoubleClick}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
sx={(theme) => ({
"&:hover": {
outline:
actionCell?.id === cell.id ||
(editDisplayMode === "cell" && isEditable) ||
(editDisplayMode === "table" && (isCreating || isEditing))
? `1px solid ${theme.palette.grey[500]}`
: undefined,
textOverflow: "clip",
},
alignItems: layoutMode?.startsWith("grid") ? "center" : undefined,
cursor: isRightClickable
? "context-menu"
: isEditable && editDisplayMode === "cell"
? "pointer"
: "inherit",
outline: actionCell?.id === cell.id ? `1px solid ${theme.palette.grey[500]}` : undefined,
outlineOffset: "-1px",
overflow: "hidden",
p:
density === "compact"
? columnDefType === "display"
? "0 0.5rem"
: "0.5rem"
: density === "comfortable"
? columnDefType === "display"
? "0.5rem 0.75rem"
: "1rem"
: columnDefType === "display"
? "1rem 1.25rem"
: "1.5rem",
textOverflow: columnDefType !== "display" ? "ellipsis" : undefined,
whiteSpace: row.getIsPinned() || density === "compact" ? "nowrap" : "normal",
...getCommonMRTCellStyles({
column,
table,
tableCellProps,
theme,
}),
...draggingBorders,
backgroundColor: baseBackgroundColor,
})}
>
{tableCellProps.children ?? (
<>
{cell.getIsPlaceholder() ? (
(columnDef.PlaceholderCell?.({ cell, column, row, table }) ?? null)
) : showSkeletons !== false && (isLoading || showSkeletons) ? (
<Skeleton animation="wave" height={20} width={skeletonWidth} {...skeletonProps} />
) : columnDefType === "display" &&
(["mrt-row-expand", "mrt-row-numbers", "mrt-row-select"].includes(column.id) ||
!row.getIsGrouped()) ? (
columnDef.Cell?.({
cell,
column,
renderedCellValue: cell.renderValue(),
row,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
})
) : showClickToCopyButton && columnDef.enableClickToCopy !== false ? (
<DataTable_CopyButton cell={cell} table={table}>
<DataTable_TableBodyCellValue {...cellValueProps} />
</DataTable_CopyButton>
) : (
<DataTable_TableBodyCellValue {...cellValueProps} />
)}
{cell.getIsGrouped() && !columnDef.GroupedCell && <> ({row.subRows?.length})</>}
</>
)}
</TableCell>
);
};
export default DataTable_TableBodyCell;
export const Memo_DataTable_TableBodyCell = memo(
DataTable_TableBodyCell,
(prev, next) => next.cell === prev.cell,
);
export const Memo_DataTable_TableBodyCell = memo(DataTable_TableBodyCell, (prev, next) => next.cell === prev.cell);

View File

@@ -2,111 +2,102 @@ import { Box } from "@mui/material";
const allowedTypes = ["string", "number"];
const DataTable_TableBodyCellValue = ({
cell,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
}) => {
const {
getState,
options: {
enableFilterMatchHighlighting,
mrtTheme: { matchHighlightColor },
},
} = table;
const { column, row } = cell;
const { columnDef } = column;
const { globalFilter, globalFilterFn } = getState();
const filterValue = column.getFilterValue();
const DataTable_TableBodyCellValue = ({ cell, rowRef, staticColumnIndex, staticRowIndex, table }) => {
const {
getState,
options: {
enableFilterMatchHighlighting,
mrtTheme: { matchHighlightColor },
},
} = table;
const { column, row } = cell;
const { columnDef } = column;
const { globalFilter, globalFilterFn } = getState();
const filterValue = column.getFilterValue();
let renderedCellValue =
cell.getIsAggregated() && columnDef.AggregatedCell
? columnDef.AggregatedCell({
cell,
column,
row,
table,
})
: row.getIsGrouped() && !cell.getIsGrouped()
? null
: cell.getIsGrouped() && columnDef.GroupedCell
? columnDef.GroupedCell({
cell,
column,
row,
table,
})
: undefined;
let renderedCellValue =
cell.getIsAggregated() && columnDef.AggregatedCell
? columnDef.AggregatedCell({
cell,
column,
row,
table,
})
: row.getIsGrouped() && !cell.getIsGrouped()
? null
: cell.getIsGrouped() && columnDef.GroupedCell
? columnDef.GroupedCell({
cell,
column,
row,
table,
})
: undefined;
const isGroupedValue = renderedCellValue !== undefined;
const isGroupedValue = renderedCellValue !== undefined;
if (!isGroupedValue) {
renderedCellValue = cell.renderValue();
}
if (
enableFilterMatchHighlighting &&
columnDef.enableFilterMatchHighlighting !== false &&
String(renderedCellValue) &&
allowedTypes.includes(typeof renderedCellValue) &&
((filterValue &&
allowedTypes.includes(typeof filterValue) &&
["autocomplete", "text"].includes(columnDef.filterVariant)) ||
(globalFilter &&
allowedTypes.includes(typeof globalFilter) &&
column.getCanGlobalFilter()))
) {
const chunks = highlightWords?.({
matchExactly:
(filterValue ? columnDef._filterFn : globalFilterFn) !== "fuzzy",
query: (filterValue ?? globalFilter ?? "").toString(),
text: renderedCellValue?.toString(),
});
if (chunks?.length > 1 || chunks?.[0]?.match) {
renderedCellValue = (
<span aria-label={renderedCellValue} role="note">
{chunks?.map(({ key, match, text }) => (
<Box
aria-hidden="true"
component="span"
key={key}
sx={
match
? {
backgroundColor: matchHighlightColor,
borderRadius: "2px",
color: (theme) =>
theme.palette.mode === "dark"
? theme.palette.common.white
: theme.palette.common.black,
padding: "2px 1px",
}
: undefined
}
>
{text}
</Box>
)) ?? renderedCellValue}
</span>
);
if (!isGroupedValue) {
renderedCellValue = cell.renderValue();
}
}
if (columnDef.Cell && !isGroupedValue) {
renderedCellValue = columnDef.Cell({
cell,
column,
renderedCellValue,
row,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
});
}
if (
enableFilterMatchHighlighting &&
columnDef.enableFilterMatchHighlighting !== false &&
String(renderedCellValue) &&
allowedTypes.includes(typeof renderedCellValue) &&
((filterValue &&
allowedTypes.includes(typeof filterValue) &&
["autocomplete", "text"].includes(columnDef.filterVariant)) ||
(globalFilter && allowedTypes.includes(typeof globalFilter) && column.getCanGlobalFilter()))
) {
const chunks = highlightWords?.({
matchExactly: (filterValue ? columnDef._filterFn : globalFilterFn) !== "fuzzy",
query: (filterValue ?? globalFilter ?? "").toString(),
text: renderedCellValue?.toString(),
});
if (chunks?.length > 1 || chunks?.[0]?.match) {
renderedCellValue = (
<span aria-label={renderedCellValue} role="note">
{chunks?.map(({ key, match, text }) => (
<Box
aria-hidden="true"
component="span"
key={key}
sx={
match
? {
backgroundColor: matchHighlightColor,
borderRadius: "2px",
color: (theme) =>
theme.palette.mode === "dark"
? theme.palette.common.white
: theme.palette.common.black,
padding: "2px 1px",
}
: undefined
}
>
{text}
</Box>
)) ?? renderedCellValue}
</span>
);
}
}
return renderedCellValue;
if (columnDef.Cell && !isGroupedValue) {
renderedCellValue = columnDef.Cell({
cell,
column,
renderedCellValue,
row,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
});
}
return renderedCellValue;
};
export default DataTable_TableBodyCellValue;

View File

@@ -1,258 +1,216 @@
import {
commonCellBeforeAfterStyles,
getCommonPinnedCellStyles,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { commonCellBeforeAfterStyles, getCommonPinnedCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
import { useTheme } from "@emotion/react";
import { TableRow, alpha, darken, lighten } from "@mui/material";
import { getIsRowSelected } from "material-react-table";
import { memo, useMemo, useRef } from "react";
import DataTable_TableBodyCell, {
Memo_DataTable_TableBodyCell,
} from "./TableBodyCell";
import DataTable_TableBodyCell, { Memo_DataTable_TableBodyCell } from "./TableBodyCell";
import DataTable_TableDetailPanel from "./TableDetailPanel";
const DataTable_TableBodyRow = ({
columnVirtualizer,
numRows,
pinnedRowIds,
row,
rowVirtualizer,
staticRowIndex,
table,
virtualRow,
...rest
columnVirtualizer,
numRows,
pinnedRowIds,
row,
rowVirtualizer,
staticRowIndex,
table,
virtualRow,
...rest
}) => {
const theme = useTheme();
const theme = useTheme();
const {
getState,
options: {
enableRowOrdering,
enableRowPinning,
enableStickyFooter,
enableStickyHeader,
layoutMode,
memoMode,
mrtTheme: {
baseBackgroundColor,
pinnedRowBackgroundColor,
selectedRowBackgroundColor,
},
muiTableBodyRowProps,
renderDetailPanel,
rowPinningDisplayMode,
},
refs: { tableFooterRef, tableHeadRef },
setHoveredRow,
} = table;
const {
density,
draggingColumn,
draggingRow,
editingCell,
editingRow,
hoveredRow,
isFullScreen,
rowPinning,
} = getState();
const {
getState,
options: {
enableRowOrdering,
enableRowPinning,
enableStickyFooter,
enableStickyHeader,
layoutMode,
memoMode,
mrtTheme: { baseBackgroundColor, pinnedRowBackgroundColor, selectedRowBackgroundColor },
muiTableBodyRowProps,
renderDetailPanel,
rowPinningDisplayMode,
},
refs: { tableFooterRef, tableHeadRef },
setHoveredRow,
} = table;
const { density, draggingColumn, draggingRow, editingCell, editingRow, hoveredRow, isFullScreen, rowPinning } =
getState();
const visibleCells = row.getVisibleCells();
const visibleCells = row.getVisibleCells();
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } =
columnVirtualizer ?? {};
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = columnVirtualizer ?? {};
const isRowSelected = getIsRowSelected({ row, table });
const isRowPinned = enableRowPinning && row.getIsPinned();
const isDraggingRow = draggingRow?.id === row.id;
const isHoveredRow = hoveredRow?.id === row.id;
const isRowSelected = getIsRowSelected({ row, table });
const isRowPinned = enableRowPinning && row.getIsPinned();
const isDraggingRow = draggingRow?.id === row.id;
const isHoveredRow = hoveredRow?.id === row.id;
const tableRowProps = {
...parseFromValuesOrFunc(muiTableBodyRowProps, {
row,
staticRowIndex,
table,
}),
...rest,
};
const tableRowProps = {
...parseFromValuesOrFunc(muiTableBodyRowProps, {
row,
staticRowIndex,
table,
}),
...rest,
};
const [bottomPinnedIndex, topPinnedIndex] = useMemo(() => {
if (
!enableRowPinning ||
!rowPinningDisplayMode?.includes("sticky") ||
!pinnedRowIds ||
!row.getIsPinned()
)
return [];
return [
[...pinnedRowIds].reverse().indexOf(row.id),
pinnedRowIds.indexOf(row.id),
];
}, [pinnedRowIds, rowPinning]);
const [bottomPinnedIndex, topPinnedIndex] = useMemo(() => {
if (!enableRowPinning || !rowPinningDisplayMode?.includes("sticky") || !pinnedRowIds || !row.getIsPinned())
return [];
return [[...pinnedRowIds].reverse().indexOf(row.id), pinnedRowIds.indexOf(row.id)];
}, [pinnedRowIds, rowPinning]);
const tableHeadHeight =
((enableStickyHeader || isFullScreen) &&
tableHeadRef.current?.clientHeight) ||
0;
const tableFooterHeight =
(enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
const tableHeadHeight = ((enableStickyHeader || isFullScreen) && tableHeadRef.current?.clientHeight) || 0;
const tableFooterHeight = (enableStickyFooter && tableFooterRef.current?.clientHeight) || 0;
const sx = parseFromValuesOrFunc(tableRowProps?.sx, theme);
const sx = parseFromValuesOrFunc(tableRowProps?.sx, theme);
const defaultRowHeight =
density === "compact" ? 37 : density === "comfortable" ? 53 : 69;
const defaultRowHeight = density === "compact" ? 37 : density === "comfortable" ? 53 : 69;
const customRowHeight =
// @ts-ignore
parseInt(tableRowProps?.style?.height ?? sx?.height, 10) || undefined;
const customRowHeight =
// @ts-ignore
parseInt(tableRowProps?.style?.height ?? sx?.height, 10) || undefined;
const rowHeight = customRowHeight || defaultRowHeight;
const rowHeight = customRowHeight || defaultRowHeight;
const handleDragEnter = (_e) => {
if (enableRowOrdering && draggingRow) {
setHoveredRow(row);
}
};
const handleDragEnter = (_e) => {
if (enableRowOrdering && draggingRow) {
setHoveredRow(row);
}
};
const handleDragOver = (e) => {
e.preventDefault();
};
const handleDragOver = (e) => {
e.preventDefault();
};
const rowRef = useRef(null);
const rowRef = useRef(null);
const cellHighlightColor = isRowSelected
? selectedRowBackgroundColor
: isRowPinned
? pinnedRowBackgroundColor
: undefined;
const cellHighlightColor = isRowSelected
? selectedRowBackgroundColor
: isRowPinned
? pinnedRowBackgroundColor
: undefined;
const cellHighlightColorHover =
tableRowProps?.hover !== false
? isRowSelected
? cellHighlightColor
: theme.palette.mode === "dark"
? `${lighten(baseBackgroundColor, 0.2)}`
: `${darken(baseBackgroundColor, 0.2)}`
: undefined;
const cellHighlightColorHover =
tableRowProps?.hover !== false
? isRowSelected
? cellHighlightColor
: theme.palette.mode === "dark"
? `${lighten(baseBackgroundColor, 0.2)}`
: `${darken(baseBackgroundColor, 0.2)}`
: undefined;
return (
<>
<TableRow
data-index={renderDetailPanel ? staticRowIndex * 2 : staticRowIndex}
data-pinned={!!isRowPinned || undefined}
data-selected={isRowSelected || undefined}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
ref={(node) => {
if (node) {
rowRef.current = node;
rowVirtualizer?.measureElement(node);
}
}}
selected={isRowSelected}
{...tableRowProps}
style={{
transform: virtualRow
? `translateY(${virtualRow.start}px)`
: undefined,
...tableRowProps?.style,
}}
sx={(theme) => ({
"&:hover td:after": cellHighlightColorHover
? {
backgroundColor: alpha(cellHighlightColorHover, 0.3),
...commonCellBeforeAfterStyles,
}
: undefined,
bottom:
!virtualRow && bottomPinnedIndex !== undefined && isRowPinned
? `${bottomPinnedIndex * rowHeight + (enableStickyFooter ? tableFooterHeight - 1 : 0)}px`
: undefined,
boxSizing: "border-box",
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
opacity: isRowPinned ? 0.97 : isDraggingRow || isHoveredRow ? 0.5 : 1,
position: virtualRow
? "absolute"
: rowPinningDisplayMode?.includes("sticky") && isRowPinned
? "sticky"
: "relative",
td: {
...getCommonPinnedCellStyles({ table, theme }),
},
"td:after": cellHighlightColor
? {
backgroundColor: cellHighlightColor,
...commonCellBeforeAfterStyles,
}
: undefined,
top: virtualRow
? 0
: topPinnedIndex !== undefined && isRowPinned
? `${
topPinnedIndex * rowHeight +
(enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0)
}px`
: undefined,
transition: virtualRow ? "none" : "all 150ms ease-in-out",
width: "100%",
zIndex:
rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0,
...sx,
})}
>
{virtualPaddingLeft ? (
<td style={{ display: "flex", width: virtualPaddingLeft }} />
) : null}
{(virtualColumns ?? visibleCells).map(
(cellOrVirtualCell, staticColumnIndex) => {
let cell = cellOrVirtualCell;
if (columnVirtualizer) {
staticColumnIndex = cellOrVirtualCell.index;
cell = visibleCells[staticColumnIndex];
}
const props = {
cell,
numRows,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
};
return cell ? (
memoMode === "cells" &&
cell.column.columnDef.columnDefType === "data" &&
!draggingColumn &&
!draggingRow &&
editingCell?.id !== cell.id &&
editingRow?.id !== row.id ? (
<Memo_DataTable_TableBodyCell key={cell.id} {...props} />
) : (
<DataTable_TableBodyCell key={cell.id} {...props} />
)
) : null;
},
)}
{virtualPaddingRight ? (
<td style={{ display: "flex", width: virtualPaddingRight }} />
) : null}
</TableRow>
{renderDetailPanel && !row.getIsGrouped() && (
<DataTable_TableDetailPanel
parentRowRef={rowRef}
row={row}
rowVirtualizer={rowVirtualizer}
staticRowIndex={staticRowIndex}
table={table}
virtualRow={virtualRow}
/>
)}
</>
);
return (
<>
<TableRow
data-index={renderDetailPanel ? staticRowIndex * 2 : staticRowIndex}
data-pinned={!!isRowPinned || undefined}
data-selected={isRowSelected || undefined}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
ref={(node) => {
if (node) {
rowRef.current = node;
rowVirtualizer?.measureElement(node);
}
}}
selected={isRowSelected}
{...tableRowProps}
style={{
transform: virtualRow ? `translateY(${virtualRow.start}px)` : undefined,
...tableRowProps?.style,
}}
sx={(theme) => ({
"&:hover td:after": cellHighlightColorHover
? {
backgroundColor: alpha(cellHighlightColorHover, 0.3),
...commonCellBeforeAfterStyles,
}
: undefined,
bottom:
!virtualRow && bottomPinnedIndex !== undefined && isRowPinned
? `${bottomPinnedIndex * rowHeight + (enableStickyFooter ? tableFooterHeight - 1 : 0)}px`
: undefined,
boxSizing: "border-box",
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
opacity: isRowPinned ? 0.97 : isDraggingRow || isHoveredRow ? 0.5 : 1,
position: virtualRow
? "absolute"
: rowPinningDisplayMode?.includes("sticky") && isRowPinned
? "sticky"
: "relative",
td: {
...getCommonPinnedCellStyles({ table, theme }),
},
"td:after": cellHighlightColor
? {
backgroundColor: cellHighlightColor,
...commonCellBeforeAfterStyles,
}
: undefined,
top: virtualRow
? 0
: topPinnedIndex !== undefined && isRowPinned
? `${
topPinnedIndex * rowHeight +
(enableStickyHeader || isFullScreen ? tableHeadHeight - 1 : 0)
}px`
: undefined,
transition: virtualRow ? "none" : "all 150ms ease-in-out",
width: "100%",
zIndex: rowPinningDisplayMode?.includes("sticky") && isRowPinned ? 2 : 0,
...sx,
})}
>
{virtualPaddingLeft ? <td style={{ display: "flex", width: virtualPaddingLeft }} /> : null}
{(virtualColumns ?? visibleCells).map((cellOrVirtualCell, staticColumnIndex) => {
let cell = cellOrVirtualCell;
if (columnVirtualizer) {
staticColumnIndex = cellOrVirtualCell.index;
cell = visibleCells[staticColumnIndex];
}
const props = {
cell,
numRows,
rowRef,
staticColumnIndex,
staticRowIndex,
table,
};
return cell ? (
memoMode === "cells" &&
cell.column.columnDef.columnDefType === "data" &&
!draggingColumn &&
!draggingRow &&
editingCell?.id !== cell.id &&
editingRow?.id !== row.id ? (
<Memo_DataTable_TableBodyCell key={cell.id} {...props} />
) : (
<DataTable_TableBodyCell key={cell.id} {...props} />
)
) : null;
})}
{virtualPaddingRight ? <td style={{ display: "flex", width: virtualPaddingRight }} /> : null}
</TableRow>
{renderDetailPanel && !row.getIsGrouped() && (
<DataTable_TableDetailPanel
parentRowRef={rowRef}
row={row}
rowVirtualizer={rowVirtualizer}
staticRowIndex={staticRowIndex}
table={table}
virtualRow={virtualRow}
/>
)}
</>
);
};
export default DataTable_TableBodyRow;
export const Memo_DataTable_TableBodyRow = memo(
DataTable_TableBodyRow,
(prev, next) =>
prev.row === next.row && prev.staticRowIndex === next.staticRowIndex,
DataTable_TableBodyRow,
(prev, next) => prev.row === next.row && prev.staticRowIndex === next.staticRowIndex
);

View File

@@ -2,90 +2,86 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils";
import { Collapse, TableCell, TableRow } from "@mui/material";
const DataTable_TableDetailPanel = ({
parentRowRef,
row,
rowVirtualizer,
staticRowIndex,
table,
virtualRow,
...rest
}) => {
const {
getState,
getVisibleLeafColumns,
options: {
layoutMode,
mrtTheme: { baseBackgroundColor },
muiDetailPanelProps,
muiTableBodyRowProps,
renderDetailPanel,
},
} = table;
const { isLoading } = getState();
const tableRowProps = parseFromValuesOrFunc(muiTableBodyRowProps, {
isDetailPanel: true,
parentRowRef,
row,
rowVirtualizer,
staticRowIndex,
table,
});
virtualRow,
...rest
}) => {
const {
getState,
getVisibleLeafColumns,
options: {
layoutMode,
mrtTheme: { baseBackgroundColor },
muiDetailPanelProps,
muiTableBodyRowProps,
renderDetailPanel,
},
} = table;
const { isLoading } = getState();
const tableCellProps = {
...parseFromValuesOrFunc(muiDetailPanelProps, {
row,
table,
}),
...rest,
};
const tableRowProps = parseFromValuesOrFunc(muiTableBodyRowProps, {
isDetailPanel: true,
row,
staticRowIndex,
table,
});
const DetailPanel = !isLoading && renderDetailPanel?.({ row, table });
const tableCellProps = {
...parseFromValuesOrFunc(muiDetailPanelProps, {
row,
table,
}),
...rest,
};
return (
<TableRow
className="Mui-TableBodyCell-DetailPanel"
data-index={renderDetailPanel ? staticRowIndex * 2 + 1 : staticRowIndex}
ref={(node) => {
if (node) {
rowVirtualizer?.measureElement?.(node);
}
}}
{...tableRowProps}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
position: virtualRow ? "absolute" : undefined,
top: virtualRow
? `${parentRowRef.current?.getBoundingClientRect()?.height}px`
: undefined,
transform: virtualRow
? `translateY(${virtualRow?.start}px)`
: undefined,
width: "100%",
...parseFromValuesOrFunc(tableRowProps?.sx, theme),
})}
>
<TableCell
className="Mui-TableBodyCell-DetailPanel"
colSpan={getVisibleLeafColumns().length}
{...tableCellProps}
sx={(theme) => ({
backgroundColor: virtualRow ? baseBackgroundColor : undefined,
borderBottom: !row.getIsExpanded() ? "none" : undefined,
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
py: !!DetailPanel && row.getIsExpanded() ? "1rem" : 0,
transition: !virtualRow ? "all 150ms ease-in-out" : undefined,
width: `100%`,
...parseFromValuesOrFunc(tableCellProps?.sx, theme),
})}
>
{virtualRow ? (
row.getIsExpanded() && DetailPanel
) : (
<Collapse in={row.getIsExpanded()} mountOnEnter unmountOnExit>
{DetailPanel}
</Collapse>
)}
</TableCell>
</TableRow>
);
const DetailPanel = !isLoading && renderDetailPanel?.({ row, table });
return (
<TableRow
className="Mui-TableBodyCell-DetailPanel"
data-index={renderDetailPanel ? staticRowIndex * 2 + 1 : staticRowIndex}
ref={(node) => {
if (node) {
rowVirtualizer?.measureElement?.(node);
}
}}
{...tableRowProps}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
position: virtualRow ? "absolute" : undefined,
top: virtualRow ? `${parentRowRef.current?.getBoundingClientRect()?.height}px` : undefined,
transform: virtualRow ? `translateY(${virtualRow?.start}px)` : undefined,
width: "100%",
...parseFromValuesOrFunc(tableRowProps?.sx, theme),
})}
>
<TableCell
className="Mui-TableBodyCell-DetailPanel"
colSpan={getVisibleLeafColumns().length}
{...tableCellProps}
sx={(theme) => ({
backgroundColor: virtualRow ? baseBackgroundColor : undefined,
borderBottom: !row.getIsExpanded() ? "none" : undefined,
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
py: !!DetailPanel && row.getIsExpanded() ? "1rem" : 0,
transition: !virtualRow ? "all 150ms ease-in-out" : undefined,
width: `100%`,
...parseFromValuesOrFunc(tableCellProps?.sx, theme),
})}
>
{virtualRow ? (
row.getIsExpanded() && DetailPanel
) : (
<Collapse in={row.getIsExpanded()} mountOnEnter unmountOnExit>
{DetailPanel}
</Collapse>
)}
</TableCell>
</TableRow>
);
};
export default DataTable_TableDetailPanel;

View File

@@ -1,74 +1,68 @@
import {
getCommonTooltipProps,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
import { Button, Tooltip } from "@mui/material";
import { useState } from "react";
const DataTable_CopyButton = ({ cell, table, ...rest }) => {
const {
options: { localization, muiCopyButtonProps },
} = table;
const { column, row } = cell;
const { columnDef } = column;
const {
options: { localization, muiCopyButtonProps },
} = table;
const { column, row } = cell;
const { columnDef } = column;
const [copied, setCopied] = useState(false);
const [copied, setCopied] = useState(false);
const handleCopy = (event, text) => {
event.stopPropagation();
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 4000);
};
const handleCopy = (event, text) => {
event.stopPropagation();
navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 4000);
};
const buttonProps = {
...parseFromValuesOrFunc(muiCopyButtonProps, {
cell,
column,
row,
table,
}),
...parseFromValuesOrFunc(columnDef.muiCopyButtonProps, {
cell,
column,
row,
table,
}),
...rest,
};
const buttonProps = {
...parseFromValuesOrFunc(muiCopyButtonProps, {
cell,
column,
row,
table,
}),
...parseFromValuesOrFunc(columnDef.muiCopyButtonProps, {
cell,
column,
row,
table,
}),
...rest,
};
return (
<Tooltip
{...getCommonTooltipProps("top")}
title={
buttonProps?.title ??
(copied ? localization.copiedToClipboard : localization.clickToCopy)
}
>
<Button
onClick={(e) => handleCopy(e, cell.getValue())}
size="small"
type="button"
variant="text"
{...buttonProps}
sx={(theme) => ({
backgroundColor: "transparent",
border: "none",
color: "inherit",
cursor: "copy",
fontFamily: "inherit",
fontSize: "inherit",
letterSpacing: "inherit",
m: "-0.25rem",
minWidth: "unset",
py: 0,
textAlign: "inherit",
textTransform: "inherit",
...parseFromValuesOrFunc(buttonProps?.sx, theme),
})}
title={undefined}
/>
</Tooltip>
);
return (
<Tooltip
{...getCommonTooltipProps("top")}
title={buttonProps?.title ?? (copied ? localization.copiedToClipboard : localization.clickToCopy)}
>
<Button
onClick={(e) => handleCopy(e, cell.getValue())}
size="small"
type="button"
variant="text"
{...buttonProps}
sx={(theme) => ({
backgroundColor: "transparent",
border: "none",
color: "inherit",
cursor: "copy",
fontFamily: "inherit",
fontSize: "inherit",
letterSpacing: "inherit",
m: "-0.25rem",
minWidth: "unset",
py: 0,
textAlign: "inherit",
textTransform: "inherit",
...parseFromValuesOrFunc(buttonProps?.sx, theme),
})}
title={undefined}
/>
</Tooltip>
);
};
export default DataTable_CopyButton;

View File

@@ -1,52 +1,46 @@
import {
getCommonTooltipProps,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
import { IconButton, Tooltip } from "@mui/material";
const DataTable_GrabHandleButton = ({ location, table, ...rest }) => {
const {
options: {
icons: { DragHandleIcon },
localization,
},
} = table;
const {
options: {
icons: { DragHandleIcon },
localization,
},
} = table;
return (
<Tooltip
{...getCommonTooltipProps("top")}
title={rest?.title ?? localization.move}
>
<IconButton
aria-label={rest.title ?? localization.move}
disableRipple
draggable="true"
size="small"
{...rest}
onClick={(e) => {
e.stopPropagation();
rest?.onClick?.(e);
}}
sx={(theme) => ({
"&:active": {
cursor: "grabbing",
},
"&:hover": {
backgroundColor: "transparent",
opacity: 1,
},
cursor: "grab",
m: "0 -0.1rem",
opacity: location === "row" ? 1 : 0.5,
p: "2px",
transition: "all 150ms ease-in-out",
...parseFromValuesOrFunc(rest?.sx, theme),
})}
title={undefined}
>
<DragHandleIcon />
</IconButton>
</Tooltip>
);
return (
<Tooltip {...getCommonTooltipProps("top")} title={rest?.title ?? localization.move}>
<IconButton
aria-label={rest.title ?? localization.move}
disableRipple
draggable="true"
size="small"
{...rest}
onClick={(e) => {
e.stopPropagation();
rest?.onClick?.(e);
}}
sx={(theme) => ({
"&:active": {
cursor: "grabbing",
},
"&:hover": {
backgroundColor: "transparent",
opacity: 1,
},
cursor: "grab",
m: "0 -0.1rem",
opacity: location === "row" ? 1 : 0.5,
p: "2px",
transition: "all 150ms ease-in-out",
...parseFromValuesOrFunc(rest?.sx, theme),
})}
title={undefined}
>
<DragHandleIcon />
</IconButton>
</Tooltip>
);
};
export default DataTable_GrabHandleButton;

View File

@@ -1,4 +1,4 @@
const DataTable_ToggleFiltersButton = ({ table, ...rest }) => {
return <></>;
return <></>;
};
export default DataTable_ToggleFiltersButton;

View File

@@ -12,122 +12,121 @@ import ScrollBox from "../../ScrollBox";
import FilterBodyController from "./FilterBodyController";
function FilterBody({ columns, drawerState, setDrawerState }) {
const { filterData, setFilterData } = useDataTable();
const [validationSchema, setValidationSchema] = useState(Yup.object({}));
const { filterData, setFilterData } = useDataTable();
const [validationSchema, setValidationSchema] = useState(Yup.object({}));
console.log(filterData);
console.log(filterData);
useEffect(() => {
const schema = Yup.object(
Object.keys(filterData).reduce((acc, key) => {
const initialValue = filterData[key];
if (initialValue.filterMode === "between") {
acc[key] = Yup.object().shape({
value: Yup.array()
.of(Yup.string().nullable())
.test({
test(value, ctx) {
const [start, end] = value || ["", ""];
if (
initialValue.datatype === "numeric" &&
parseInt(end, 10) <= parseInt(start, 10)
) {
return ctx.createError({
message: `مقدار وارده باید بیشتر از (${start}) باشد`,
useEffect(() => {
const schema = Yup.object(
Object.keys(filterData).reduce((acc, key) => {
const initialValue = filterData[key];
if (initialValue.filterMode === "between") {
acc[key] = Yup.object().shape({
value: Yup.array()
.of(Yup.string().nullable())
.test({
test(value, ctx) {
const [start, end] = value || ["", ""];
if (
initialValue.datatype === "numeric" &&
parseInt(end, 10) <= parseInt(start, 10)
) {
return ctx.createError({
message: `مقدار وارده باید بیشتر از (${start}) باشد`,
});
} else if ((start && !end) || (!start && end)) {
return ctx.createError({
message: "این بخش را تکمیل نمایید",
});
}
return true;
},
}),
});
} else if ((start && !end) || (!start && end)) {
return ctx.createError({
message: "این بخش را تکمیل نمایید",
});
}
return true;
},
}),
});
}
return acc;
}, {}),
}
return acc;
}, {})
);
setValidationSchema(schema);
}, [filterData]);
const {
handleSubmit,
control,
reset,
formState: { errors, isDirty, isValid },
} = useForm({
defaultValues: filterData,
resolver: yupResolver(validationSchema),
mode: "all",
});
const onSubmit = (data) => {
setDrawerState(false);
setFilterData(data);
};
return (
<>
<FilterHeader setDrawerState={setDrawerState} />
{Object.keys(filterData).length > 0 && (
<ScrollBox>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={{ px: 2, py: 3 }}>
{columns.map((column) =>
column.enableColumnFilter ? (
column.dependencyId ? (
<FilterBodyControllerWithDependency
key={column.id}
column={column}
control={control}
errors={errors}
reset={reset}
/>
) : (
<FilterBodyController
key={column.id}
column={column}
control={control}
errors={errors}
reset={reset}
/>
)
) : null
)}
</Box>
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
pb: 2,
}}
>
<Button
type="submit"
variant="contained"
size="large"
disabled={!isDirty || !isValid}
sx={{
px: 8,
boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
backgroundColor: "primary2",
":hover": {
backgroundColor: "primary2",
},
}}
>
اعمال فیلتر
</Button>
</Box>
</form>
</ScrollBox>
)}
</>
);
setValidationSchema(schema);
}, [filterData]);
const {
handleSubmit,
control,
reset,
formState: { errors, isDirty, isValid },
} = useForm({
defaultValues: filterData,
resolver: yupResolver(validationSchema),
mode: "all",
});
const onSubmit = (data) => {
setDrawerState(false);
setFilterData(data);
};
return (
<>
<FilterHeader setDrawerState={setDrawerState} />
{Object.keys(filterData).length > 0 && (
<ScrollBox>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={{ px: 2, py: 3 }}>
{columns.map((column) =>
column.enableColumnFilter ? (
column.dependencyId ? (
<FilterBodyControllerWithDependency
key={column.id}
column={column}
control={control}
errors={errors}
reset={reset}
/>
) : (
<FilterBodyController
key={column.id}
column={column}
control={control}
errors={errors}
reset={reset}
/>
)
) : null,
)}
</Box>
<Box
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
pb: 2,
}}
>
<Button
type="submit"
variant="contained"
size="large"
disabled={!isDirty || !isValid}
sx={{
px: 8,
boxShadow:
"rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
backgroundColor: "primary2",
":hover": {
backgroundColor: "primary2",
},
}}
>
اعمال فیلتر
</Button>
</Box>
</form>
</ScrollBox>
)}
</>
);
}
export default FilterBody;

View File

@@ -2,24 +2,24 @@ import { Controller, useWatch } from "react-hook-form";
import FilterBodyField from "./FilterBodyField";
const FilterBodyController = ({ column, control, reset, errors }) => {
return (
<Controller
name={`${column.id}`}
control={control}
render={({ field: { value, name, onBlur, onChange } }) => {
return (
<FilterBodyField
column={column}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={null}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
return (
<Controller
name={`${column.id}`}
control={control}
render={({ field: { value, name, onBlur, onChange } }) => {
return (
<FilterBodyField
column={column}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={null}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
};
export default FilterBodyController;

View File

@@ -1,32 +1,27 @@
import { Controller, useWatch } from "react-hook-form";
import FilterBodyField from "./FilterBodyField";
const FilterBodyControllerWithDependency = ({
column,
control,
reset,
errors,
}) => {
const dependencyField = useWatch({ control, name: column.dependencyId });
const FilterBodyControllerWithDependency = ({ column, control, reset, errors }) => {
const dependencyField = useWatch({ control, name: column.dependencyId });
return (
<Controller
name={`${column.id}`}
control={control}
render={({ field: { value, name, onBlur, onChange } }) => {
return (
<FilterBodyField
column={column}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={dependencyField}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
return (
<Controller
name={`${column.id}`}
control={control}
render={({ field: { value, name, onBlur, onChange } }) => {
return (
<FilterBodyField
column={column}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={dependencyField}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
};
export default FilterBodyControllerWithDependency;

View File

@@ -8,98 +8,97 @@ import CustomTextFieldRange from "@/core/components/DataTable/filter/fieldsType/
import { useState } from "react";
const columnFilterModeOptionFa = {
equals: "برابر",
notEquals: "نابرابر",
contains: "شامل",
lessThan: "کوچکتر",
greaterThan: "بزرگتر",
fuzzy: "فازی",
between: "مابین",
equals: "برابر",
notEquals: "نابرابر",
contains: "شامل",
lessThan: "کوچکتر",
greaterThan: "بزرگتر",
fuzzy: "فازی",
between: "مابین",
};
function FilterBodyField({
column,
filterParameters,
handleChange,
handleBlur,
dependencyFieldValue,
setFieldValue,
resetForm,
errors,
column,
filterParameters,
handleChange,
handleBlur,
dependencyFieldValue,
setFieldValue,
resetForm,
errors,
}) {
const [anchorEl, setAnchorEl] = useState(null);
const defaultFilterTranslation =
columnFilterModeOptionFa[filterParameters.filterMode] ||
filterParameters.filterMode;
const [anchorEl, setAnchorEl] = useState(null);
const defaultFilterTranslation =
columnFilterModeOptionFa[filterParameters.filterMode] || filterParameters.filterMode;
const handleOpenFilterBox = (event) => {
setAnchorEl(event.currentTarget);
};
const renderField = () => {
const commonProps = {
column,
filterParameters,
defaultFilterTranslation,
handleOpenFilterBox,
dependencyFieldValue,
setFieldValue,
handleChange,
handleBlur,
errors,
const handleOpenFilterBox = (event) => {
setAnchorEl(event.currentTarget);
};
switch (filterParameters.datatype) {
case "numeric":
if (filterParameters.filterMode === "between") {
return <CustomTextFieldRange {...commonProps} />;
}
if (filterParameters.filterMode === "equals") {
return column.ColumnSelectComponent ? (
<column.ColumnSelectComponent {...commonProps} />
) : (
<CustomSelect {...commonProps} />
);
}
break;
case "date":
if (filterParameters.filterMode === "equals") {
return <CustomDatePicker {...commonProps} />;
}
if (filterParameters.filterMode === "between") {
return <CustomDatePickerRange {...commonProps} />;
}
break;
const renderField = () => {
const commonProps = {
column,
filterParameters,
defaultFilterTranslation,
handleOpenFilterBox,
dependencyFieldValue,
setFieldValue,
handleChange,
handleBlur,
errors,
};
case "array":
if (filterParameters.filterMode === "equals") {
return <CustomSelectMultiple {...commonProps} />;
switch (filterParameters.datatype) {
case "numeric":
if (filterParameters.filterMode === "between") {
return <CustomTextFieldRange {...commonProps} />;
}
if (filterParameters.filterMode === "equals") {
return column.ColumnSelectComponent ? (
<column.ColumnSelectComponent {...commonProps} />
) : (
<CustomSelect {...commonProps} />
);
}
break;
case "date":
if (filterParameters.filterMode === "equals") {
return <CustomDatePicker {...commonProps} />;
}
if (filterParameters.filterMode === "between") {
return <CustomDatePickerRange {...commonProps} />;
}
break;
case "array":
if (filterParameters.filterMode === "equals") {
return <CustomSelectMultiple {...commonProps} />;
}
break;
default:
return <CustomTextField {...commonProps} />;
}
break;
};
default:
return <CustomTextField {...commonProps} />;
}
};
return (
<>
{renderField()}
{Array.isArray(column.columnFilterModeOptions) && (
<FilterOptionList
column={column}
anchorEl={anchorEl}
setAnchorEl={setAnchorEl}
filterParameters={filterParameters}
filterType={filterParameters.filterMode}
handleChange={handleChange}
resetForm={resetForm}
filterOption={column.columnFilterModeOptions}
columnFilterModeOptionFa={columnFilterModeOptionFa}
/>
)}
</>
);
return (
<>
{renderField()}
{Array.isArray(column.columnFilterModeOptions) && (
<FilterOptionList
column={column}
anchorEl={anchorEl}
setAnchorEl={setAnchorEl}
filterParameters={filterParameters}
filterType={filterParameters.filterMode}
handleChange={handleChange}
resetForm={resetForm}
filterOption={column.columnFilterModeOptions}
columnFilterModeOptionFa={columnFilterModeOptionFa}
/>
)}
</>
);
}
export default FilterBodyField;

View File

@@ -4,36 +4,34 @@ import { IconButton, Tooltip, Badge } from "@mui/material";
import useDataTable from "@/lib/hooks/useDataTable";
function FilterButton({ drawerState, setDrawerState }) {
const { filterData } = useDataTable();
const isValueEmpty = (value) => {
if (Array.isArray(value)) {
return value.length === 0 || value.every((v) => v === "");
}
return value === "" || value === null || value === undefined;
};
const filteredFilterData = Object.values(filterData).filter(
(filter) => !isValueEmpty(filter.value),
);
return (
<Tooltip title="فیلتر">
<IconButton
onClick={() => {
setDrawerState(!drawerState);
}}
aria-label="filter table"
>
<Badge
badgeContent={filteredFilterData.length}
color="primary"
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<FilterAltIcon />
</Badge>
</IconButton>
</Tooltip>
);
const { filterData } = useDataTable();
const isValueEmpty = (value) => {
if (Array.isArray(value)) {
return value.length === 0 || value.every((v) => v === "");
}
return value === "" || value === null || value === undefined;
};
const filteredFilterData = Object.values(filterData).filter((filter) => !isValueEmpty(filter.value));
return (
<Tooltip title="فیلتر">
<IconButton
onClick={() => {
setDrawerState(!drawerState);
}}
aria-label="filter table"
>
<Badge
badgeContent={filteredFilterData.length}
color="primary"
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<FilterAltIcon />
</Badge>
</IconButton>
</Tooltip>
);
}
export default FilterButton;

View File

@@ -4,35 +4,35 @@ import { Box, Drawer } from "@mui/material";
import FilterDrawer from "../../FilterDrawer";
const FilterCustom = ({ filterData, setFilterData }) => {
const [open, setOpen] = useState(false);
const [open, setOpen] = useState(false);
const closeDrawer = useCallback(() => setOpen(false), []);
const closeDrawer = useCallback(() => setOpen(false), []);
return (
<>
<FilterButton drawerState={open} setDrawerState={setOpen} />
<Drawer
open={open}
onClose={() => setOpen(false)}
sx={{
overflowY: "hidden",
display: "flex",
flexDirection: "column",
height: "100%",
zIndex: "1300",
}}
>
<Box sx={{ width: { xs: 300, sm: 450 } }}>
{open && (
<FilterDrawer
defaultValues={filterData}
setFilterData={setFilterData}
closeDrawer={closeDrawer}
/>
)}
</Box>
</Drawer>
</>
);
return (
<>
<FilterButton drawerState={open} setDrawerState={setOpen} />
<Drawer
open={open}
onClose={() => setOpen(false)}
sx={{
overflowY: "hidden",
display: "flex",
flexDirection: "column",
height: "100%",
zIndex: "1300",
}}
>
<Box sx={{ width: { xs: 300, sm: 450 } }}>
{open && (
<FilterDrawer
defaultValues={filterData}
setFilterData={setFilterData}
closeDrawer={closeDrawer}
/>
)}
</Box>
</Drawer>
</>
);
};
export default FilterCustom;

View File

@@ -5,31 +5,30 @@ import FilterAltIcon from "@mui/icons-material/FilterAlt";
import { Box, IconButton, Typography } from "@mui/material";
function FilterHeader({ setDrawerState }) {
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: (theme) => theme.palette.primary.main,
boxShadow:
"rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<FilterAltIcon sx={{ color: "#fff", mr: 1 }} />
<Typography variant="h6" sx={{ color: "#fff" }}>
فیلتر
</Typography>
</Box>
<IconButton sx={{ color: "#fff" }} onClick={() => setDrawerState(false)}>
<CancelIcon sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
);
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: (theme) => theme.palette.primary.main,
boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<FilterAltIcon sx={{ color: "#fff", mr: 1 }} />
<Typography variant="h6" sx={{ color: "#fff" }}>
فیلتر
</Typography>
</Box>
<IconButton sx={{ color: "#fff" }} onClick={() => setDrawerState(false)}>
<CancelIcon sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
);
}
export default FilterHeader;

View File

@@ -4,55 +4,49 @@ import { ListItem, Menu } from "@mui/material";
import { useState } from "react";
function FilterOptionList({
filterType,
filterOption,
filterParameters,
anchorEl,
columnFilterModeOptionFa,
setAnchorEl,
handleChange,
filterType,
filterOption,
filterParameters,
anchorEl,
columnFilterModeOptionFa,
setAnchorEl,
handleChange,
}) {
const [selectedFilter, setSelectedFilter] = useState(filterType);
const [selectedFilter, setSelectedFilter] = useState(filterType);
const handleChangeItem = (event, index) => {
handleChange({
...filterParameters,
value: filterOption[index] === "between" ? ["", ""] : "",
filterMode: filterOption[index],
});
setSelectedFilter(filterOption[index]);
setAnchorEl(null);
};
const handleChangeItem = (event, index) => {
handleChange({
...filterParameters,
value: filterOption[index] === "between" ? ["", ""] : "",
filterMode: filterOption[index],
});
setSelectedFilter(filterOption[index]);
setAnchorEl(null);
};
const handleCloseFilterBox = () => {
setAnchorEl(null);
};
const handleCloseFilterBox = () => {
setAnchorEl(null);
};
return (
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleCloseFilterBox}
>
{filterOption.map((option, index) => (
<ListItem
key={index}
onClick={(event) => handleChangeItem(event, index)}
selected={option === selectedFilter}
sx={{
cursor: "pointer",
width: "100px",
display: "flex",
justifyContent: "center",
}}
>
{columnFilterModeOptionFa[option]}
</ListItem>
))}
</Menu>
);
return (
<Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleCloseFilterBox}>
{filterOption.map((option, index) => (
<ListItem
key={index}
onClick={(event) => handleChangeItem(event, index)}
selected={option === selectedFilter}
sx={{
cursor: "pointer",
width: "100px",
display: "flex",
justifyContent: "center",
}}
>
{columnFilterModeOptionFa[option]}
</ListItem>
))}
</Menu>
);
}
export default FilterOptionList;

View File

@@ -2,30 +2,22 @@ import React from "react";
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
import { Typography } from "@mui/material";
function CustomDatePicker({
column,
filterParameters,
defaultFilterTranslation,
handleChange,
}) {
return (
<MuiDatePicker
name={`${column.id}.value`}
value={filterParameters.value}
setFieldValue={(name, formattedDate) => {
handleChange({ ...filterParameters, value: formattedDate });
}}
placeholder={column.header}
helperText={
<Typography
variant="button"
sx={{ color: (theme) => theme.palette.primary.main }}
>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
);
function CustomDatePicker({ column, filterParameters, defaultFilterTranslation, handleChange }) {
return (
<MuiDatePicker
name={`${column.id}.value`}
value={filterParameters.value}
setFieldValue={(name, formattedDate) => {
handleChange({ ...filterParameters, value: formattedDate });
}}
placeholder={column.header}
helperText={
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
);
}
export default CustomDatePicker;

View File

@@ -4,57 +4,44 @@ import React from "react";
import { Box, Typography } from "@mui/material";
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
function CustomDatePickerRange({
column,
filterParameters,
defaultFilterTranslation,
handleChange,
errors,
}) {
return (
<Box sx={{ display: "flex", gap: 1 }}>
<MuiDatePicker
label={column.header}
name={`${column.id}.value[0]`}
value={filterParameters.value[0]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [formattedDate, filterParameters.value[1]],
});
}}
maxDate={filterParameters.value[1]}
placeholder={`از تاریخ`}
helperText={
<Typography
variant="button"
sx={{ color: (theme) => theme.palette.primary.main }}
>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
<MuiDatePicker
label={column.header}
name={`${column.id}.value[1]`}
value={filterParameters.value[1]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [filterParameters.value[0], formattedDate],
});
}}
minDate={filterParameters.value[0]}
placeholder={`تا تاریخ`}
helperText={
errors?.[`${column.id}`]?.value
? errors?.[`${column.id}`]?.value.message
: null
}
error={Boolean(errors?.[`${column.id}`]?.value)}
/>
</Box>
);
function CustomDatePickerRange({ column, filterParameters, defaultFilterTranslation, handleChange, errors }) {
return (
<Box sx={{ display: "flex", gap: 1 }}>
<MuiDatePicker
label={column.header}
name={`${column.id}.value[0]`}
value={filterParameters.value[0]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [formattedDate, filterParameters.value[1]],
});
}}
maxDate={filterParameters.value[1]}
placeholder={`از تاریخ`}
helperText={
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
<MuiDatePicker
label={column.header}
name={`${column.id}.value[1]`}
value={filterParameters.value[1]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [filterParameters.value[0], formattedDate],
});
}}
minDate={filterParameters.value[0]}
placeholder={`تا تاریخ`}
helperText={errors?.[`${column.id}`]?.value ? errors?.[`${column.id}`]?.value.message : null}
error={Boolean(errors?.[`${column.id}`]?.value)}
/>
</Box>
);
}
export default CustomDatePickerRange;

View File

@@ -6,81 +6,67 @@ import { Box, FormHelperText, IconButton, InputAdornment } from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
import moment from "jalali-moment";
function MuiDatePicker({
label,
value,
setFieldValue,
name,
minDate,
maxDate,
helperText,
placeholder,
error,
}) {
return (
<Box sx={{ display: "flex", flexDirection: "column", my: 1 }}>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={
faIR.components.MuiLocalizationProvider.defaultProps.localeText
}
>
<MobileDatePicker
value={value ? new Date(value) : null}
sx={{ width: "100%" }}
id={name}
label={label}
name={name}
closeOnSelect={true}
aria-describedby="component-helper-text"
onChange={(value) => {
const date = new Date(value);
const formattedDate = moment(date)
.locale("en")
.format("YYYY-MM-DD");
setFieldValue(name, formattedDate);
}}
minDate={minDate ? new Date(minDate) : null}
maxDate={maxDate ? new Date(maxDate) : null}
slotProps={{
textField: {
size: "small",
error: error,
placeholder: placeholder,
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
onClick={(event) => {
event.stopPropagation();
setFieldValue(name, "");
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
function MuiDatePicker({ label, value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) {
return (
<Box sx={{ display: "flex", flexDirection: "column", my: 1 }}>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
>
<MobileDatePicker
value={value ? new Date(value) : null}
sx={{ width: "100%" }}
id={name}
label={label}
name={name}
closeOnSelect={true}
aria-describedby="component-helper-text"
onChange={(value) => {
const date = new Date(value);
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD");
setFieldValue(name, formattedDate);
}}
minDate={minDate ? new Date(minDate) : null}
maxDate={maxDate ? new Date(maxDate) : null}
slotProps={{
textField: {
size: "small",
error: error,
placeholder: placeholder,
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
onClick={(event) => {
event.stopPropagation();
setFieldValue(name, "");
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
},
}}
>
<ClearIcon />
</IconButton>
</InputAdornment>
),
},
InputLabelProps: {
shrink: true,
},
},
}}
>
<ClearIcon />
</IconButton>
</InputAdornment>
),
},
InputLabelProps: {
shrink: true,
},
},
}}
/>
{/* <FormHelperText id="component-helper-text" variant="caption" sx={{ ml: 2, color: error ? "#d32f2f" : "unset", fontWeight: 'bold' }}>
}}
/>
{/* <FormHelperText id="component-helper-text" variant="caption" sx={{ ml: 2, color: error ? "#d32f2f" : "unset", fontWeight: 'bold' }}>
{helperText ? helperText : ""}
</FormHelperText> */}
</LocalizationProvider>
</Box>
);
</LocalizationProvider>
</Box>
);
}
export default MuiDatePicker;

View File

@@ -1,38 +1,30 @@
"use client";
import {
FormControl,
InputLabel,
MenuItem,
OutlinedInput,
Select,
} from "@mui/material";
import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
function CustomSelect({ column, filterParameters, handleChange }) {
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel id={`label${column.id}`} shrink>
{column.header}
</InputLabel>
<Select
labelId={`label${column.id}`}
id={column.id}
name={`${column.id}.value`}
value={filterParameters.value}
input={<OutlinedInput label={column.header} />}
size="small"
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
displayEmpty
>
{column.columnSelectOption().map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel id={`label${column.id}`} shrink>
{column.header}
</InputLabel>
<Select
labelId={`label${column.id}`}
id={column.id}
name={`${column.id}.value`}
value={filterParameters.value}
input={<OutlinedInput label={column.header} />}
size="small"
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
displayEmpty
>
{column.columnSelectOption().map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default CustomSelect;

View File

@@ -1,49 +1,39 @@
"use client";
import {
FormControl,
FormHelperText,
InputLabel,
MenuItem,
OutlinedInput,
Select,
Typography,
} from "@mui/material";
import { FormControl, FormHelperText, InputLabel, MenuItem, OutlinedInput, Select, Typography } from "@mui/material";
import { useCallback, useEffect } from "react";
function CustomSelectByDependency({
column,
filterParameters,
value,
defaultFilterTranslation,
handleChange,
columnSelectOption,
column,
filterParameters,
value,
defaultFilterTranslation,
handleChange,
columnSelectOption,
}) {
return (
<FormControl fullWidth sx={{ my: 1 }} size="small">
<InputLabel id={`label${column.id}`} shrink>
{column.header}
</InputLabel>
<Select
labelId={`label${column.id}`}
id={column.id}
name={`${column.id}.value`}
value={value}
size="small"
input={<OutlinedInput label={column.header} />}
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
displayEmpty
>
{columnSelectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
return (
<FormControl fullWidth sx={{ my: 1 }} size="small">
<InputLabel id={`label${column.id}`} shrink>
{column.header}
</InputLabel>
<Select
labelId={`label${column.id}`}
id={column.id}
name={`${column.id}.value`}
value={value}
size="small"
input={<OutlinedInput label={column.header} />}
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
displayEmpty
>
{columnSelectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default CustomSelectByDependency;

View File

@@ -1,62 +1,55 @@
"use client";
import {
Box,
Chip,
FormControl,
FormHelperText,
InputLabel,
MenuItem,
OutlinedInput,
Select,
Typography,
Box,
Chip,
FormControl,
FormHelperText,
InputLabel,
MenuItem,
OutlinedInput,
Select,
Typography,
} from "@mui/material";
function CustomSelectMultiple({
column,
filterParameters,
defaultFilterTranslation,
handleChange,
}) {
const columnSelectOption = column.columnSelectOption;
function CustomSelectMultiple({ column, filterParameters, defaultFilterTranslation, handleChange }) {
const columnSelectOption = column.columnSelectOption;
const getLabelForValue = (value) => {
const option = columnSelectOption.find((opt) => opt.value === value);
return option ? option.label : value;
};
const getLabelForValue = (value) => {
const option = columnSelectOption.find((opt) => opt.value === value);
return option ? option.label : value;
};
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel htmlFor="uncontrolled-native" id={`label${column.id}`}>
{column.header}
</InputLabel>
<Select
labelId={`label${column.id}`}
id={column.id}
value={filterParameters.value}
multiple
size="small"
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => (
<Chip key={value} label={getLabelForValue(value)} />
))}
</Box>
)}
input={<OutlinedInput label={column.header} />}
InputLabelProps={{ shrink: true }}
>
{columnSelectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel htmlFor="uncontrolled-native" id={`label${column.id}`}>
{column.header}
</InputLabel>
<Select
labelId={`label${column.id}`}
id={column.id}
value={filterParameters.value}
multiple
size="small"
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => (
<Chip key={value} label={getLabelForValue(value)} />
))}
</Box>
)}
input={<OutlinedInput label={column.header} />}
InputLabelProps={{ shrink: true }}
>
{columnSelectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default CustomSelectMultiple;

View File

@@ -2,41 +2,35 @@ import { InputAdornment, TextField, Typography } from "@mui/material";
import FilterListIcon from "@mui/icons-material/FilterList";
function CustomTextField({
column,
defaultFilterTranslation,
filterParameters,
handleOpenFilterBox,
handleBlur,
handleChange,
column,
defaultFilterTranslation,
filterParameters,
handleOpenFilterBox,
handleBlur,
handleChange,
}) {
return (
<TextField
id={column.id}
name={column.id}
label={column.header}
value={filterParameters.value}
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
onBlur={handleBlur}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment
position="end"
sx={{ cursor: "pointer" }}
onClick={handleOpenFilterBox}
>
<FilterListIcon />
</InputAdornment>
),
}}
InputLabelProps={{ shrink: true }}
/>
);
return (
<TextField
id={column.id}
name={column.id}
label={column.header}
value={filterParameters.value}
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
onBlur={handleBlur}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment position="end" sx={{ cursor: "pointer" }} onClick={handleOpenFilterBox}>
<FilterListIcon />
</InputAdornment>
),
}}
InputLabelProps={{ shrink: true }}
/>
);
}
export default CustomTextField;

View File

@@ -2,84 +2,73 @@ import { Box, InputAdornment, TextField, Typography } from "@mui/material";
import FilterListIcon from "@mui/icons-material/FilterList";
function CustomTextFieldRange({
column,
defaultFilterTranslation,
handleOpenFilterBox,
handleChange,
filterParameters,
handleBlur,
errors,
column,
defaultFilterTranslation,
handleOpenFilterBox,
handleChange,
filterParameters,
handleBlur,
errors,
}) {
return (
<Box sx={{ display: "flex" }}>
<TextField
id={`${column.id}.value[0]`}
name={`${column.id}.value[0]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [e.target.value, filterParameters.value[1]],
})
}
onBlur={handleBlur}
label={<Typography>از {column.header}</Typography>}
value={filterParameters.value[0]}
fullWidth
error={
touched?.[`${column.id}`]?.value &&
Boolean(errors?.[`${column.id}`]?.value)
}
helperText={
<Typography
variant="caption"
sx={{
color: (theme) => theme.palette.primary.main,
fontWeight: "bold",
}}
>
نوع فیلتر: {defaultFilterTranslation}
</Typography>
}
variant="outlined"
size="small"
sx={{ my: 1, marginRight: 1 }}
/>
<TextField
id={`${column.id}.value[1]`}
name={`${column.id}.value[1]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [filterParameters.value[0], e.target.value],
})
}
onBlur={handleBlur}
error={Boolean(errors?.[`${column.id}`]?.value)}
helperText={
errors?.[`${column.id}`]?.value
? errors?.[`${column.id}`]?.value.message
: null
}
label={<Typography>تا {column.header}</Typography>}
value={filterParameters.value[1]}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment
position="end"
sx={{ cursor: "pointer" }}
onClick={handleOpenFilterBox}
>
<FilterListIcon />
</InputAdornment>
),
}}
/>
</Box>
);
return (
<Box sx={{ display: "flex" }}>
<TextField
id={`${column.id}.value[0]`}
name={`${column.id}.value[0]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [e.target.value, filterParameters.value[1]],
})
}
onBlur={handleBlur}
label={<Typography>از {column.header}</Typography>}
value={filterParameters.value[0]}
fullWidth
error={touched?.[`${column.id}`]?.value && Boolean(errors?.[`${column.id}`]?.value)}
helperText={
<Typography
variant="caption"
sx={{
color: (theme) => theme.palette.primary.main,
fontWeight: "bold",
}}
>
نوع فیلتر: {defaultFilterTranslation}
</Typography>
}
variant="outlined"
size="small"
sx={{ my: 1, marginRight: 1 }}
/>
<TextField
id={`${column.id}.value[1]`}
name={`${column.id}.value[1]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [filterParameters.value[0], e.target.value],
})
}
onBlur={handleBlur}
error={Boolean(errors?.[`${column.id}`]?.value)}
helperText={errors?.[`${column.id}`]?.value ? errors?.[`${column.id}`]?.value.message : null}
label={<Typography>تا {column.header}</Typography>}
value={filterParameters.value[1]}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment position="end" sx={{ cursor: "pointer" }} onClick={handleOpenFilterBox}>
<FilterListIcon />
</InputAdornment>
),
}}
/>
</Box>
);
}
export default CustomTextFieldRange;

View File

@@ -5,37 +5,37 @@ import FilterBody from "@/core/components/DataTable/filter/FilterBody";
import { Box, Drawer } from "@mui/material";
function FilterColumn({ columns, user_id, page_name, table_name }) {
const [open, setOpen] = useState(false);
const [open, setOpen] = useState(false);
return (
<>
<FilterButton drawerState={open} setDrawerState={setOpen} />
<Drawer
open={open}
onClose={() => setOpen(false)}
sx={{
overflowY: "hidden",
display: "flex",
flexDirection: "column",
height: "100%",
zIndex: "1300",
}}
>
<Box sx={{ width: { xs: 300, sm: 450 } }}>
{open && (
<FilterBody
columns={columns}
drawerState={open}
setDrawerState={setOpen}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
)}
</Box>
</Drawer>
</>
);
return (
<>
<FilterButton drawerState={open} setDrawerState={setOpen} />
<Drawer
open={open}
onClose={() => setOpen(false)}
sx={{
overflowY: "hidden",
display: "flex",
flexDirection: "column",
height: "100%",
zIndex: "1300",
}}
>
<Box sx={{ width: { xs: 300, sm: 450 } }}>
{open && (
<FilterBody
columns={columns}
drawerState={open}
setDrawerState={setOpen}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
)}
</Box>
</Drawer>
</>
);
}
export default FilterColumn;

View File

@@ -3,54 +3,49 @@ import { TableHead } from "@mui/material";
import DataTable_TableHeadRow from "./TableHeadRow";
const DataTable_TableHead = ({ columnVirtualizer, table, ...rest }) => {
const {
getState,
options: {
enableStickyHeader,
layoutMode,
muiTableHeadProps,
positionToolbarAlertBanner,
},
refs: { tableHeadRef },
} = table;
const { isFullScreen, showAlertBanner } = getState();
const {
getState,
options: { enableStickyHeader, layoutMode, muiTableHeadProps, positionToolbarAlertBanner },
refs: { tableHeadRef },
} = table;
const { isFullScreen, showAlertBanner } = getState();
const tableHeadProps = {
...parseFromValuesOrFunc(muiTableHeadProps, { table }),
...rest,
};
const tableHeadProps = {
...parseFromValuesOrFunc(muiTableHeadProps, { table }),
...rest,
};
const stickyHeader = enableStickyHeader || isFullScreen;
const stickyHeader = enableStickyHeader || isFullScreen;
return (
<TableHead
{...tableHeadProps}
ref={(ref) => {
tableHeadRef.current = ref;
if (tableHeadProps?.ref) {
// @ts-ignore
tableHeadProps.ref.current = ref;
}
}}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
opacity: 0.97,
position: stickyHeader ? "sticky" : "relative",
top: stickyHeader && layoutMode?.startsWith("grid") ? 0 : undefined,
zIndex: stickyHeader ? 2 : undefined,
...parseFromValuesOrFunc(tableHeadProps?.sx, theme),
})}
>
{table.getHeaderGroups().map((headerGroup, index) => (
<DataTable_TableHeadRow
columnVirtualizer={columnVirtualizer}
headerGroup={headerGroup}
key={headerGroup.id}
table={table}
index={index}
/>
))}
</TableHead>
);
return (
<TableHead
{...tableHeadProps}
ref={(ref) => {
tableHeadRef.current = ref;
if (tableHeadProps?.ref) {
// @ts-ignore
tableHeadProps.ref.current = ref;
}
}}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
opacity: 0.97,
position: stickyHeader ? "sticky" : "relative",
top: stickyHeader && layoutMode?.startsWith("grid") ? 0 : undefined,
zIndex: stickyHeader ? 2 : undefined,
...parseFromValuesOrFunc(tableHeadProps?.sx, theme),
})}
>
{table.getHeaderGroups().map((headerGroup, index) => (
<DataTable_TableHeadRow
columnVirtualizer={columnVirtualizer}
headerGroup={headerGroup}
key={headerGroup.id}
table={table}
index={index}
/>
))}
</TableHead>
);
};
export default DataTable_TableHead;

View File

@@ -1,290 +1,244 @@
import {
getCommonMRTCellStyles,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { getCommonMRTCellStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
import { useTheme } from "@emotion/react";
import { Box, TableCell } from "@mui/material";
import { MRT_TableHeadCellSortLabel } from "material-react-table";
import { useMemo } from "react";
const DataTable_TableHeadCell = ({
columnVirtualizer,
header,
staticColumnIndex,
backgroundColor,
table,
...rest
}) => {
const theme = useTheme();
const {
getState,
options: {
columnResizeDirection,
columnResizeMode,
enableColumnActions,
enableColumnDragging,
enableColumnOrdering,
enableColumnPinning,
enableGrouping,
enableMultiSort,
layoutMode,
mrtTheme: { draggingBorderColor },
muiTableHeadCellProps,
},
refs: { tableHeadCellRefs },
setHoveredColumn,
} = table;
const {
columnSizingInfo,
density,
draggingColumn,
grouping,
hoveredColumn,
showColumnFilters,
} = getState();
const { column } = header;
const { columnDef } = column;
const { columnDefType } = columnDef;
const tableCellProps = {
...parseFromValuesOrFunc(muiTableHeadCellProps, { column, table }),
...parseFromValuesOrFunc(columnDef.muiTableHeadCellProps, {
column,
table,
}),
...rest,
};
const isColumnPinned =
enableColumnPinning &&
columnDef.columnDefType !== "group" &&
column.getIsPinned();
const showColumnActions =
(enableColumnActions || columnDef.enableColumnActions) &&
columnDef.enableColumnActions !== false;
const showDragHandle =
enableColumnDragging !== false &&
columnDef.enableColumnDragging !== false &&
(enableColumnDragging ||
(enableColumnOrdering && columnDef.enableColumnOrdering !== false) ||
(enableGrouping &&
columnDef.enableGrouping !== false &&
!grouping.includes(column.id)));
const headerPL = useMemo(() => {
let pl = 0;
if (column.getCanSort()) pl += 1;
if (showColumnActions) pl += 1.75;
if (showDragHandle) pl += 1.5;
return pl;
}, [showColumnActions, showDragHandle]);
const draggingBorders = useMemo(() => {
const showResizeBorder =
columnSizingInfo.isResizingColumn === column.id &&
columnResizeMode === "onChange" &&
!header.subHeaders.length;
const borderStyle = showResizeBorder
? `2px solid ${draggingBorderColor} !important`
: draggingColumn?.id === column.id
? `1px dashed ${theme.palette.grey[500]}`
: hoveredColumn?.id === column.id
? `2px dashed ${draggingBorderColor}`
: undefined;
if (showResizeBorder) {
return columnResizeDirection === "ltr"
? { borderRight: borderStyle }
: { borderLeft: borderStyle };
}
const draggingBorders = borderStyle
? {
borderLeft: borderStyle,
borderRight: borderStyle,
borderTop: borderStyle,
}
: undefined;
return draggingBorders;
}, [draggingColumn, hoveredColumn, columnSizingInfo.isResizingColumn]);
const handleDragEnter = (_e) => {
if (enableGrouping && hoveredColumn?.id === "drop-zone") {
setHoveredColumn(null);
}
if (enableColumnOrdering && draggingColumn && columnDefType !== "group") {
setHoveredColumn(
columnDef.enableColumnOrdering !== false ? column : null,
);
}
};
const handleDragOver = (e) => {
if (columnDef.enableColumnOrdering !== false) {
e.preventDefault();
}
};
const HeaderElement =
parseFromValuesOrFunc(columnDef.Header, {
column,
header,
table,
}) ?? columnDef.header;
const columnRelativeDepth = header.depth - column.depth;
if (columnRelativeDepth > 1) {
return null;
}
let rowSpan = 1;
if (header.isPlaceholder) {
const leafs = header.getLeafHeaders();
rowSpan = leafs[leafs.length - 1].depth - header.depth;
}
return (
<TableCell
align={
columnDefType === "group"
? "center"
: theme.direction === "rtl"
? "right"
: "left"
}
colSpan={header.colSpan}
rowSpan={rowSpan}
data-index={staticColumnIndex}
data-pinned={!!isColumnPinned || undefined}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
ref={(node) => {
if (node) {
tableHeadCellRefs.current[column.id] = node;
if (columnDefType !== "group") {
columnVirtualizer?.measureElement?.(node);
}
}
}}
{...tableCellProps}
sx={(theme) => ({
"& :hover": {
".MuiButtonBase-root": {
opacity: 1,
},
const DataTable_TableHeadCell = ({ columnVirtualizer, header, staticColumnIndex, backgroundColor, table, ...rest }) => {
const theme = useTheme();
const {
getState,
options: {
columnResizeDirection,
columnResizeMode,
enableColumnActions,
enableColumnDragging,
enableColumnOrdering,
enableColumnPinning,
enableGrouping,
enableMultiSort,
layoutMode,
mrtTheme: { draggingBorderColor },
muiTableHeadCellProps,
},
flexDirection: layoutMode?.startsWith("grid") ? "column" : undefined,
fontWeight: "bold",
overflow: "visible",
p:
density === "compact"
? "0.5rem"
: density === "comfortable"
? columnDefType === "display"
? "0.75rem"
: "1rem"
: columnDefType === "display"
? "1rem 1.25rem"
: "1.5rem",
pb:
columnDefType === "display"
? 0
: showColumnFilters || density === "compact"
? "0.4rem"
: "0.6rem",
pt:
columnDefType === "group" || density === "compact"
? "0.25rem"
: density === "comfortable"
? ".75rem"
: "1.25rem",
userSelect: enableMultiSort && column.getCanSort() ? "none" : undefined,
verticalAlign: "middle",
...getCommonMRTCellStyles({
column,
header,
table,
tableCellProps,
theme,
refs: { tableHeadCellRefs },
setHoveredColumn,
} = table;
const { columnSizingInfo, density, draggingColumn, grouping, hoveredColumn, showColumnFilters } = getState();
const { column } = header;
const { columnDef } = column;
const { columnDefType } = columnDef;
const tableCellProps = {
...parseFromValuesOrFunc(muiTableHeadCellProps, { column, table }),
...parseFromValuesOrFunc(columnDef.muiTableHeadCellProps, {
column,
table,
}),
...draggingBorders,
backgroundColor: backgroundColor,
})}
>
{tableCellProps.children ?? (
<Box
className="Mui-TableHeadCell-Content"
sx={{
alignItems: "center",
display: "flex",
flexDirection:
tableCellProps?.align === "right" ? "row-reverse" : "row",
justifyContent:
columnDefType === "group" || tableCellProps?.align === "center"
? "center"
: column.getCanResize()
? "space-between"
: "flex-start",
position: "relative",
width: "100%",
}}
>
<Box
className="Mui-TableHeadCell-Content-Labels"
onClick={column.getToggleSortingHandler()}
sx={{
alignItems: "center",
cursor:
column.getCanSort() && columnDefType !== "group"
? "pointer"
: undefined,
display: "flex",
flexDirection:
tableCellProps?.align === "right" ? "row-reverse" : "row",
overflow: columnDefType === "data" ? "hidden" : undefined,
pl:
tableCellProps?.align === "center"
? `${headerPL}rem`
: undefined,
...rest,
};
const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== "group" && column.getIsPinned();
const showColumnActions =
(enableColumnActions || columnDef.enableColumnActions) && columnDef.enableColumnActions !== false;
const showDragHandle =
enableColumnDragging !== false &&
columnDef.enableColumnDragging !== false &&
(enableColumnDragging ||
(enableColumnOrdering && columnDef.enableColumnOrdering !== false) ||
(enableGrouping && columnDef.enableGrouping !== false && !grouping.includes(column.id)));
const headerPL = useMemo(() => {
let pl = 0;
if (column.getCanSort()) pl += 1;
if (showColumnActions) pl += 1.75;
if (showDragHandle) pl += 1.5;
return pl;
}, [showColumnActions, showDragHandle]);
const draggingBorders = useMemo(() => {
const showResizeBorder =
columnSizingInfo.isResizingColumn === column.id &&
columnResizeMode === "onChange" &&
!header.subHeaders.length;
const borderStyle = showResizeBorder
? `2px solid ${draggingBorderColor} !important`
: draggingColumn?.id === column.id
? `1px dashed ${theme.palette.grey[500]}`
: hoveredColumn?.id === column.id
? `2px dashed ${draggingBorderColor}`
: undefined;
if (showResizeBorder) {
return columnResizeDirection === "ltr" ? { borderRight: borderStyle } : { borderLeft: borderStyle };
}
const draggingBorders = borderStyle
? {
borderLeft: borderStyle,
borderRight: borderStyle,
borderTop: borderStyle,
}
: undefined;
return draggingBorders;
}, [draggingColumn, hoveredColumn, columnSizingInfo.isResizingColumn]);
const handleDragEnter = (_e) => {
if (enableGrouping && hoveredColumn?.id === "drop-zone") {
setHoveredColumn(null);
}
if (enableColumnOrdering && draggingColumn && columnDefType !== "group") {
setHoveredColumn(columnDef.enableColumnOrdering !== false ? column : null);
}
};
const handleDragOver = (e) => {
if (columnDef.enableColumnOrdering !== false) {
e.preventDefault();
}
};
const HeaderElement =
parseFromValuesOrFunc(columnDef.Header, {
column,
header,
table,
}) ?? columnDef.header;
const columnRelativeDepth = header.depth - column.depth;
if (columnRelativeDepth > 1) {
return null;
}
let rowSpan = 1;
if (header.isPlaceholder) {
const leafs = header.getLeafHeaders();
rowSpan = leafs[leafs.length - 1].depth - header.depth;
}
return (
<TableCell
align={columnDefType === "group" ? "center" : theme.direction === "rtl" ? "right" : "left"}
colSpan={header.colSpan}
rowSpan={rowSpan}
data-index={staticColumnIndex}
data-pinned={!!isColumnPinned || undefined}
onDragEnter={handleDragEnter}
onDragOver={handleDragOver}
ref={(node) => {
if (node) {
tableHeadCellRefs.current[column.id] = node;
if (columnDefType !== "group") {
columnVirtualizer?.measureElement?.(node);
}
}
}}
>
<Box
className="Mui-TableHeadCell-Content-Wrapper"
sx={{
"&:hover": {
textOverflow: "clip",
{...tableCellProps}
sx={(theme) => ({
"& :hover": {
".MuiButtonBase-root": {
opacity: 1,
},
},
minWidth: `${Math.min(columnDef.header?.length ?? 0, 4)}ch`,
overflow: columnDefType === "data" ? "hidden" : undefined,
textOverflow: "ellipsis",
textAlign: "start",
color: "#fff",
fontWeight: "400",
whiteSpace: "nowrap",
}}
>
{HeaderElement}
</Box>
{column.getCanSort() && columnDefType !== "group" && (
<MRT_TableHeadCellSortLabel
sx={{
width: 20,
"& .MuiTableSortLabel-icon": {
color: `#fff !important`,
},
}}
header={header}
table={table}
/>
flexDirection: layoutMode?.startsWith("grid") ? "column" : undefined,
fontWeight: "bold",
overflow: "visible",
p:
density === "compact"
? "0.5rem"
: density === "comfortable"
? columnDefType === "display"
? "0.75rem"
: "1rem"
: columnDefType === "display"
? "1rem 1.25rem"
: "1.5rem",
pb: columnDefType === "display" ? 0 : showColumnFilters || density === "compact" ? "0.4rem" : "0.6rem",
pt:
columnDefType === "group" || density === "compact"
? "0.25rem"
: density === "comfortable"
? ".75rem"
: "1.25rem",
userSelect: enableMultiSort && column.getCanSort() ? "none" : undefined,
verticalAlign: "middle",
...getCommonMRTCellStyles({
column,
header,
table,
tableCellProps,
theme,
}),
...draggingBorders,
backgroundColor: backgroundColor,
})}
>
{tableCellProps.children ?? (
<Box
className="Mui-TableHeadCell-Content"
sx={{
alignItems: "center",
display: "flex",
flexDirection: tableCellProps?.align === "right" ? "row-reverse" : "row",
justifyContent:
columnDefType === "group" || tableCellProps?.align === "center"
? "center"
: column.getCanResize()
? "space-between"
: "flex-start",
position: "relative",
width: "100%",
}}
>
<Box
className="Mui-TableHeadCell-Content-Labels"
onClick={column.getToggleSortingHandler()}
sx={{
alignItems: "center",
cursor: column.getCanSort() && columnDefType !== "group" ? "pointer" : undefined,
display: "flex",
flexDirection: tableCellProps?.align === "right" ? "row-reverse" : "row",
overflow: columnDefType === "data" ? "hidden" : undefined,
pl: tableCellProps?.align === "center" ? `${headerPL}rem` : undefined,
}}
>
<Box
className="Mui-TableHeadCell-Content-Wrapper"
sx={{
"&:hover": {
textOverflow: "clip",
},
minWidth: `${Math.min(columnDef.header?.length ?? 0, 4)}ch`,
overflow: columnDefType === "data" ? "hidden" : undefined,
textOverflow: "ellipsis",
textAlign: "start",
color: "#fff",
fontWeight: "400",
whiteSpace: "nowrap",
}}
>
{HeaderElement}
</Box>
{column.getCanSort() && columnDefType !== "group" && (
<MRT_TableHeadCellSortLabel
sx={{
width: 20,
"& .MuiTableSortLabel-icon": {
color: `#fff !important`,
},
}}
header={header}
table={table}
/>
)}
</Box>
</Box>
)}
</Box>
</Box>
)}
</TableCell>
);
</TableCell>
);
};
export default DataTable_TableHeadCell;

View File

@@ -3,67 +3,58 @@ import { TableRow, useTheme } from "@mui/material";
import DataTable_TableHeadCell from "./TableHeadCell";
const DataTable_TableHeadRow = ({
columnVirtualizer,
headerGroup,
table,
index, // Add index prop
...rest
columnVirtualizer,
headerGroup,
table,
index, // Add index prop
...rest
}) => {
const { palette } = useTheme();
const { palette } = useTheme();
const {
options: { enableStickyHeader, layoutMode, muiTableHeadRowProps },
} = table;
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } =
columnVirtualizer ?? {};
const {
options: { enableStickyHeader, layoutMode, muiTableHeadRowProps },
} = table;
const { virtualColumns, virtualPaddingLeft, virtualPaddingRight } = columnVirtualizer ?? {};
const backgroundColor =
index % 2 === 0 ? palette.primary.main : palette.secondary.main;
const backgroundColor = index % 2 === 0 ? palette.primary.main : palette.secondary.main;
const tableRowProps = {
...parseFromValuesOrFunc(muiTableHeadRowProps, {
headerGroup,
table,
}),
...rest,
sx: (theme) => ({
// Access theme from the sx function
...(parseFromValuesOrFunc(muiTableHeadRowProps?.sx, theme) || {}),
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
position:
enableStickyHeader && layoutMode === "semantic" ? "sticky" : "relative",
top: 0,
}),
};
const tableRowProps = {
...parseFromValuesOrFunc(muiTableHeadRowProps, {
headerGroup,
table,
}),
...rest,
sx: (theme) => ({
// Access theme from the sx function
...(parseFromValuesOrFunc(muiTableHeadRowProps?.sx, theme) || {}),
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
position: enableStickyHeader && layoutMode === "semantic" ? "sticky" : "relative",
top: 0,
}),
};
return (
<TableRow {...tableRowProps}>
{virtualPaddingLeft && (
<th style={{ display: "flex", width: virtualPaddingLeft }} />
)}
{(virtualColumns ?? headerGroup.headers).map(
(headerOrVirtualHeader, staticColumnIndex) => {
const header = columnVirtualizer
? headerGroup.headers[headerOrVirtualHeader.index]
: headerOrVirtualHeader;
return (
<TableRow {...tableRowProps}>
{virtualPaddingLeft && <th style={{ display: "flex", width: virtualPaddingLeft }} />}
{(virtualColumns ?? headerGroup.headers).map((headerOrVirtualHeader, staticColumnIndex) => {
const header = columnVirtualizer
? headerGroup.headers[headerOrVirtualHeader.index]
: headerOrVirtualHeader;
return header ? (
<DataTable_TableHeadCell
columnVirtualizer={columnVirtualizer}
header={header}
backgroundColor={backgroundColor}
key={header.id}
staticColumnIndex={staticColumnIndex}
table={table}
/>
) : null;
},
)}
{virtualPaddingRight && (
<th style={{ display: "flex", width: virtualPaddingRight }} />
)}
</TableRow>
);
return header ? (
<DataTable_TableHeadCell
columnVirtualizer={columnVirtualizer}
header={header}
backgroundColor={backgroundColor}
key={header.id}
staticColumnIndex={staticColumnIndex}
table={table}
/>
) : null;
})}
{virtualPaddingRight && <th style={{ display: "flex", width: virtualPaddingRight }} />}
</TableRow>
);
};
export default DataTable_TableHeadRow;

View File

@@ -8,36 +8,31 @@ import HideOrShowAll from "@/core/components/DataTable/hide/HideOrShowAll";
import ScrollBox from "../../ScrollBox";
function HideBody({ columns, drawerState, setDrawerState }) {
const { hideData, setHideData } = useDataTable();
const { hideData, setHideData } = useDataTable();
return (
<Drawer
open={drawerState}
onClose={() => setDrawerState(false)}
sx={{
overflowY: "hidden",
display: "flex",
flexDirection: "column",
height: "100%",
zIndex: "1300",
}}
>
<HideHeader setDrawerState={setDrawerState} />
<HideOrShowAll hideData={hideData} setHideData={setHideData} />
<ScrollBox>
<Box sx={{ px: 1, py: 2, display: "flex", flexDirection: "column" }}>
{columns.map((column) => (
<HideBodyField
key={column.id}
column={column}
hideData={hideData}
setHideData={setHideData}
/>
))}
</Box>
</ScrollBox>
</Drawer>
);
return (
<Drawer
open={drawerState}
onClose={() => setDrawerState(false)}
sx={{
overflowY: "hidden",
display: "flex",
flexDirection: "column",
height: "100%",
zIndex: "1300",
}}
>
<HideHeader setDrawerState={setDrawerState} />
<HideOrShowAll hideData={hideData} setHideData={setHideData} />
<ScrollBox>
<Box sx={{ px: 1, py: 2, display: "flex", flexDirection: "column" }}>
{columns.map((column) => (
<HideBodyField key={column.id} column={column} hideData={hideData} setHideData={setHideData} />
))}
</Box>
</ScrollBox>
</Drawer>
);
}
export default HideBody;

View File

@@ -3,78 +3,74 @@ import { SimpleTreeView } from "@mui/x-tree-view";
import { TreeItem, treeItemClasses } from "@mui/x-tree-view/TreeItem";
const CustomTreeItem = styled(TreeItem)(({ theme }) => ({
[`& .${treeItemClasses.content}`]: {
padding: theme.spacing(0.5, 0.5),
margin: theme.spacing(0.2, 0),
gap: 0,
},
[`& .${treeItemClasses.iconContainer}`]: {
"& .close": {
opacity: 0.3,
[`& .${treeItemClasses.content}`]: {
padding: theme.spacing(0.5, 0.5),
margin: theme.spacing(0.2, 0),
gap: 0,
},
[`& .${treeItemClasses.iconContainer}`]: {
"& .close": {
opacity: 0.3,
},
},
[`& .${treeItemClasses.groupTransition}`]: {
marginLeft: 16,
paddingLeft: 16,
borderLeft: `1px dashed ${alpha(theme.palette.text.primary, 0.4)}`,
},
},
[`& .${treeItemClasses.groupTransition}`]: {
marginLeft: 16,
paddingLeft: 16,
borderLeft: `1px dashed ${alpha(theme.palette.text.primary, 0.4)}`,
},
}));
function HideBodyField({ column, hideData, setHideData }) {
const handleCheckboxChange = () => {
setHideData((prevData) => {
const updateHideData = (data, id) => {
if (data.hasOwnProperty(id)) {
return { ...data, [id]: !data[id] };
const handleCheckboxChange = () => {
setHideData((prevData) => {
const updateHideData = (data, id) => {
if (data.hasOwnProperty(id)) {
return { ...data, [id]: !data[id] };
}
const updatedData = { ...data };
for (const key in data) {
if (data[key] && typeof data[key] === "object") {
updatedData[key] = updateHideData(data[key], id);
}
}
return updatedData;
};
return updateHideData(prevData, column.id);
});
};
const labelContent = (() => {
if (typeof hideData[column.id] === "boolean") {
return (
<Box sx={{ display: "flex", alignItems: "center" }}>
<Checkbox checked={hideData[column.id]} onChange={handleCheckboxChange} name={column.id} />
<Typography variant="subtitle1">{column.header}</Typography>
</Box>
);
} else {
return (
<Box sx={{ display: "flex", alignItems: "center", p: 1 }}>
<Typography variant="subtitle1">{column.header}</Typography>
</Box>
);
}
const updatedData = { ...data };
for (const key in data) {
if (data[key] && typeof data[key] === "object") {
updatedData[key] = updateHideData(data[key], id);
}
}
return updatedData;
};
})();
return updateHideData(prevData, column.id);
});
};
const labelContent = (() => {
if (typeof hideData[column.id] === "boolean") {
return (
<Box sx={{ display: "flex", alignItems: "center" }}>
<Checkbox
checked={hideData[column.id]}
onChange={handleCheckboxChange}
name={column.id}
/>
<Typography variant="subtitle1">{column.header}</Typography>
</Box>
);
} else {
return (
<Box sx={{ display: "flex", alignItems: "center", p: 1 }}>
<Typography variant="subtitle1">{column.header}</Typography>
</Box>
);
}
})();
return (
<SimpleTreeView disableSelection>
<CustomTreeItem itemId={column.id} label={labelContent}>
{column.columns?.map((subColumn) => (
<HideBodyField
key={subColumn.id}
column={subColumn}
hideData={hideData[column.id]}
setHideData={setHideData}
/>
))}
</CustomTreeItem>
</SimpleTreeView>
);
return (
<SimpleTreeView disableSelection>
<CustomTreeItem itemId={column.id} label={labelContent}>
{column.columns?.map((subColumn) => (
<HideBodyField
key={subColumn.id}
column={subColumn}
hideData={hideData[column.id]}
setHideData={setHideData}
/>
))}
</CustomTreeItem>
</SimpleTreeView>
);
}
export default HideBodyField;

View File

@@ -5,33 +5,31 @@ import useDataTable from "@/lib/hooks/useDataTable";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
function HideButton({ drawerState, setDrawerState }) {
const { hideData } = useDataTable();
const flattenHideData = flattenObjectOfObjects(hideData);
const falseCount = Object.values(flattenHideData).filter(
(value) => value === false,
).length;
const { hideData } = useDataTable();
const flattenHideData = flattenObjectOfObjects(hideData);
const falseCount = Object.values(flattenHideData).filter((value) => value === false).length;
return (
<Tooltip title="نمایش/مخفی کردن ستون ها">
<IconButton
onClick={() => {
setDrawerState(!drawerState);
}}
aria-label="hide table column"
>
<Badge
badgeContent={falseCount}
color="primary"
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<ViewColumnIcon />
</Badge>
</IconButton>
</Tooltip>
);
return (
<Tooltip title="نمایش/مخفی کردن ستون ها">
<IconButton
onClick={() => {
setDrawerState(!drawerState);
}}
aria-label="hide table column"
>
<Badge
badgeContent={falseCount}
color="primary"
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
>
<ViewColumnIcon />
</Badge>
</IconButton>
</Tooltip>
);
}
export default HideButton;

View File

@@ -5,31 +5,30 @@ import CancelIcon from "@mui/icons-material/Cancel";
import ViewColumnIcon from "@mui/icons-material/ViewColumn";
function FilterHeader({ setDrawerState }) {
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: "#155175",
boxShadow:
"rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<ViewColumnIcon sx={{ color: "#fff", mr: 1 }} />
<Typography variant="h6" sx={{ color: "#fff" }}>
نمایش/مخفی کردن ستون ها
</Typography>
</Box>
<IconButton sx={{ color: "#fff" }} onClick={() => setDrawerState(false)}>
<CancelIcon sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
);
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: "#155175",
boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<ViewColumnIcon sx={{ color: "#fff", mr: 1 }} />
<Typography variant="h6" sx={{ color: "#fff" }}>
نمایش/مخفی کردن ستون ها
</Typography>
</Box>
<IconButton sx={{ color: "#fff" }} onClick={() => setDrawerState(false)}>
<CancelIcon sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
);
}
export default FilterHeader;

View File

@@ -5,66 +5,66 @@ import VisibilityIcon from "@mui/icons-material/Visibility";
import VisibilityOffIcon from "@mui/icons-material/VisibilityOff";
const setAllValues = (obj, value) => {
const result = {};
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
result[key] = setAllValues(obj[key], value);
} else {
result[key] = value;
const result = {};
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
result[key] = setAllValues(obj[key], value);
} else {
result[key] = value;
}
}
}
return result;
return result;
};
const allValuesAre = (obj, value) => {
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
if (!allValuesAre(obj[key], value)) {
return false;
}
} else if (obj[key] !== value) {
return false;
for (const key in obj) {
if (typeof obj[key] === "object" && obj[key] !== null) {
if (!allValuesAre(obj[key], value)) {
return false;
}
} else if (obj[key] !== value) {
return false;
}
}
}
return true;
return true;
};
function HideOrShowAll({ hideData, setHideData }) {
const handleShowAll = () => {
const newHideData = setAllValues(hideData, true);
setHideData(newHideData);
};
const handleShowAll = () => {
const newHideData = setAllValues(hideData, true);
setHideData(newHideData);
};
const handleHideAll = () => {
const newHideData = setAllValues(hideData, false);
setHideData(newHideData);
};
const handleHideAll = () => {
const newHideData = setAllValues(hideData, false);
setHideData(newHideData);
};
const allHidden = allValuesAre(hideData, false);
const allVisible = allValuesAre(hideData, true);
const allHidden = allValuesAre(hideData, false);
const allVisible = allValuesAre(hideData, true);
return (
<Box sx={{ my: 1, display: "flex" }}>
<Button
sx={{ flex: 1 }}
color="info"
disabled={allVisible}
startIcon={<VisibilityIcon />}
onClick={handleShowAll}
>
نمایش همه
</Button>
<Button
sx={{ flex: 1 }}
color="error"
disabled={allHidden}
startIcon={<VisibilityOffIcon />}
onClick={handleHideAll}
>
مخفی کردن همه
</Button>
</Box>
);
return (
<Box sx={{ my: 1, display: "flex" }}>
<Button
sx={{ flex: 1 }}
color="info"
disabled={allVisible}
startIcon={<VisibilityIcon />}
onClick={handleShowAll}
>
نمایش همه
</Button>
<Button
sx={{ flex: 1 }}
color="error"
disabled={allHidden}
startIcon={<VisibilityOffIcon />}
onClick={handleHideAll}
>
مخفی کردن همه
</Button>
</Box>
);
}
export default HideOrShowAll;

View File

@@ -5,20 +5,20 @@ import HideButton from "@/core/components/DataTable/hide/HideButton";
import HideBody from "@/core/components/DataTable/hide/HideBody";
function HideColumn({ columns, user_id, page_name, table_name }) {
const [open, setOpen] = useState(false);
return (
<>
<HideButton drawerState={open} setDrawerState={setOpen} />
<HideBody
columns={columns}
drawerState={open}
setDrawerState={setOpen}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
</>
);
const [open, setOpen] = useState(false);
return (
<>
<HideButton drawerState={open} setDrawerState={setOpen} />
<HideBody
columns={columns}
drawerState={open}
setDrawerState={setOpen}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
</>
);
}
export default HideColumn;

View File

@@ -2,17 +2,17 @@ import DataTable_Main from "./Main";
import DataTableProvider from "@/lib/contexts/DataTable";
const DataTable = (props) => {
return (
<DataTableProvider
user_id={props.user_id}
page_name={props.page_name}
table_name={props.table_name}
columns={props.columns}
initialSort={props.sorting}
>
<DataTable_Main {...props} />
</DataTableProvider>
);
return (
<DataTableProvider
user_id={props.user_id}
page_name={props.page_name}
table_name={props.table_name}
columns={props.columns}
initialSort={props.sorting}
>
<DataTable_Main {...props} />
</DataTableProvider>
);
};
export default DataTable;

View File

@@ -1,92 +1,91 @@
export const FA_DATATABLE_LOCALIZATION = {
actions: "عملیات",
and: "و",
cancel: "لغو",
changeFilterMode: "تغییر حالت فیلتر",
changeSearchMode: "تغییر حالت جستجو",
clearFilter: "پاک کردن فیلتر",
clearSearch: "پاک کردن جستجو",
clearSort: "پاک کردن مرتب سازی",
clickToCopy: "کلیک برای کپی",
collapse: "جمع شدن",
collapseAll: "جمع شدن همه",
columnActions: "عملیات ستون",
copiedToClipboard: "کپی شد",
dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}",
edit: "ویرایش",
expand: "باز شدن",
expandAll: "باز شدن همه",
filterArrIncludes: "شامل",
filterArrIncludesAll: "شامل همه",
filterArrIncludesSome: "شامل",
filterBetween: "میان",
filterBetweenInclusive: "میان با احتساب هر دو",
filterByColumn: "فیلتر بر اساس {column}",
filterContains: "شامل",
filterEmpty: "خالی",
filterEndsWith: "به پایان می‌رسد با",
filterEquals: "برابر",
filterEqualsString: "برابر",
filterFuzzy: "نزدیک",
filterGreaterThan: "بزرگتر از",
filterGreaterThanOrEqualTo: "بزرگتر یا مساوی",
filterInNumberRange: "میان",
filterIncludesString: "شامل",
filterIncludesStringSensitive: "شامل",
filterLessThan: "کوچکتر از",
filterLessThanOrEqualTo: "کوچکتر یا مساوی",
filterMode: "حالت فیلتر: {filterType}",
filterNotEmpty: "غیر خالی",
filterNotEquals: "نا برابر",
filterStartsWith: "شروع می‌شود با",
filterWeakEquals: "برابر",
filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}",
goToFirstPage: "رفتن به صفحه اول",
goToLastPage: "رفتن به صفحه آخر",
goToNextPage: "رفتن به صفحه بعدی",
goToPreviousPage: "رفتن به صفحه قبلی",
grab: "گرفتن",
groupByColumn: "گروه بندی بر اساس {column}",
groupedBy: "گروه بندی شده بر اساس",
hideAll: "پنهان کردن همه",
hideColumn: "پنهان کردن ستون {column}",
max: "حداکثر",
min: "حداقل",
move: "انتقال",
noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد",
noResultsFound: "نتیجه‌ای یافت نشد",
of: "از",
or: "یا",
pinToLeft: "چسباندن به سمت چپ",
pinToRight: "چسباندن به سمت راست",
resetColumnSize: "بازنشانی اندازه ستون",
resetOrder: "بازنشانی ترتیب",
rowActions: "عملیات ردیف",
rowNumber: "#",
rowNumbers: "شماره ردیف",
rowsPerPage: "ردیف در هر صفحه",
save: "ذخیره",
search: "جستجو",
selectedCountOfRowCountRowsSelected:
"{selectedCount} از {rowCount} ردیف انتخاب شده",
select: "انتخاب",
showAll: "نمایش همه",
showAllColumns: "نمایش همه ستون‌ها",
showHideColumns: "نمایش/مخفی کردن ستون‌ها",
showHideFilters: "نمایش/مخفی کردن فیلترها",
showHideSearch: "نمایش/مخفی کردن جستجو",
sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی",
sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی",
sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی",
sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی",
thenBy: "، سپس بر اساس ",
toggleDensity: "تغییر تراکم",
toggleFullScreen: "تغییر حالت تمام صفحه",
toggleSelectAll: "انتخاب/عدم انتخاب همه",
toggleSelectRow: "انتخاب/عدم انتخاب ردیف",
toggleVisibility: "تغییر پیدا/پنهان",
ungroupByColumn: "لغو گروه بندی بر اساس {column}",
unpin: "رها کردن",
unpinAll: "رها کردن همه",
unsorted: "بدون مرتب سازی",
actions: "عملیات",
and: "و",
cancel: "لغو",
changeFilterMode: "تغییر حالت فیلتر",
changeSearchMode: "تغییر حالت جستجو",
clearFilter: "پاک کردن فیلتر",
clearSearch: "پاک کردن جستجو",
clearSort: "پاک کردن مرتب سازی",
clickToCopy: "کلیک برای کپی",
collapse: "جمع شدن",
collapseAll: "جمع شدن همه",
columnActions: "عملیات ستون",
copiedToClipboard: "کپی شد",
dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}",
edit: "ویرایش",
expand: "باز شدن",
expandAll: "باز شدن همه",
filterArrIncludes: "شامل",
filterArrIncludesAll: "شامل همه",
filterArrIncludesSome: "شامل",
filterBetween: "میان",
filterBetweenInclusive: "میان با احتساب هر دو",
filterByColumn: "فیلتر بر اساس {column}",
filterContains: "شامل",
filterEmpty: "خالی",
filterEndsWith: "به پایان می‌رسد با",
filterEquals: "برابر",
filterEqualsString: "برابر",
filterFuzzy: "نزدیک",
filterGreaterThan: "بزرگتر از",
filterGreaterThanOrEqualTo: "بزرگتر یا مساوی",
filterInNumberRange: "میان",
filterIncludesString: "شامل",
filterIncludesStringSensitive: "شامل",
filterLessThan: "کوچکتر از",
filterLessThanOrEqualTo: "کوچکتر یا مساوی",
filterMode: "حالت فیلتر: {filterType}",
filterNotEmpty: "غیر خالی",
filterNotEquals: "نا برابر",
filterStartsWith: "شروع می‌شود با",
filterWeakEquals: "برابر",
filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}",
goToFirstPage: "رفتن به صفحه اول",
goToLastPage: "رفتن به صفحه آخر",
goToNextPage: "رفتن به صفحه بعدی",
goToPreviousPage: "رفتن به صفحه قبلی",
grab: "گرفتن",
groupByColumn: "گروه بندی بر اساس {column}",
groupedBy: "گروه بندی شده بر اساس",
hideAll: "پنهان کردن همه",
hideColumn: "پنهان کردن ستون {column}",
max: "حداکثر",
min: "حداقل",
move: "انتقال",
noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد",
noResultsFound: "نتیجه‌ای یافت نشد",
of: "از",
or: "یا",
pinToLeft: "چسباندن به سمت چپ",
pinToRight: "چسباندن به سمت راست",
resetColumnSize: "بازنشانی اندازه ستون",
resetOrder: "بازنشانی ترتیب",
rowActions: "عملیات ردیف",
rowNumber: "#",
rowNumbers: "شماره ردیف",
rowsPerPage: "ردیف در هر صفحه",
save: "ذخیره",
search: "جستجو",
selectedCountOfRowCountRowsSelected: "{selectedCount} از {rowCount} ردیف انتخاب شده",
select: "انتخاب",
showAll: "نمایش همه",
showAllColumns: "نمایش همه ستون‌ها",
showHideColumns: "نمایش/مخفی کردن ستون‌ها",
showHideFilters: "نمایش/مخفی کردن فیلترها",
showHideSearch: "نمایش/مخفی کردن جستجو",
sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی",
sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی",
sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی",
sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی",
thenBy: "، سپس بر اساس ",
toggleDensity: "تغییر تراکم",
toggleFullScreen: "تغییر حالت تمام صفحه",
toggleSelectAll: "انتخاب/عدم انتخاب همه",
toggleSelectRow: "انتخاب/عدم انتخاب ردیف",
toggleVisibility: "تغییر پیدا/پنهان",
ungroupByColumn: "لغو گروه بندی بر اساس {column}",
unpin: "رها کردن",
unpinAll: "رها کردن همه",
unsorted: "بدون مرتب سازی",
};

View File

@@ -1,49 +1,38 @@
import { Box, IconButton, ListItemIcon, MenuItem } from "@mui/material";
const DataTable_ActionMenuItem = ({
icon,
label,
onOpenSubMenu,
table,
...rest
}) => {
const {
options: {
icons: { ArrowRightIcon },
},
} = table;
const DataTable_ActionMenuItem = ({ icon, label, onOpenSubMenu, table, ...rest }) => {
const {
options: {
icons: { ArrowRightIcon },
},
} = table;
return (
<MenuItem
sx={{
alignItems: "center",
justifyContent: "space-between",
minWidth: "120px",
my: 0,
py: "6px",
}}
{...rest}
>
<Box
sx={{
alignItems: "center",
display: "flex",
}}
>
<ListItemIcon>{icon}</ListItemIcon>
{label}
</Box>
{onOpenSubMenu && (
<IconButton
onClick={onOpenSubMenu}
onMouseEnter={onOpenSubMenu}
size="small"
sx={{ p: 0 }}
return (
<MenuItem
sx={{
alignItems: "center",
justifyContent: "space-between",
minWidth: "120px",
my: 0,
py: "6px",
}}
{...rest}
>
<ArrowRightIcon />
</IconButton>
)}
</MenuItem>
);
<Box
sx={{
alignItems: "center",
display: "flex",
}}
>
<ListItemIcon>{icon}</ListItemIcon>
{label}
</Box>
{onOpenSubMenu && (
<IconButton onClick={onOpenSubMenu} onMouseEnter={onOpenSubMenu} size="small" sx={{ p: 0 }}>
<ArrowRightIcon />
</IconButton>
)}
</MenuItem>
);
};
export default DataTable_ActionMenuItem;

View File

@@ -3,94 +3,92 @@ import { Menu } from "@mui/material";
import DataTable_ActionMenuItem from "./ActionMenuItem";
const DataTable_CellActionMenu = ({ table, ...rest }) => {
const {
getState,
options: {
editDisplayMode,
enableClickToCopy,
enableEditing,
icons: { ContentCopy, EditIcon },
localization,
mrtTheme: { menuBackgroundColor },
renderCellActionMenuItems,
},
refs: { actionCellRef },
} = table;
const { actionCell, density } = getState();
const cell = actionCell || null;
const { row } = cell;
const { column } = cell;
const { columnDef } = column;
const {
getState,
options: {
editDisplayMode,
enableClickToCopy,
enableEditing,
icons: { ContentCopy, EditIcon },
localization,
mrtTheme: { menuBackgroundColor },
renderCellActionMenuItems,
},
refs: { actionCellRef },
} = table;
const { actionCell, density } = getState();
const cell = actionCell || null;
const { row } = cell;
const { column } = cell;
const { columnDef } = column;
const handleClose = (event) => {
event?.stopPropagation();
table.setActionCell(null);
actionCellRef.current = null;
};
const handleClose = (event) => {
event?.stopPropagation();
table.setActionCell(null);
actionCellRef.current = null;
};
const internalMenuItems = [
(parseFromValuesOrFunc(enableClickToCopy, cell) === "context-menu" ||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) ===
"context-menu") && (
<DataTable_ActionMenuItem
icon={<ContentCopy />}
key={"mrt-copy"}
label={localization.copy}
onClick={(event) => {
event.stopPropagation();
navigator.clipboard.writeText(cell.getValue());
handleClose();
}}
table={table}
/>
),
parseFromValuesOrFunc(enableEditing, row) && editDisplayMode === "cell" && (
<DataTable_ActionMenuItem
icon={<EditIcon />}
key={"mrt-edit"}
label={localization.edit}
onClick={() => {
openEditingCell({ cell, table });
handleClose();
}}
table={table}
/>
),
].filter(Boolean);
const internalMenuItems = [
(parseFromValuesOrFunc(enableClickToCopy, cell) === "context-menu" ||
parseFromValuesOrFunc(columnDef.enableClickToCopy, cell) === "context-menu") && (
<DataTable_ActionMenuItem
icon={<ContentCopy />}
key={"mrt-copy"}
label={localization.copy}
onClick={(event) => {
event.stopPropagation();
navigator.clipboard.writeText(cell.getValue());
handleClose();
}}
table={table}
/>
),
parseFromValuesOrFunc(enableEditing, row) && editDisplayMode === "cell" && (
<DataTable_ActionMenuItem
icon={<EditIcon />}
key={"mrt-edit"}
label={localization.edit}
onClick={() => {
openEditingCell({ cell, table });
handleClose();
}}
table={table}
/>
),
].filter(Boolean);
const renderActionProps = {
cell,
closeMenu: handleClose,
column,
internalMenuItems,
row,
table,
};
const renderActionProps = {
cell,
closeMenu: handleClose,
column,
internalMenuItems,
row,
table,
};
const menuItems =
columnDef.renderCellActionMenuItems?.(renderActionProps) ??
renderCellActionMenuItems?.(renderActionProps);
const menuItems =
columnDef.renderCellActionMenuItems?.(renderActionProps) ?? renderCellActionMenuItems?.(renderActionProps);
return (
(!!menuItems?.length || !!internalMenuItems?.length) && (
<Menu
MenuListProps={{
dense: density === "compact",
sx: {
backgroundColor: menuBackgroundColor,
},
}}
anchorEl={actionCellRef.current}
disableScrollLock
onClick={(event) => event.stopPropagation()}
onClose={handleClose}
open={!!cell}
transformOrigin={{ horizontal: -100, vertical: 8 }}
{...rest}
>
{menuItems ?? internalMenuItems}
</Menu>
)
);
return (
(!!menuItems?.length || !!internalMenuItems?.length) && (
<Menu
MenuListProps={{
dense: density === "compact",
sx: {
backgroundColor: menuBackgroundColor,
},
}}
anchorEl={actionCellRef.current}
disableScrollLock
onClick={(event) => event.stopPropagation()}
onClose={handleClose}
open={!!cell}
transformOrigin={{ horizontal: -100, vertical: 8 }}
{...rest}
>
{menuItems ?? internalMenuItems}
</Menu>
)
);
};
export default DataTable_CellActionMenu;

View File

@@ -5,32 +5,32 @@ import useTableSetting from "@/lib/hooks/useTableSetting";
import useDataTable from "@/lib/hooks/useDataTable";
function ResetStorage({ user_id, page_name, table_name }) {
const { resetAction } = useTableSetting();
const { isAnyDirty } = useDataTable();
const reset = () => {
resetAction(user_id, page_name, table_name);
};
const { resetAction } = useTableSetting();
const { isAnyDirty } = useDataTable();
const reset = () => {
resetAction(user_id, page_name, table_name);
};
return (
<Tooltip title="بازنشانی اطلاعات">
<IconButton onClick={reset} aria-label="reset table data">
{isAnyDirty ? (
<Badge
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
color="primary"
variant="dot"
>
<AutorenewIcon />
</Badge>
) : (
<AutorenewIcon />
)}
</IconButton>
</Tooltip>
);
return (
<Tooltip title="بازنشانی اطلاعات">
<IconButton onClick={reset} aria-label="reset table data">
{isAnyDirty ? (
<Badge
anchorOrigin={{
vertical: "top",
horizontal: "left",
}}
color="primary"
variant="dot"
>
<AutorenewIcon />
</Badge>
) : (
<AutorenewIcon />
)}
</IconButton>
</Tooltip>
);
}
export default ResetStorage;

View File

@@ -5,98 +5,96 @@ import DataTable_TopToolbar from "../toolbar/TopToolbar";
import DataTable_TableContainer from "./TableContainer";
const DataTable_Paper = ({
table,
table_name,
columns,
user_id,
page_name,
mutate,
need_filter,
table_url,
table_title,
setFilterData,
...rest
table,
table_name,
columns,
user_id,
page_name,
mutate,
need_filter,
table_url,
table_title,
setFilterData,
...rest
}) => {
const {
getState,
options: {
enableBottomToolbar,
enableTopToolbar,
mrtTheme: { baseBackgroundColor },
muiTablePaperProps,
renderBottomToolbar,
renderTopToolbar,
},
refs: { tablePaperRef },
} = table;
const {
getState,
options: {
enableBottomToolbar,
enableTopToolbar,
mrtTheme: { baseBackgroundColor },
muiTablePaperProps,
renderBottomToolbar,
renderTopToolbar,
},
refs: { tablePaperRef },
} = table;
const { isFullScreen } = getState();
const { isFullScreen } = getState();
const paperProps = {
...parseFromValuesOrFunc(muiTablePaperProps, { table }),
...rest,
};
const paperProps = {
...parseFromValuesOrFunc(muiTablePaperProps, { table }),
...rest,
};
return (
<Paper
elevation={0}
{...paperProps}
ref={(ref) => {
tablePaperRef.current = ref;
if (paperProps?.ref) {
//@ts-ignore
paperProps.ref.current = ref;
}
}}
style={{
...(isFullScreen
? {
bottom: 0,
height: "100dvh",
left: 0,
margin: 0,
maxHeight: "100dvh",
maxWidth: "100dvw",
padding: 0,
position: "fixed",
right: 0,
top: 0,
width: "100dvw",
zIndex: 999,
}
: {}),
...paperProps?.style,
}}
sx={(theme) => ({
backgroundColor: baseBackgroundColor,
backgroundImage: "unset",
overflow: "hidden",
transition: "all 100ms ease-in-out",
...parseFromValuesOrFunc(paperProps?.sx, theme),
})}
>
{enableTopToolbar &&
(parseFromValuesOrFunc(renderTopToolbar, { table }) ?? (
<DataTable_TopToolbar
need_filter={need_filter}
table={table}
mutate={mutate}
columns={columns}
table_url={table_url}
user_id={user_id}
page_name={page_name}
table_name={table_name}
table_title={table_title}
setFilterData={setFilterData}
return (
<Paper
elevation={0}
{...paperProps}
/>
))}
<DataTable_TableContainer table={table} />
{enableBottomToolbar &&
(parseFromValuesOrFunc(renderBottomToolbar, { table }) ?? (
<DataTable_BottomToolbar table={table} />
))}
</Paper>
);
ref={(ref) => {
tablePaperRef.current = ref;
if (paperProps?.ref) {
//@ts-ignore
paperProps.ref.current = ref;
}
}}
style={{
...(isFullScreen
? {
bottom: 0,
height: "100dvh",
left: 0,
margin: 0,
maxHeight: "100dvh",
maxWidth: "100dvw",
padding: 0,
position: "fixed",
right: 0,
top: 0,
width: "100dvw",
zIndex: 999,
}
: {}),
...paperProps?.style,
}}
sx={(theme) => ({
backgroundColor: baseBackgroundColor,
backgroundImage: "unset",
overflow: "hidden",
transition: "all 100ms ease-in-out",
...parseFromValuesOrFunc(paperProps?.sx, theme),
})}
>
{enableTopToolbar &&
(parseFromValuesOrFunc(renderTopToolbar, { table }) ?? (
<DataTable_TopToolbar
need_filter={need_filter}
table={table}
mutate={mutate}
columns={columns}
table_url={table_url}
user_id={user_id}
page_name={page_name}
table_name={table_name}
table_title={table_title}
setFilterData={setFilterData}
{...paperProps}
/>
))}
<DataTable_TableContainer table={table} />
{enableBottomToolbar &&
(parseFromValuesOrFunc(renderBottomToolbar, { table }) ?? <DataTable_BottomToolbar table={table} />)}
</Paper>
);
};
export default DataTable_Paper;

View File

@@ -2,75 +2,72 @@ import { parseCSSVarId, parseFromValuesOrFunc } from "@/core/utils/utils";
import { Table } from "@mui/material";
import { useMRT_ColumnVirtualizer } from "material-react-table";
import { useMemo } from "react";
import DataTable_TableBody, {
Memo_DataTable_TableBody,
} from "../body/TableBody";
import DataTable_TableBody, { Memo_DataTable_TableBody } from "../body/TableBody";
import DataTable_TableHead from "../head/TableHead";
const DataTable_Table = ({ table, ...rest }) => {
const {
getFlatHeaders,
getState,
options: {
columns,
enableStickyHeader,
enableTableFooter,
enableTableHead,
layoutMode,
memoMode,
muiTableProps,
renderCaption,
},
} = table;
const { columnSizing, columnSizingInfo, columnVisibility, isFullScreen } =
getState();
const {
getFlatHeaders,
getState,
options: {
columns,
enableStickyHeader,
enableTableFooter,
enableTableHead,
layoutMode,
memoMode,
muiTableProps,
renderCaption,
},
} = table;
const { columnSizing, columnSizingInfo, columnVisibility, isFullScreen } = getState();
const tableProps = {
...parseFromValuesOrFunc(muiTableProps, { table }),
...rest,
};
const tableProps = {
...parseFromValuesOrFunc(muiTableProps, { table }),
...rest,
};
const Caption = parseFromValuesOrFunc(renderCaption, { table });
const Caption = parseFromValuesOrFunc(renderCaption, { table });
const columnSizeVars = useMemo(() => {
const headers = getFlatHeaders();
const colSizes = {};
for (let i = 0; i < headers.length; i++) {
const header = headers[i];
const colSize = header.getSize();
colSizes[`--header-${parseCSSVarId(header.id)}-size`] = colSize;
colSizes[`--col-${parseCSSVarId(header.column.id)}-size`] = colSize;
}
return colSizes;
}, [columns, columnSizing, columnSizingInfo, columnVisibility]);
const columnSizeVars = useMemo(() => {
const headers = getFlatHeaders();
const colSizes = {};
for (let i = 0; i < headers.length; i++) {
const header = headers[i];
const colSize = header.getSize();
colSizes[`--header-${parseCSSVarId(header.id)}-size`] = colSize;
colSizes[`--col-${parseCSSVarId(header.column.id)}-size`] = colSize;
}
return colSizes;
}, [columns, columnSizing, columnSizingInfo, columnVisibility]);
const columnVirtualizer = useMRT_ColumnVirtualizer(table);
const columnVirtualizer = useMRT_ColumnVirtualizer(table);
const commonTableGroupProps = {
columnVirtualizer,
table,
};
const commonTableGroupProps = {
columnVirtualizer,
table,
};
return (
<Table
stickyHeader={enableStickyHeader || isFullScreen}
{...tableProps}
style={{ ...columnSizeVars, ...tableProps?.style }}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
position: "relative",
...parseFromValuesOrFunc(tableProps?.sx, theme),
})}
>
{!!Caption && <caption>{Caption}</caption>}
{enableTableHead && <DataTable_TableHead {...commonTableGroupProps} />}
{memoMode === "table-body" || columnSizingInfo.isResizingColumn ? (
<Memo_DataTable_TableBody {...commonTableGroupProps} />
) : (
<DataTable_TableBody {...commonTableGroupProps} />
)}
{/* {enableTableFooter && <MRT_TableFooter {...commonTableGroupProps} />} */}
</Table>
);
return (
<Table
stickyHeader={enableStickyHeader || isFullScreen}
{...tableProps}
style={{ ...columnSizeVars, ...tableProps?.style }}
sx={(theme) => ({
display: layoutMode?.startsWith("grid") ? "grid" : undefined,
position: "relative",
...parseFromValuesOrFunc(tableProps?.sx, theme),
})}
>
{!!Caption && <caption>{Caption}</caption>}
{enableTableHead && <DataTable_TableHead {...commonTableGroupProps} />}
{memoMode === "table-body" || columnSizingInfo.isResizingColumn ? (
<Memo_DataTable_TableBody {...commonTableGroupProps} />
) : (
<DataTable_TableBody {...commonTableGroupProps} />
)}
{/* {enableTableFooter && <MRT_TableFooter {...commonTableGroupProps} />} */}
</Table>
);
};
export default DataTable_Table;

View File

@@ -5,80 +5,68 @@ import DataTable_CellActionMenu from "../menus/CellActionMenu";
import DataTable_Table from "./Table";
import DataTable_TableLoadingOverlay from "./TableLoadingOverlay";
const useIsomorphicLayoutEffect =
typeof window !== "undefined" ? useLayoutEffect : useEffect;
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
const DataTable_TableContainer = ({ table, ...rest }) => {
const {
getState,
options: { enableCellActions, enableStickyHeader, muiTableContainerProps },
refs: { bottomToolbarRef, tableContainerRef, topToolbarRef },
} = table;
const { actionCell, isFullScreen, isLoading, showLoadingOverlay } =
getState();
const {
getState,
options: { enableCellActions, enableStickyHeader, muiTableContainerProps },
refs: { bottomToolbarRef, tableContainerRef, topToolbarRef },
} = table;
const { actionCell, isFullScreen, isLoading, showLoadingOverlay } = getState();
const loading =
showLoadingOverlay !== false && (isLoading || showLoadingOverlay);
const loading = showLoadingOverlay !== false && (isLoading || showLoadingOverlay);
const [totalToolbarHeight, setTotalToolbarHeight] = useState(0);
const [totalToolbarHeight, setTotalToolbarHeight] = useState(0);
const tableContainerProps = {
...parseFromValuesOrFunc(muiTableContainerProps, {
table,
}),
...rest,
};
const tableContainerProps = {
...parseFromValuesOrFunc(muiTableContainerProps, {
table,
}),
...rest,
};
useIsomorphicLayoutEffect(() => {
const topToolbarHeight =
typeof document !== "undefined"
? (topToolbarRef.current?.offsetHeight ?? 0)
: 0;
useIsomorphicLayoutEffect(() => {
const topToolbarHeight = typeof document !== "undefined" ? (topToolbarRef.current?.offsetHeight ?? 0) : 0;
const bottomToolbarHeight =
typeof document !== "undefined"
? (bottomToolbarRef?.current?.offsetHeight ?? 0)
: 0;
const bottomToolbarHeight =
typeof document !== "undefined" ? (bottomToolbarRef?.current?.offsetHeight ?? 0) : 0;
setTotalToolbarHeight(topToolbarHeight + bottomToolbarHeight);
});
setTotalToolbarHeight(topToolbarHeight + bottomToolbarHeight);
});
return (
<TableContainer
aria-busy={loading}
aria-describedby={loading ? "mrt-progress" : undefined}
{...tableContainerProps}
ref={(node) => {
if (node) {
tableContainerRef.current = node;
if (tableContainerProps?.ref) {
//@ts-ignore
tableContainerProps.ref.current = node;
}
}
}}
style={{
maxHeight: isFullScreen
? `calc(100vh - ${totalToolbarHeight}px)`
: undefined,
...tableContainerProps?.style,
}}
sx={(theme) => ({
maxHeight: enableStickyHeader
? `clamp(350px, calc(100vh - ${totalToolbarHeight}px), 9999px)`
: undefined,
maxWidth: "100%",
overflow: "auto",
position: "relative",
...parseFromValuesOrFunc(tableContainerProps?.sx, theme),
})}
>
{loading ? <DataTable_TableLoadingOverlay table={table} /> : null}
<DataTable_Table table={table} />
{enableCellActions && actionCell && (
<DataTable_CellActionMenu table={table} />
)}
</TableContainer>
);
return (
<TableContainer
aria-busy={loading}
aria-describedby={loading ? "mrt-progress" : undefined}
{...tableContainerProps}
ref={(node) => {
if (node) {
tableContainerRef.current = node;
if (tableContainerProps?.ref) {
//@ts-ignore
tableContainerProps.ref.current = node;
}
}
}}
style={{
maxHeight: isFullScreen ? `calc(100vh - ${totalToolbarHeight}px)` : undefined,
...tableContainerProps?.style,
}}
sx={(theme) => ({
maxHeight: enableStickyHeader
? `clamp(350px, calc(100vh - ${totalToolbarHeight}px), 9999px)`
: undefined,
maxWidth: "100%",
overflow: "auto",
position: "relative",
...parseFromValuesOrFunc(tableContainerProps?.sx, theme),
})}
>
{loading ? <DataTable_TableLoadingOverlay table={table} /> : null}
<DataTable_Table table={table} />
{enableCellActions && actionCell && <DataTable_CellActionMenu table={table} />}
</TableContainer>
);
};
export default DataTable_TableContainer;

View File

@@ -1,44 +1,44 @@
import { Box, CircularProgress } from "@mui/material";
const DataTable_TableLoadingOverlay = ({ table, ...rest }) => {
const {
options: {
localization,
mrtTheme: { baseBackgroundColor },
muiCircularProgressProps,
},
} = table;
const {
options: {
localization,
mrtTheme: { baseBackgroundColor },
muiCircularProgressProps,
},
} = table;
const circularProgressProps = {
...parseFromValuesOrFunc(muiCircularProgressProps, { table }),
...rest,
};
const circularProgressProps = {
...parseFromValuesOrFunc(muiCircularProgressProps, { table }),
...rest,
};
return (
<Box
sx={{
alignItems: "center",
backgroundColor: alpha(baseBackgroundColor, 0.5),
bottom: 0,
display: "flex",
justifyContent: "center",
left: 0,
maxHeight: "100vh",
position: "absolute",
right: 0,
top: 0,
width: "100%",
zIndex: 3,
}}
>
{circularProgressProps?.Component ?? (
<CircularProgress
aria-label={localization.noRecordsToDisplay}
id="mrt-progress"
{...circularProgressProps}
/>
)}
</Box>
);
return (
<Box
sx={{
alignItems: "center",
backgroundColor: alpha(baseBackgroundColor, 0.5),
bottom: 0,
display: "flex",
justifyContent: "center",
left: 0,
maxHeight: "100vh",
position: "absolute",
right: 0,
top: 0,
width: "100%",
zIndex: 3,
}}
>
{circularProgressProps?.Component ?? (
<CircularProgress
aria-label={localization.noRecordsToDisplay}
id="mrt-progress"
{...circularProgressProps}
/>
)}
</Box>
);
};
export default DataTable_TableLoadingOverlay;

View File

@@ -1,85 +1,72 @@
import {
getCommonToolbarStyles,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
import { Box, alpha, useMediaQuery } from "@mui/material";
import DataTable_LinearProgressBar from "./LinearProgressBar";
import DataTable_TablePagination from "./TablePagination";
const DataTable_BottomToolbar = ({ table, ...rest }) => {
const {
getState,
options: {
enablePagination,
muiBottomToolbarProps,
positionPagination,
renderBottomToolbarCustomActions,
},
refs: { bottomToolbarRef },
} = table;
const { isFullScreen } = getState();
const {
getState,
options: { enablePagination, muiBottomToolbarProps, positionPagination, renderBottomToolbarCustomActions },
refs: { bottomToolbarRef },
} = table;
const { isFullScreen } = getState();
const isMobile = useMediaQuery("(max-width:720px)");
const toolbarProps = {
...parseFromValuesOrFunc(muiBottomToolbarProps, { table }),
...rest,
};
const isMobile = useMediaQuery("(max-width:720px)");
const toolbarProps = {
...parseFromValuesOrFunc(muiBottomToolbarProps, { table }),
...rest,
};
const stackAlertBanner = isMobile || !!renderBottomToolbarCustomActions;
return (
<Box
{...toolbarProps}
ref={(node) => {
if (node) {
bottomToolbarRef.current = node;
if (toolbarProps?.ref) {
// @ts-ignore
toolbarProps.ref.current = node;
}
}
}}
sx={(theme) => ({
...getCommonToolbarStyles({ table, theme }),
bottom: isFullScreen ? "0" : undefined,
boxShadow: `0 1px 2px -1px ${alpha(theme.palette.grey[700], 0.5)} inset`,
left: 0,
position: isFullScreen ? "fixed" : "relative",
right: 0,
...parseFromValuesOrFunc(toolbarProps?.sx, theme),
})}
>
<DataTable_LinearProgressBar isTopToolbar={false} table={table} />
<Box
sx={{
alignItems: "center",
boxSizing: "border-box",
display: "flex",
justifyContent: "space-between",
p: "0.5rem",
width: "100%",
}}
>
{renderBottomToolbarCustomActions ? (
renderBottomToolbarCustomActions({ table })
) : (
<span />
)}
const stackAlertBanner = isMobile || !!renderBottomToolbarCustomActions;
return (
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
position: stackAlertBanner ? "relative" : "absolute",
right: 0,
top: 0,
}}
{...toolbarProps}
ref={(node) => {
if (node) {
bottomToolbarRef.current = node;
if (toolbarProps?.ref) {
// @ts-ignore
toolbarProps.ref.current = node;
}
}
}}
sx={(theme) => ({
...getCommonToolbarStyles({ table, theme }),
bottom: isFullScreen ? "0" : undefined,
boxShadow: `0 1px 2px -1px ${alpha(theme.palette.grey[700], 0.5)} inset`,
left: 0,
position: isFullScreen ? "fixed" : "relative",
right: 0,
...parseFromValuesOrFunc(toolbarProps?.sx, theme),
})}
>
{enablePagination &&
["both", "bottom"].includes(positionPagination ?? "") && (
<DataTable_TablePagination position="bottom" table={table} />
)}
<DataTable_LinearProgressBar isTopToolbar={false} table={table} />
<Box
sx={{
alignItems: "center",
boxSizing: "border-box",
display: "flex",
justifyContent: "space-between",
p: "0.5rem",
width: "100%",
}}
>
{renderBottomToolbarCustomActions ? renderBottomToolbarCustomActions({ table }) : <span />}
<Box
sx={{
display: "flex",
justifyContent: "flex-end",
position: stackAlertBanner ? "relative" : "absolute",
right: 0,
top: 0,
}}
>
{enablePagination && ["both", "bottom"].includes(positionPagination ?? "") && (
<DataTable_TablePagination position="bottom" table={table} />
)}
</Box>
</Box>
</Box>
</Box>
</Box>
);
);
};
export default DataTable_BottomToolbar;

View File

@@ -2,39 +2,39 @@ import { parseFromValuesOrFunc } from "@/core/utils/utils";
import { Collapse, LinearProgress } from "@mui/material";
const DataTable_LinearProgressBar = ({ isTopToolbar, table, ...rest }) => {
const {
getState,
options: { muiLinearProgressProps },
} = table;
const { isSaving, showProgressBars } = getState();
const {
getState,
options: { muiLinearProgressProps },
} = table;
const { isSaving, showProgressBars } = getState();
const linearProgressProps = {
...parseFromValuesOrFunc(muiLinearProgressProps, {
isTopToolbar,
table,
}),
...rest,
};
const linearProgressProps = {
...parseFromValuesOrFunc(muiLinearProgressProps, {
isTopToolbar,
table,
}),
...rest,
};
return (
<Collapse
in={showProgressBars !== false && (showProgressBars || isSaving)}
mountOnEnter
sx={{
bottom: isTopToolbar ? 0 : undefined,
position: "absolute",
top: !isTopToolbar ? 0 : undefined,
width: "100%",
}}
unmountOnExit
>
<LinearProgress
aria-busy="true"
aria-label="Loading"
sx={{ position: "relative" }}
{...linearProgressProps}
/>
</Collapse>
);
return (
<Collapse
in={showProgressBars !== false && (showProgressBars || isSaving)}
mountOnEnter
sx={{
bottom: isTopToolbar ? 0 : undefined,
position: "absolute",
top: !isTopToolbar ? 0 : undefined,
width: "100%",
}}
unmountOnExit
>
<LinearProgress
aria-busy="true"
aria-label="Loading"
sx={{ position: "relative" }}
{...linearProgressProps}
/>
</Collapse>
);
};
export default DataTable_LinearProgressBar;

View File

@@ -1,228 +1,218 @@
import {
flipIconStyles,
getCommonTooltipProps,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { flipIconStyles, getCommonTooltipProps, parseFromValuesOrFunc } from "@/core/utils/utils";
import { useTheme } from "@emotion/react";
import {
Box,
IconButton,
InputLabel,
MenuItem,
Pagination,
PaginationItem,
Select,
Tooltip,
Typography,
useMediaQuery,
Box,
IconButton,
InputLabel,
MenuItem,
Pagination,
PaginationItem,
Select,
Tooltip,
Typography,
useMediaQuery,
} from "@mui/material";
const defaultRowsPerPage = [5, 10, 15, 20, 25, 30, 50, 100];
const DataTable_TablePagination = ({ position = "bottom", table, ...rest }) => {
const theme = useTheme();
const isMobile = useMediaQuery("(max-width: 720px)");
const theme = useTheme();
const isMobile = useMediaQuery("(max-width: 720px)");
const {
getState,
options: {
enableToolbarInternalActions,
icons: { ChevronLeftIcon, ChevronRightIcon, FirstPageIcon, LastPageIcon },
localization,
muiPaginationProps,
paginationDisplayMode,
},
} = table;
const {
getState,
options: {
enableToolbarInternalActions,
icons: { ChevronLeftIcon, ChevronRightIcon, FirstPageIcon, LastPageIcon },
localization,
muiPaginationProps,
paginationDisplayMode,
},
} = table;
const {
pagination: { pageIndex = 0, pageSize = 10 },
showGlobalFilter,
} = getState();
const {
pagination: { pageIndex = 0, pageSize = 10 },
showGlobalFilter,
} = getState();
const paginationProps = {
...parseFromValuesOrFunc(muiPaginationProps, {
table,
}),
...rest,
};
const paginationProps = {
...parseFromValuesOrFunc(muiPaginationProps, {
table,
}),
...rest,
};
const totalRowCount = table.getRowCount();
const numberOfPages = table.getPageCount();
const showFirstLastPageButtons = numberOfPages > 2;
const firstRowIndex = pageIndex * pageSize;
const lastRowIndex = Math.min(pageIndex * pageSize + pageSize, totalRowCount);
const totalRowCount = table.getRowCount();
const numberOfPages = table.getPageCount();
const showFirstLastPageButtons = numberOfPages > 2;
const firstRowIndex = pageIndex * pageSize;
const lastRowIndex = Math.min(pageIndex * pageSize + pageSize, totalRowCount);
const {
SelectProps = {},
disabled = false,
rowsPerPageOptions = defaultRowsPerPage,
showFirstButton = showFirstLastPageButtons,
showLastButton = showFirstLastPageButtons,
showRowsPerPage = true,
...restPaginationProps
} = paginationProps ?? {};
const {
SelectProps = {},
disabled = false,
rowsPerPageOptions = defaultRowsPerPage,
showFirstButton = showFirstLastPageButtons,
showLastButton = showFirstLastPageButtons,
showRowsPerPage = true,
...restPaginationProps
} = paginationProps ?? {};
const disableBack = pageIndex <= 0 || disabled;
const disableNext = lastRowIndex >= totalRowCount || disabled;
const disableBack = pageIndex <= 0 || disabled;
const disableNext = lastRowIndex >= totalRowCount || disabled;
if (isMobile && SelectProps?.native !== false) {
SelectProps.native = true;
}
if (isMobile && SelectProps?.native !== false) {
SelectProps.native = true;
}
const tooltipProps = getCommonTooltipProps();
const tooltipProps = getCommonTooltipProps();
return (
<Box
className="MuiTablePagination-root"
sx={{
alignItems: "center",
display: "flex",
flexWrap: "wrap",
gap: "8px",
justifyContent: { md: "space-between", sm: "center" },
justifySelf: "flex-end",
mt:
position === "top" &&
enableToolbarInternalActions &&
!showGlobalFilter
? "3rem"
: undefined,
position: "relative",
px: "8px",
py: "12px",
zIndex: 2,
}}
>
{showRowsPerPage && (
<Box sx={{ alignItems: "center", display: "flex", gap: "8px" }}>
<InputLabel htmlFor="mrt-rows-per-page" sx={{ mb: 0 }}>
{localization.rowsPerPage}
</InputLabel>
<Select
MenuProps={{ disableScrollLock: true }}
disableUnderline
disabled={disabled}
inputProps={{
"aria-label": localization.rowsPerPage,
id: "mrt-rows-per-page",
return (
<Box
className="MuiTablePagination-root"
sx={{
alignItems: "center",
display: "flex",
flexWrap: "wrap",
gap: "8px",
justifyContent: { md: "space-between", sm: "center" },
justifySelf: "flex-end",
mt: position === "top" && enableToolbarInternalActions && !showGlobalFilter ? "3rem" : undefined,
position: "relative",
px: "8px",
py: "12px",
zIndex: 2,
}}
label={localization.rowsPerPage}
onChange={(event) => table.setPageSize(+event.target.value)}
sx={{ mb: 0 }}
value={pageSize}
variant="standard"
{...SelectProps}
>
{rowsPerPageOptions.map((option) => {
const value = typeof option !== "number" ? option.value : option;
const label =
typeof option !== "number" ? option.label : `${option}`;
return (
SelectProps?.children ??
(SelectProps?.native ? (
<option key={value} value={value}>
{label}
</option>
) : (
<MenuItem key={value} sx={{ m: 0 }} value={value}>
{label}
</MenuItem>
))
);
})}
</Select>
>
{showRowsPerPage && (
<Box sx={{ alignItems: "center", display: "flex", gap: "8px" }}>
<InputLabel htmlFor="mrt-rows-per-page" sx={{ mb: 0 }}>
{localization.rowsPerPage}
</InputLabel>
<Select
MenuProps={{ disableScrollLock: true }}
disableUnderline
disabled={disabled}
inputProps={{
"aria-label": localization.rowsPerPage,
id: "mrt-rows-per-page",
}}
label={localization.rowsPerPage}
onChange={(event) => table.setPageSize(+event.target.value)}
sx={{ mb: 0 }}
value={pageSize}
variant="standard"
{...SelectProps}
>
{rowsPerPageOptions.map((option) => {
const value = typeof option !== "number" ? option.value : option;
const label = typeof option !== "number" ? option.label : `${option}`;
return (
SelectProps?.children ??
(SelectProps?.native ? (
<option key={value} value={value}>
{label}
</option>
) : (
<MenuItem key={value} sx={{ m: 0 }} value={value}>
{label}
</MenuItem>
))
);
})}
</Select>
</Box>
)}
{paginationDisplayMode === "pages" ? (
<Pagination
count={numberOfPages}
disabled={disabled}
onChange={(_e, newPageIndex) => table.setPageIndex(newPageIndex - 1)}
page={pageIndex + 1}
renderItem={(item) => (
<PaginationItem
slots={{
first: FirstPageIcon,
last: LastPageIcon,
next: ChevronRightIcon,
previous: ChevronLeftIcon,
}}
{...item}
/>
)}
showFirstButton={showFirstButton}
showLastButton={showLastButton}
{...restPaginationProps}
/>
) : paginationDisplayMode === "default" ? (
<>
<Typography
align="center"
component="span"
sx={{ m: "0 4px", minWidth: "8ch" }}
variant="body2"
>{`${
lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString()
}-${lastRowIndex.toLocaleString()} ${
localization.of
} ${totalRowCount.toLocaleString()}`}</Typography>
<Box gap="xs">
{showFirstButton && (
<Tooltip {...tooltipProps} title={localization.goToFirstPage}>
<span>
<IconButton
aria-label={localization.goToFirstPage}
disabled={disableBack}
onClick={() => table.firstPage()}
size="small"
>
<FirstPageIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
)}
<Tooltip {...tooltipProps} title={localization.goToPreviousPage}>
<span>
<IconButton
aria-label={localization.goToPreviousPage}
disabled={disableBack}
onClick={() => table.previousPage()}
size="small"
>
<ChevronLeftIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
<Tooltip {...tooltipProps} title={localization.goToNextPage}>
<span>
<IconButton
aria-label={localization.goToNextPage}
disabled={disableNext}
onClick={() => table.nextPage()}
size="small"
>
<ChevronRightIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
{showLastButton && (
<Tooltip {...tooltipProps} title={localization.goToLastPage}>
<span>
<IconButton
aria-label={localization.goToLastPage}
disabled={disableNext}
onClick={() => table.lastPage()}
size="small"
>
<LastPageIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
)}
</Box>
</>
) : null}
</Box>
)}
{paginationDisplayMode === "pages" ? (
<Pagination
count={numberOfPages}
disabled={disabled}
onChange={(_e, newPageIndex) => table.setPageIndex(newPageIndex - 1)}
page={pageIndex + 1}
renderItem={(item) => (
<PaginationItem
slots={{
first: FirstPageIcon,
last: LastPageIcon,
next: ChevronRightIcon,
previous: ChevronLeftIcon,
}}
{...item}
/>
)}
showFirstButton={showFirstButton}
showLastButton={showLastButton}
{...restPaginationProps}
/>
) : paginationDisplayMode === "default" ? (
<>
<Typography
align="center"
component="span"
sx={{ m: "0 4px", minWidth: "8ch" }}
variant="body2"
>{`${
lastRowIndex === 0 ? 0 : (firstRowIndex + 1).toLocaleString()
}-${lastRowIndex.toLocaleString()} ${
localization.of
} ${totalRowCount.toLocaleString()}`}</Typography>
<Box gap="xs">
{showFirstButton && (
<Tooltip {...tooltipProps} title={localization.goToFirstPage}>
<span>
<IconButton
aria-label={localization.goToFirstPage}
disabled={disableBack}
onClick={() => table.firstPage()}
size="small"
>
<FirstPageIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
)}
<Tooltip {...tooltipProps} title={localization.goToPreviousPage}>
<span>
<IconButton
aria-label={localization.goToPreviousPage}
disabled={disableBack}
onClick={() => table.previousPage()}
size="small"
>
<ChevronLeftIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
<Tooltip {...tooltipProps} title={localization.goToNextPage}>
<span>
<IconButton
aria-label={localization.goToNextPage}
disabled={disableNext}
onClick={() => table.nextPage()}
size="small"
>
<ChevronRightIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
{showLastButton && (
<Tooltip {...tooltipProps} title={localization.goToLastPage}>
<span>
<IconButton
aria-label={localization.goToLastPage}
disabled={disableNext}
onClick={() => table.lastPage()}
size="small"
>
<LastPageIcon {...flipIconStyles(theme)} />
</IconButton>
</span>
</Tooltip>
)}
</Box>
</>
) : null}
</Box>
);
);
};
export default DataTable_TablePagination;

View File

@@ -1,7 +1,4 @@
import {
getCommonToolbarStyles,
parseFromValuesOrFunc,
} from "@/core/utils/utils";
import { getCommonToolbarStyles, parseFromValuesOrFunc } from "@/core/utils/utils";
import { Box, Typography, useMediaQuery } from "@mui/material";
import DataTable_LinearProgressBar from "./LinearProgressBar";
import DataTable_TablePagination from "./TablePagination";
@@ -12,145 +9,134 @@ import HideColumn from "@/core/components/DataTable/hide";
import FilterCustom from "../filter/FilterCustom";
const DataTable_TopToolbar = ({
mutate,
need_filter,
table,
columns,
table_url,
user_id,
page_name,
table_name,
table_title,
special_data,
special_filter,
setFilterData,
mutate,
need_filter,
table,
columns,
table_url,
user_id,
page_name,
table_name,
table_title,
special_data,
special_filter,
setFilterData,
}) => {
const {
getState,
options: {
enablePagination,
enableToolbarInternalActions,
muiTopToolbarProps,
positionPagination,
renderTopToolbarCustomActions,
},
refs: { topToolbarRef },
} = table;
const { isFullScreen, showGlobalFilter } = getState();
const {
getState,
options: {
enablePagination,
enableToolbarInternalActions,
muiTopToolbarProps,
positionPagination,
renderTopToolbarCustomActions,
},
refs: { topToolbarRef },
} = table;
const { isFullScreen, showGlobalFilter } = getState();
const isMobile = useMediaQuery("(max-width:720px)");
const isTablet = useMediaQuery("(max-width:1024px)");
const isMobile = useMediaQuery("(max-width:720px)");
const isTablet = useMediaQuery("(max-width:1024px)");
const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table });
const toolbarProps = parseFromValuesOrFunc(muiTopToolbarProps, { table });
const stackAlertBanner =
isMobile ||
!!renderTopToolbarCustomActions ||
(showGlobalFilter && isTablet);
const stackAlertBanner = isMobile || !!renderTopToolbarCustomActions || (showGlobalFilter && isTablet);
return (
<Box
{...toolbarProps}
ref={(ref) => {
topToolbarRef.current = ref;
if (toolbarProps?.ref) {
// @ts-ignore
toolbarProps.ref.current = ref;
}
}}
sx={(theme) => ({
...getCommonToolbarStyles({ table, theme }),
position: isFullScreen ? "sticky" : "relative",
top: isFullScreen ? "0" : undefined,
...parseFromValuesOrFunc(toolbarProps?.sx, theme),
})}
>
<Box
sx={{
flexWrap: { xs: "wrap", sm: "no-wrap" },
boxSizing: "border-box",
display: "flex",
gap: "0.5rem",
justifyContent: "space-between",
alignItems: "center",
p: "0.5rem",
position: stackAlertBanner ? "relative" : "absolute",
right: 0,
top: 0,
width: "100%",
}}
>
return (
<Box
sx={{
display: "flex",
alignItems: "center",
order: { xs: 2, sm: 1 },
}}
>
{renderTopToolbarCustomActions?.({ table })}
</Box>
<Typography
sx={{
textAlign: "center",
order: { xs: 1, sm: 2 },
width: { xs: "100%", sm: "unset" },
}}
fontWeight={600}
>
{table_title || ""}
</Typography>
{enableToolbarInternalActions && (
<Box
sx={{
gap: "0.5rem",
flexWrap: "wrap-reverse",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
order: 3,
{...toolbarProps}
ref={(ref) => {
topToolbarRef.current = ref;
if (toolbarProps?.ref) {
// @ts-ignore
toolbarProps.ref.current = ref;
}
}}
>
{!special_data && (
<>
<ResetStorage
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
<UpdateTable mutate={mutate} />
</>
sx={(theme) => ({
...getCommonToolbarStyles({ table, theme }),
position: isFullScreen ? "sticky" : "relative",
top: isFullScreen ? "0" : undefined,
...parseFromValuesOrFunc(toolbarProps?.sx, theme),
})}
>
<Box
sx={{
flexWrap: { xs: "wrap", sm: "no-wrap" },
boxSizing: "border-box",
display: "flex",
gap: "0.5rem",
justifyContent: "space-between",
alignItems: "center",
p: "0.5rem",
position: stackAlertBanner ? "relative" : "absolute",
right: 0,
top: 0,
width: "100%",
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
order: { xs: 2, sm: 1 },
}}
>
{renderTopToolbarCustomActions?.({ table })}
</Box>
<Typography
sx={{
textAlign: "center",
order: { xs: 1, sm: 2 },
width: { xs: "100%", sm: "unset" },
}}
fontWeight={600}
>
{table_title || ""}
</Typography>
{enableToolbarInternalActions && (
<Box
sx={{
gap: "0.5rem",
flexWrap: "wrap-reverse",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
order: 3,
}}
>
{!special_data && (
<>
<ResetStorage user_id={user_id} page_name={page_name} table_name={table_name} />
<UpdateTable mutate={mutate} />
</>
)}
<HideColumn
columns={table.options.columns}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
{need_filter && (
<FilterColumn
columns={columns}
table_url={table_url}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
)}
{special_filter && setFilterData && (
<FilterCustom filterData={special_filter} setFilterData={setFilterData} />
)}
</Box>
)}
</Box>
{enablePagination && ["both", "top"].includes(positionPagination ?? "") && (
<DataTable_TablePagination position="top" table={table} />
)}
<HideColumn
columns={table.options.columns}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
{need_filter && (
<FilterColumn
columns={columns}
table_url={table_url}
user_id={user_id}
page_name={page_name}
table_name={table_name}
/>
)}
{special_filter && setFilterData && (
<FilterCustom
filterData={special_filter}
setFilterData={setFilterData}
/>
)}
</Box>
)}
</Box>
{enablePagination &&
["both", "top"].includes(positionPagination ?? "") && (
<DataTable_TablePagination position="top" table={table} />
)}
<DataTable_LinearProgressBar isTopToolbar table={table} />
</Box>
);
<DataTable_LinearProgressBar isTopToolbar table={table} />
</Box>
);
};
export default DataTable_TopToolbar;

View File

@@ -3,17 +3,17 @@ import { IconButton, Tooltip } from "@mui/material";
import RestartAltIcon from "@mui/icons-material/RestartAlt";
function UpdateTable({ mutate }) {
const update = () => {
mutate();
};
const update = () => {
mutate();
};
return (
<Tooltip title="بروزرسانی اطلاعات">
<IconButton onClick={update} aria-label="refactor table">
<RestartAltIcon />
</IconButton>
</Tooltip>
);
return (
<Tooltip title="بروزرسانی اطلاعات">
<IconButton onClick={update} aria-label="refactor table">
<RestartAltIcon />
</IconButton>
</Tooltip>
);
}
export default UpdateTable;

View File

@@ -2,7 +2,7 @@ import DataTable from "@/core/components/DataTable";
import { useAuth } from "@/lib/contexts/auth";
const DataTableWithAuth = (props) => {
const { user } = useAuth();
return <DataTable user_id={user.username} {...props} />;
const { user } = useAuth();
return <DataTable user_id={user.username} {...props} />;
};
export default DataTableWithAuth;

View File

@@ -1,8 +1,6 @@
import { forwardRef } from "react";
import { Slide } from "@mui/material";
export const DialogTransition = forwardRef(
function DialogTransition(props, ref) {
export const DialogTransition = forwardRef(function DialogTransition(props, ref) {
return <Slide direction="up" ref={ref} {...props} />;
},
);
});

View File

@@ -2,24 +2,24 @@ import { Controller } from "react-hook-form";
import FilterField from "./FilterField";
const FilterController = ({ item, control, reset, errors }) => {
return (
<Controller
name={`${item.id}`}
control={control}
render={({ field: { value, onBlur, onChange } }) => {
return (
<FilterField
item={item}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={null}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
return (
<Controller
name={`${item.id}`}
control={control}
render={({ field: { value, onBlur, onChange } }) => {
return (
<FilterField
item={item}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={null}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
};
export default FilterController;

View File

@@ -2,26 +2,26 @@ import { Controller, useWatch } from "react-hook-form";
import FilterField from "./FilterField";
const FilterControllerWithDependency = ({ item, control, reset, errors }) => {
const dependencyField = useWatch({ control, name: item.dependencyId });
const dependencyField = useWatch({ control, name: item.dependencyId });
return (
<Controller
name={`${item.id}`}
control={control}
render={({ field: { value, name, onBlur, onChange } }) => {
return (
<FilterField
item={item}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={dependencyField}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
return (
<Controller
name={`${item.id}`}
control={control}
render={({ field: { value, name, onBlur, onChange } }) => {
return (
<FilterField
item={item}
filterParameters={value}
handleChange={onChange}
handleBlur={onBlur}
dependencyFieldValue={dependencyField}
resetForm={() => reset()}
errors={errors}
/>
);
}}
/>
);
};
export default FilterControllerWithDependency;

View File

@@ -8,98 +8,96 @@ import CustomTextField from "./fieldsType/CustomTextField";
import FilterOptionList from "./FilterOptionList";
const filterModeOptionFa = {
equals: "برابر",
notEquals: "نابرابر",
contains: "شامل",
lessThan: "کوچکتر",
greaterThan: "بزرگتر",
fuzzy: "فازی",
between: "مابین",
equals: "برابر",
notEquals: "نابرابر",
contains: "شامل",
lessThan: "کوچکتر",
greaterThan: "بزرگتر",
fuzzy: "فازی",
between: "مابین",
};
function FilterField({
item,
filterParameters,
handleChange,
handleBlur,
dependencyFieldValue,
setFieldValue,
resetForm,
errors,
item,
filterParameters,
handleChange,
handleBlur,
dependencyFieldValue,
setFieldValue,
resetForm,
errors,
}) {
const [anchorEl, setAnchorEl] = useState(null);
const defaultFilterTranslation =
filterModeOptionFa[filterParameters.filterMode] ||
filterParameters.filterMode;
const [anchorEl, setAnchorEl] = useState(null);
const defaultFilterTranslation = filterModeOptionFa[filterParameters.filterMode] || filterParameters.filterMode;
const handleOpenFilterBox = (event) => {
setAnchorEl(event.currentTarget);
};
const renderField = () => {
const commonProps = {
item,
filterParameters,
defaultFilterTranslation,
handleOpenFilterBox,
dependencyFieldValue,
setFieldValue,
handleChange,
handleBlur,
errors,
const handleOpenFilterBox = (event) => {
setAnchorEl(event.currentTarget);
};
switch (filterParameters.datatype) {
case "numeric":
if (filterParameters.filterMode === "between") {
return <CustomTextFieldRange {...commonProps} />;
}
if (filterParameters.filterMode === "equals") {
return item.SelectComponent ? (
<item.SelectComponent {...commonProps} />
) : (
<CustomSelect {...commonProps} />
);
}
break;
case "date":
if (filterParameters.filterMode === "equals") {
return <CustomDatePicker {...commonProps} />;
}
if (filterParameters.filterMode === "between") {
return <CustomDatePickerRange {...commonProps} />;
}
break;
const renderField = () => {
const commonProps = {
item,
filterParameters,
defaultFilterTranslation,
handleOpenFilterBox,
dependencyFieldValue,
setFieldValue,
handleChange,
handleBlur,
errors,
};
case "array":
if (filterParameters.filterMode === "equals") {
return <CustomSelectMultiple {...commonProps} />;
switch (filterParameters.datatype) {
case "numeric":
if (filterParameters.filterMode === "between") {
return <CustomTextFieldRange {...commonProps} />;
}
if (filterParameters.filterMode === "equals") {
return item.SelectComponent ? (
<item.SelectComponent {...commonProps} />
) : (
<CustomSelect {...commonProps} />
);
}
break;
case "date":
if (filterParameters.filterMode === "equals") {
return <CustomDatePicker {...commonProps} />;
}
if (filterParameters.filterMode === "between") {
return <CustomDatePickerRange {...commonProps} />;
}
break;
case "array":
if (filterParameters.filterMode === "equals") {
return <CustomSelectMultiple {...commonProps} />;
}
break;
default:
return <CustomTextField {...commonProps} />;
}
break;
};
default:
return <CustomTextField {...commonProps} />;
}
};
return (
<>
{renderField()}
{Array.isArray(item.filterModeOptions) && (
<FilterOptionList
item={item}
anchorEl={anchorEl}
setAnchorEl={setAnchorEl}
filterParameters={filterParameters}
filterType={filterParameters.filterMode}
handleChange={handleChange}
resetForm={resetForm}
filterOption={item.filterModeOptions}
filterModeOptionFa={filterModeOptionFa}
/>
)}
</>
);
return (
<>
{renderField()}
{Array.isArray(item.filterModeOptions) && (
<FilterOptionList
item={item}
anchorEl={anchorEl}
setAnchorEl={setAnchorEl}
filterParameters={filterParameters}
filterType={filterParameters.filterMode}
handleChange={handleChange}
resetForm={resetForm}
filterOption={item.filterModeOptions}
filterModeOptionFa={filterModeOptionFa}
/>
)}
</>
);
}
export default FilterField;

View File

@@ -4,55 +4,49 @@ import { ListItem, Menu } from "@mui/material";
import { useState } from "react";
function FilterOptionList({
filterType,
filterOption,
filterParameters,
anchorEl,
filterModeOptionFa,
setAnchorEl,
handleChange,
filterType,
filterOption,
filterParameters,
anchorEl,
filterModeOptionFa,
setAnchorEl,
handleChange,
}) {
const [selectedFilter, setSelectedFilter] = useState(filterType);
const [selectedFilter, setSelectedFilter] = useState(filterType);
const handleChangeItem = (event, index) => {
handleChange({
...filterParameters,
value: filterOption[index] === "between" ? ["", ""] : "",
filterMode: filterOption[index],
});
setSelectedFilter(filterOption[index]);
setAnchorEl(null);
};
const handleChangeItem = (event, index) => {
handleChange({
...filterParameters,
value: filterOption[index] === "between" ? ["", ""] : "",
filterMode: filterOption[index],
});
setSelectedFilter(filterOption[index]);
setAnchorEl(null);
};
const handleCloseFilterBox = () => {
setAnchorEl(null);
};
const handleCloseFilterBox = () => {
setAnchorEl(null);
};
return (
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleCloseFilterBox}
>
{filterOption.map((option, index) => (
<ListItem
key={index}
onClick={(event) => handleChangeItem(event, index)}
selected={option === selectedFilter}
sx={{
cursor: "pointer",
width: "100px",
display: "flex",
justifyContent: "center",
}}
>
{filterModeOptionFa[option]}
</ListItem>
))}
</Menu>
);
return (
<Menu id="simple-menu" anchorEl={anchorEl} keepMounted open={Boolean(anchorEl)} onClose={handleCloseFilterBox}>
{filterOption.map((option, index) => (
<ListItem
key={index}
onClick={(event) => handleChangeItem(event, index)}
selected={option === selectedFilter}
sx={{
cursor: "pointer",
width: "100px",
display: "flex",
justifyContent: "center",
}}
>
{filterModeOptionFa[option]}
</ListItem>
))}
</Menu>
);
}
export default FilterOptionList;

View File

@@ -2,30 +2,22 @@ import React from "react";
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
import { Typography } from "@mui/material";
function CustomDatePicker({
column,
filterParameters,
defaultFilterTranslation,
handleChange,
}) {
return (
<MuiDatePicker
name={`${column.id}.value`}
value={filterParameters.value}
setFieldValue={(name, formattedDate) => {
handleChange({ ...filterParameters, value: formattedDate });
}}
placeholder={column.header}
helperText={
<Typography
variant="button"
sx={{ color: (theme) => theme.palette.primary.main }}
>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
);
function CustomDatePicker({ column, filterParameters, defaultFilterTranslation, handleChange }) {
return (
<MuiDatePicker
name={`${column.id}.value`}
value={filterParameters.value}
setFieldValue={(name, formattedDate) => {
handleChange({ ...filterParameters, value: formattedDate });
}}
placeholder={column.header}
helperText={
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
);
}
export default CustomDatePicker;

View File

@@ -4,57 +4,44 @@ import React from "react";
import { Box, Typography } from "@mui/material";
import MuiDatePicker from "@/core/components/DataTable/filter/fieldsType/CustomDate/MuiDatePicker";
function CustomDatePickerRange({
item,
filterParameters,
defaultFilterTranslation,
handleChange,
errors,
}) {
return (
<Box sx={{ display: "flex", gap: 1 }}>
<MuiDatePicker
label={item.header}
name={`${item.id}.value[0]`}
value={filterParameters.value[0]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [formattedDate, filterParameters.value[1]],
});
}}
maxDate={filterParameters.value[1]}
placeholder={`از تاریخ`}
helperText={
<Typography
variant="button"
sx={{ color: (theme) => theme.palette.primary.main }}
>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
<MuiDatePicker
label={item.header}
name={`${item.id}.value[1]`}
value={filterParameters.value[1]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [filterParameters.value[0], formattedDate],
});
}}
minDate={filterParameters.value[0]}
placeholder={`تا تاریخ`}
helperText={
errors?.[`${item.id}`]?.value
? errors?.[`${item.id}`]?.value.message
: null
}
error={Boolean(errors?.[`${item.id}`]?.value)}
/>
</Box>
);
function CustomDatePickerRange({ item, filterParameters, defaultFilterTranslation, handleChange, errors }) {
return (
<Box sx={{ display: "flex", gap: 1 }}>
<MuiDatePicker
label={item.header}
name={`${item.id}.value[0]`}
value={filterParameters.value[0]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [formattedDate, filterParameters.value[1]],
});
}}
maxDate={filterParameters.value[1]}
placeholder={`از تاریخ`}
helperText={
<Typography variant="button" sx={{ color: (theme) => theme.palette.primary.main }}>
نوع فیلتر: {defaultFilterTranslation} (تاریخ)
</Typography>
}
/>
<MuiDatePicker
label={item.header}
name={`${item.id}.value[1]`}
value={filterParameters.value[1]}
setFieldValue={(name, formattedDate) => {
handleChange({
...filterParameters,
value: [filterParameters.value[0], formattedDate],
});
}}
minDate={filterParameters.value[0]}
placeholder={`تا تاریخ`}
helperText={errors?.[`${item.id}`]?.value ? errors?.[`${item.id}`]?.value.message : null}
error={Boolean(errors?.[`${item.id}`]?.value)}
/>
</Box>
);
}
export default CustomDatePickerRange;

View File

@@ -6,81 +6,67 @@ import { Box, FormHelperText, IconButton, InputAdornment } from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
import moment from "jalali-moment";
function MuiDatePicker({
label,
value,
setFieldValue,
name,
minDate,
maxDate,
helperText,
placeholder,
error,
}) {
return (
<Box sx={{ display: "flex", flexDirection: "column", my: 1 }}>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={
faIR.components.MuiLocalizationProvider.defaultProps.localeText
}
>
<MobileDatePicker
value={value ? new Date(value) : null}
sx={{ width: "100%" }}
id={name}
label={label}
name={name}
closeOnSelect={true}
aria-describedby="component-helper-text"
onChange={(value) => {
const date = new Date(value);
const formattedDate = moment(date)
.locale("en")
.format("YYYY-MM-DD");
setFieldValue(name, formattedDate);
}}
minDate={minDate ? new Date(minDate) : null}
maxDate={maxDate ? new Date(maxDate) : null}
slotProps={{
textField: {
size: "small",
error: error,
placeholder: placeholder,
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
onClick={(event) => {
event.stopPropagation();
setFieldValue(name, "");
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
function MuiDatePicker({ label, value, setFieldValue, name, minDate, maxDate, helperText, placeholder, error }) {
return (
<Box sx={{ display: "flex", flexDirection: "column", my: 1 }}>
<LocalizationProvider
dateAdapter={AdapterDateFnsJalali}
localeText={faIR.components.MuiLocalizationProvider.defaultProps.localeText}
>
<MobileDatePicker
value={value ? new Date(value) : null}
sx={{ width: "100%" }}
id={name}
label={label}
name={name}
closeOnSelect={true}
aria-describedby="component-helper-text"
onChange={(value) => {
const date = new Date(value);
const formattedDate = moment(date).locale("en").format("YYYY-MM-DD");
setFieldValue(name, formattedDate);
}}
minDate={minDate ? new Date(minDate) : null}
maxDate={maxDate ? new Date(maxDate) : null}
slotProps={{
textField: {
size: "small",
error: error,
placeholder: placeholder,
InputProps: {
endAdornment: (
<InputAdornment position="end">
<IconButton
size="small"
onClick={(event) => {
event.stopPropagation();
setFieldValue(name, "");
}}
sx={{
color: "#bfbfbf",
"&:hover": {
backgroundColor: "rgba(189, 189, 189, 0.1)",
color: "#363434",
},
}}
>
<ClearIcon />
</IconButton>
</InputAdornment>
),
},
InputLabelProps: {
shrink: true,
},
},
}}
>
<ClearIcon />
</IconButton>
</InputAdornment>
),
},
InputLabelProps: {
shrink: true,
},
},
}}
/>
{/* <FormHelperText id="component-helper-text" variant="caption" sx={{ ml: 2, color: error ? "#d32f2f" : "unset", fontWeight: 'bold' }}>
}}
/>
{/* <FormHelperText id="component-helper-text" variant="caption" sx={{ ml: 2, color: error ? "#d32f2f" : "unset", fontWeight: 'bold' }}>
{helperText ? helperText : ""}
</FormHelperText> */}
</LocalizationProvider>
</Box>
);
</LocalizationProvider>
</Box>
);
}
export default MuiDatePicker;

View File

@@ -1,38 +1,30 @@
"use client";
import {
FormControl,
InputLabel,
MenuItem,
OutlinedInput,
Select,
} from "@mui/material";
import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
function CustomSelect({ item, filterParameters, handleChange }) {
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel id={`label${item.id}`} shrink>
{item.header}
</InputLabel>
<Select
labelId={`label${item.id}`}
id={item.id}
name={`${item.id}.value`}
value={filterParameters.value}
input={<OutlinedInput label={item.header} />}
size="small"
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
displayEmpty
>
{item.selectOption().map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel id={`label${item.id}`} shrink>
{item.header}
</InputLabel>
<Select
labelId={`label${item.id}`}
id={item.id}
name={`${item.id}.value`}
value={filterParameters.value}
input={<OutlinedInput label={item.header} />}
size="small"
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
displayEmpty
>
{item.selectOption().map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default CustomSelect;

View File

@@ -1,44 +1,30 @@
"use client";
import {
FormControl,
InputLabel,
MenuItem,
OutlinedInput,
Select,
} from "@mui/material";
function CustomSelectByDependency({
item,
filterParameters,
value,
handleChange,
selectOption,
}) {
return (
<FormControl fullWidth sx={{ my: 1 }} size="small">
<InputLabel id={`label${item.id}`} shrink>
{item.header}
</InputLabel>
<Select
labelId={`label${item.id}`}
id={item.id}
name={`${item.id}.value`}
value={value}
size="small"
input={<OutlinedInput label={item.header} />}
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
displayEmpty
>
{selectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
import { FormControl, InputLabel, MenuItem, OutlinedInput, Select } from "@mui/material";
function CustomSelectByDependency({ item, filterParameters, value, handleChange, selectOption }) {
return (
<FormControl fullWidth sx={{ my: 1 }} size="small">
<InputLabel id={`label${item.id}`} shrink>
{item.header}
</InputLabel>
<Select
labelId={`label${item.id}`}
id={item.id}
name={`${item.id}.value`}
value={value}
size="small"
input={<OutlinedInput label={item.header} />}
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
displayEmpty
>
{selectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default CustomSelectByDependency;

View File

@@ -1,57 +1,55 @@
"use client";
import {
Box,
Chip,
FormControl,
FormHelperText,
InputLabel,
MenuItem,
OutlinedInput,
Select,
Typography,
Box,
Chip,
FormControl,
FormHelperText,
InputLabel,
MenuItem,
OutlinedInput,
Select,
Typography,
} from "@mui/material";
function CustomSelectMultiple({ item, filterParameters, handleChange }) {
const selectOption = item.selectOption;
const selectOption = item.selectOption;
const getLabelForValue = (value) => {
const option = selectOption.find((opt) => opt.value === value);
return option ? option.label : value;
};
const getLabelForValue = (value) => {
const option = selectOption.find((opt) => opt.value === value);
return option ? option.label : value;
};
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel htmlFor="uncontrolled-native" id={`label${item.id}`}>
{item.header}
</InputLabel>
<Select
labelId={`label${item.id}`}
id={item.id}
value={filterParameters.value}
multiple
size="small"
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => (
<Chip key={value} label={getLabelForValue(value)} />
))}
</Box>
)}
input={<OutlinedInput label={item.header} />}
InputLabelProps={{ shrink: true }}
>
{selectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
return (
<FormControl fullWidth sx={{ marginY: 1 }} size="small">
<InputLabel htmlFor="uncontrolled-native" id={`label${item.id}`}>
{item.header}
</InputLabel>
<Select
labelId={`label${item.id}`}
id={item.id}
value={filterParameters.value}
multiple
size="small"
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
renderValue={(selected) => (
<Box sx={{ display: "flex", flexWrap: "wrap", gap: 0.5 }}>
{selected.map((value) => (
<Chip key={value} label={getLabelForValue(value)} />
))}
</Box>
)}
input={<OutlinedInput label={item.header} />}
InputLabelProps={{ shrink: true }}
>
{selectOption.map((option) => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
</FormControl>
);
}
export default CustomSelectMultiple;

View File

@@ -1,41 +1,29 @@
import { InputAdornment, TextField, Typography } from "@mui/material";
import FilterListIcon from "@mui/icons-material/FilterList";
function CustomTextField({
item,
filterParameters,
handleOpenFilterBox,
handleBlur,
handleChange,
}) {
return (
<TextField
id={item.id}
name={item.id}
label={item.header}
value={filterParameters.value}
onChange={(e) =>
handleChange({ ...filterParameters, value: e.target.value })
}
onBlur={handleBlur}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment
position="end"
sx={{ cursor: "pointer" }}
onClick={handleOpenFilterBox}
>
<FilterListIcon />
</InputAdornment>
),
}}
InputLabelProps={{ shrink: true }}
/>
);
function CustomTextField({ item, filterParameters, handleOpenFilterBox, handleBlur, handleChange }) {
return (
<TextField
id={item.id}
name={item.id}
label={item.header}
value={filterParameters.value}
onChange={(e) => handleChange({ ...filterParameters, value: e.target.value })}
onBlur={handleBlur}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment position="end" sx={{ cursor: "pointer" }} onClick={handleOpenFilterBox}>
<FilterListIcon />
</InputAdornment>
),
}}
InputLabelProps={{ shrink: true }}
/>
);
}
export default CustomTextField;

View File

@@ -2,84 +2,73 @@ import { Box, InputAdornment, TextField, Typography } from "@mui/material";
import FilterListIcon from "@mui/icons-material/FilterList";
function CustomTextFieldRange({
item,
defaultFilterTranslation,
handleOpenFilterBox,
handleChange,
filterParameters,
handleBlur,
errors,
item,
defaultFilterTranslation,
handleOpenFilterBox,
handleChange,
filterParameters,
handleBlur,
errors,
}) {
return (
<Box sx={{ display: "flex" }}>
<TextField
id={`${item.id}.value[0]`}
name={`${item.id}.value[0]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [e.target.value, filterParameters.value[1]],
})
}
onBlur={handleBlur}
label={<Typography>از {item.header}</Typography>}
value={filterParameters.value[0]}
fullWidth
error={
touched?.[`${item.id}`]?.value &&
Boolean(errors?.[`${item.id}`]?.value)
}
helperText={
<Typography
variant="caption"
sx={{
color: (theme) => theme.palette.primary.main,
fontWeight: "bold",
}}
>
نوع فیلتر: {defaultFilterTranslation}
</Typography>
}
variant="outlined"
size="small"
sx={{ my: 1, marginRight: 1 }}
/>
<TextField
id={`${item.id}.value[1]`}
name={`${item.id}.value[1]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [filterParameters.value[0], e.target.value],
})
}
onBlur={handleBlur}
error={Boolean(errors?.[`${item.id}`]?.value)}
helperText={
errors?.[`${item.id}`]?.value
? errors?.[`${item.id}`]?.value.message
: null
}
label={<Typography>تا {item.header}</Typography>}
value={filterParameters.value[1]}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment
position="end"
sx={{ cursor: "pointer" }}
onClick={handleOpenFilterBox}
>
<FilterListIcon />
</InputAdornment>
),
}}
/>
</Box>
);
return (
<Box sx={{ display: "flex" }}>
<TextField
id={`${item.id}.value[0]`}
name={`${item.id}.value[0]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [e.target.value, filterParameters.value[1]],
})
}
onBlur={handleBlur}
label={<Typography>از {item.header}</Typography>}
value={filterParameters.value[0]}
fullWidth
error={touched?.[`${item.id}`]?.value && Boolean(errors?.[`${item.id}`]?.value)}
helperText={
<Typography
variant="caption"
sx={{
color: (theme) => theme.palette.primary.main,
fontWeight: "bold",
}}
>
نوع فیلتر: {defaultFilterTranslation}
</Typography>
}
variant="outlined"
size="small"
sx={{ my: 1, marginRight: 1 }}
/>
<TextField
id={`${item.id}.value[1]`}
name={`${item.id}.value[1]`}
onChange={(e) =>
handleChange({
...filterParameters,
value: [filterParameters.value[0], e.target.value],
})
}
onBlur={handleBlur}
error={Boolean(errors?.[`${item.id}`]?.value)}
helperText={errors?.[`${item.id}`]?.value ? errors?.[`${item.id}`]?.value.message : null}
label={<Typography>تا {item.header}</Typography>}
value={filterParameters.value[1]}
fullWidth
variant="outlined"
size="small"
sx={{ my: 1 }}
InputProps={{
endAdornment: (
<InputAdornment position="end" sx={{ cursor: "pointer" }} onClick={handleOpenFilterBox}>
<FilterListIcon />
</InputAdornment>
),
}}
/>
</Box>
);
}
export default CustomTextFieldRange;

View File

@@ -8,15 +8,14 @@ import FilterController from "./FilterController";
import FilterControllerWithDependency from "./FilterControllerWithDependency";
const headerSx = {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: (theme) => theme.palette.primary.main,
boxShadow:
"rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
px: 2,
py: 1,
backgroundColor: (theme) => theme.palette.primary.main,
boxShadow: "rgba(0, 0, 0, 0.19) 0px 10px 20px, rgba(0, 0, 0, 0.23) 0px 6px 6px",
maxWidth: "450px",
};
const headerTitleSx = { display: "flex", alignItems: "center" };
@@ -25,136 +24,135 @@ const iconButtonSx = { color: "#fff" };
const formContainerSx = { px: 2, py: 3 };
const footerSx = {
display: "flex",
justifyContent: "center",
alignItems: "center",
pb: 2,
display: "flex",
justifyContent: "center",
alignItems: "center",
pb: 2,
};
const submitButtonSx = {
px: 8,
boxShadow:
"rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
backgroundColor: "primary2",
":hover": { backgroundColor: "primary2" },
px: 8,
boxShadow: "rgba(0, 0, 0, 0.23) 0px 6px 6px, rgba(0, 0, 0, 0.19) 10px 0px 20px",
backgroundColor: "primary2",
":hover": { backgroundColor: "primary2" },
};
const validationSchema = Yup.object({
activity_date_time: Yup.array()
.of(Yup.string().nullable())
.test({
test(value, ctx) {
const [start, end] = value || ["", ""];
if ((start && !end) || (!start && end)) {
return ctx.createError({ message: "این بخش را تکمیل نمایید" });
}
return true;
},
}),
activity_date_time: Yup.array()
.of(Yup.string().nullable())
.test({
test(value, ctx) {
const [start, end] = value || ["", ""];
if ((start && !end) || (!start && end)) {
return ctx.createError({ message: "این بخش را تکمیل نمایید" });
}
return true;
},
}),
});
const FilterDrawer = ({ defaultValues, setFilterData, closeDrawer }) => {
const {
control,
errors,
reset,
handleSubmit,
formState: { isDirty },
} = useForm({
defaultValues,
resolver: yupResolver(
Yup.object(
Object.keys(defaultValues).reduce((acc, key) => {
const initialValue = defaultValues[key];
if (initialValue.filterMode === "between") {
acc[key] = Yup.object().shape({
value: Yup.array()
.of(Yup.string().nullable())
.test({
test(value, ctx) {
const [start, end] = value || ["", ""];
if (
initialValue.datatype === "numeric" &&
parseInt(end, 10) <= parseInt(start, 10)
) {
return ctx.createError({
message: `مقدار وارده باید بیشتر از (${start}) باشد`,
});
} else if ((start && !end) || (!start && end)) {
return ctx.createError({
message: "این بخش را تکمیل نمایید",
});
const {
control,
errors,
reset,
handleSubmit,
formState: { isDirty },
} = useForm({
defaultValues,
resolver: yupResolver(
Yup.object(
Object.keys(defaultValues).reduce((acc, key) => {
const initialValue = defaultValues[key];
if (initialValue.filterMode === "between") {
acc[key] = Yup.object().shape({
value: Yup.array()
.of(Yup.string().nullable())
.test({
test(value, ctx) {
const [start, end] = value || ["", ""];
if (
initialValue.datatype === "numeric" &&
parseInt(end, 10) <= parseInt(start, 10)
) {
return ctx.createError({
message: `مقدار وارده باید بیشتر از (${start}) باشد`,
});
} else if ((start && !end) || (!start && end)) {
return ctx.createError({
message: "این بخش را تکمیل نمایید",
});
}
return true;
},
}),
});
}
return true;
},
}),
});
}
return acc;
}, {}),
),
),
mode: "all",
});
return acc;
}, {})
)
),
mode: "all",
});
const onSubmit = (data) => {
setFilterData(data);
closeDrawer();
};
const onSubmit = (data) => {
setFilterData(data);
closeDrawer();
};
return (
<>
<Box sx={headerSx}>
<Box sx={headerTitleSx}>
<FilterAlt sx={headerIconSx} />
<Typography variant="h6" sx={{ color: "#fff" }}>
فیلتر
</Typography>
</Box>
<IconButton sx={iconButtonSx} onClick={closeDrawer}>
<Cancel sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
<ScrollBox>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={formContainerSx}>
{Object.values(defaultValues).map(
(item) =>
item.enable &&
(item.dependencyId ? (
<FilterControllerWithDependency
key={item.id}
item={item}
control={control}
errors={errors}
reset={reset}
/>
) : (
<FilterController
key={item.id}
item={item}
control={control}
errors={errors}
reset={reset}
/>
)),
)}
<Box sx={footerSx}>
<Button
type="submit"
variant="contained"
size="large"
disabled={!isDirty}
sx={submitButtonSx}
>
اعمال فیلتر
</Button>
return (
<>
<Box sx={headerSx}>
<Box sx={headerTitleSx}>
<FilterAlt sx={headerIconSx} />
<Typography variant="h6" sx={{ color: "#fff" }}>
فیلتر
</Typography>
</Box>
<IconButton sx={iconButtonSx} onClick={closeDrawer}>
<Cancel sx={{ fontSize: "1em" }} />
</IconButton>
</Box>
</Box>
</form>
</ScrollBox>
</>
);
<ScrollBox>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={formContainerSx}>
{Object.values(defaultValues).map(
(item) =>
item.enable &&
(item.dependencyId ? (
<FilterControllerWithDependency
key={item.id}
item={item}
control={control}
errors={errors}
reset={reset}
/>
) : (
<FilterController
key={item.id}
item={item}
control={control}
errors={errors}
reset={reset}
/>
))
)}
<Box sx={footerSx}>
<Button
type="submit"
variant="contained"
size="large"
disabled={!isDirty}
sx={submitButtonSx}
>
اعمال فیلتر
</Button>
</Box>
</Box>
</form>
</ScrollBox>
</>
);
};
export default FilterDrawer;

View File

@@ -4,79 +4,65 @@ import SvgLoading from "@/core/components/svgs/SvgLoading";
import { Backdrop, Box, Stack, styled, useTheme } from "@mui/material";
const LoadingImage = styled(Box)({
"@keyframes load": {
"0%": {
transform: "scale(1)",
"@keyframes load": {
"0%": {
transform: "scale(1)",
},
"50%": {
transform: "scale(.5)",
},
"100%": {
transform: "scale(1)",
},
},
"50%": {
transform: "scale(.5)",
},
"100%": {
transform: "scale(1)",
},
},
animation: "load 2s infinite",
animation: "load 2s infinite",
});
const LoadingHardPage = ({
children,
loading,
authState = false,
sx = {},
icon = null,
width = 200,
height = 200,
label = "",
children,
loading,
authState = false,
sx = {},
icon = null,
width = 200,
height = 200,
label = "",
}) => {
const theme = useTheme();
return (
<>
<Backdrop
sx={{
bgcolor: "#fff",
zIndex: (theme) => theme.zIndex.drawer + 1,
...sx,
}}
open={loading}
>
<Stack alignItems={"center"} spacing={2}>
{authState ? (
<Box>
{icon ? (
<Box
sx={{ color: "primary.main", width: width, height: height }}
>
{icon}
</Box>
) : (
<SvgError
color={theme.palette.error.main}
width={width}
height={height}
/>
)}
</Box>
) : (
<LoadingImage>
{icon ? (
<Box
sx={{ color: "primary.main", width: width, height: height }}
>
{icon}
</Box>
) : (
<SvgLoading width={width} height={height} />
)}
</LoadingImage>
)}
<Stack sx={{ color: authState ? "error.main" : "primary.main" }}>
{label}
</Stack>
</Stack>
</Backdrop>
{children}
</>
);
const theme = useTheme();
return (
<>
<Backdrop
sx={{
bgcolor: "#fff",
zIndex: (theme) => theme.zIndex.drawer + 1,
...sx,
}}
open={loading}
>
<Stack alignItems={"center"} spacing={2}>
{authState ? (
<Box>
{icon ? (
<Box sx={{ color: "primary.main", width: width, height: height }}>{icon}</Box>
) : (
<SvgError color={theme.palette.error.main} width={width} height={height} />
)}
</Box>
) : (
<LoadingImage>
{icon ? (
<Box sx={{ color: "primary.main", width: width, height: height }}>{icon}</Box>
) : (
<SvgLoading width={width} height={height} />
)}
</LoadingImage>
)}
<Stack sx={{ color: authState ? "error.main" : "primary.main" }}>{label}</Stack>
</Stack>
</Backdrop>
{children}
</>
);
};
export default LoadingHardPage;

View File

@@ -1,10 +1,10 @@
import { styled, TextField } from "@mui/material";
const LtrTextField = styled(TextField)`
.MuiInputBase-input {
/* @noflip */
direction: ltr;
}
.MuiInputBase-input {
/* @noflip */
direction: ltr;
}
`;
export default LtrTextField;

View File

@@ -7,88 +7,66 @@ import { toast } from "react-toastify";
import useTableSetting from "@/lib/hooks/useTableSetting";
import { flattenObjectOfObjects } from "@/core/utils/flattenObjectOfObjects";
function AskForKeepData({
filterData,
sortData,
hideData,
user_id,
page_name,
table_name,
columns,
}) {
const { filterAction, sortAction, hideAction } = useTableSetting();
function AskForKeepData({ filterData, sortData, hideData, user_id, page_name, table_name, columns }) {
const { filterAction, sortAction, hideAction } = useTableSetting();
const filteredHideData = Object.fromEntries(
Object.entries(hideData).filter(([key, value]) => value === false),
);
const filteredHideData = Object.fromEntries(Object.entries(hideData).filter(([key, value]) => value === false));
const flattenHideData = flattenObjectOfObjects(filteredHideData);
const flattenHideData = flattenObjectOfObjects(filteredHideData);
const onSaveFilter = () => {
const filteredItems = Object.keys(filterData)
.map((key) => {
const value = filterData[key].value;
if (
value !== "" &&
!(
Array.isArray(value) &&
(value.length === 0 ||
(value.length === 2 && value[0] === "" && value[1] === ""))
)
) {
return filterData[key];
}
})
.filter(Boolean);
filterAction(user_id, page_name, table_name, filteredItems, columns);
sortAction(user_id, page_name, table_name, sortData, columns);
hideAction(user_id, page_name, table_name, flattenHideData, columns);
toast.dismiss({ containerId: "datatable" });
};
const onSaveFilter = () => {
const filteredItems = Object.keys(filterData)
.map((key) => {
const value = filterData[key].value;
if (
value !== "" &&
!(
Array.isArray(value) &&
(value.length === 0 || (value.length === 2 && value[0] === "" && value[1] === ""))
)
) {
return filterData[key];
}
})
.filter(Boolean);
filterAction(user_id, page_name, table_name, filteredItems, columns);
sortAction(user_id, page_name, table_name, sortData, columns);
hideAction(user_id, page_name, table_name, flattenHideData, columns);
toast.dismiss({ containerId: "datatable" });
};
const handleDismiss = () => {
toast.dismiss({ containerId: "datatable" });
};
const handleDismiss = () => {
toast.dismiss({ containerId: "datatable" });
};
return (
<Box sx={{ width: "100%" }}>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
mb: 1,
}}
>
<Typography
color="primary.main"
variant="subtitle1"
sx={{ fontWeight: "500" }}
>
ذخیره سازی تغییرات
</Typography>
<SaveIcon sx={{ color: "primary.main" }} />
</Box>
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟
</Typography>
</Box>
<Box sx={{ display: "flex", gap: 1, mt: 2 }}>
<Button
variant="contained"
size="small"
endIcon={<DownloadIcon />}
onClick={onSaveFilter}
>
ذخیره
</Button>
<Button variant="outlined" size="small" onClick={handleDismiss}>
رد کردن
</Button>
</Box>
</Box>
);
return (
<Box sx={{ width: "100%" }}>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
mb: 1,
}}
>
<Typography color="primary.main" variant="subtitle1" sx={{ fontWeight: "500" }}>
ذخیره سازی تغییرات
</Typography>
<SaveIcon sx={{ color: "primary.main" }} />
</Box>
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">آیا مایل به ذخیره تغییر های اعمال شده برای دفعات بعد هستید؟</Typography>
</Box>
<Box sx={{ display: "flex", gap: 1, mt: 2 }}>
<Button variant="contained" size="small" endIcon={<DownloadIcon />} onClick={onSaveFilter}>
ذخیره
</Button>
<Button variant="outlined" size="small" onClick={handleDismiss}>
رد کردن
</Button>
</Box>
</Box>
);
}
export default AskForKeepData;

View File

@@ -3,23 +3,18 @@ import { Paper } from "@mui/material";
import LoadingHardPage from "./LoadingHardPage";
const PageLoading = () => {
return (
<Paper
elevation={0}
sx={{
position: "relative",
overflowX: "hidden",
width: "100%",
height: "100%",
}}
>
<LoadingHardPage
width={100}
height={100}
loading={true}
sx={{ position: "absolute" }}
/>
</Paper>
);
return (
<Paper
elevation={0}
sx={{
position: "relative",
overflowX: "hidden",
width: "100%",
height: "100%",
}}
>
<LoadingHardPage width={100} height={100} loading={true} sx={{ position: "absolute" }} />
</Paper>
);
};
export default PageLoading;

View File

@@ -3,16 +3,16 @@
import { Chip, Divider, Typography } from "@mui/material";
const PageTitle = ({ title }) => {
return (
<Divider>
<Chip
label={
<Typography fontSize={14} fontWeight={500}>
{title}
</Typography>
}
/>
</Divider>
);
return (
<Divider>
<Chip
label={
<Typography fontSize={14} fontWeight={500}>
{title}
</Typography>
}
/>
</Divider>
);
};
export default PageTitle;

View File

@@ -1,15 +1,15 @@
"use client";
import {
Chip,
Divider,
FormControl,
FormHelperText,
Grid,
IconButton,
InputAdornment,
InputLabel,
OutlinedInput,
Chip,
Divider,
FormControl,
FormHelperText,
Grid,
IconButton,
InputAdornment,
InputLabel,
OutlinedInput,
} from "@mui/material";
import StyledForm from "@/core/components/StyledForm";
import { useForm } from "react-hook-form";
@@ -22,164 +22,133 @@ import VisibilityOff from "@mui/icons-material/VisibilityOff";
import useRequest from "@/lib/hooks/useRequest";
const validationSchema = object({
current_password: string().required("اجباری"),
new_password: string().required("اجباری"),
repeat_new_password: string()
.required("اجباری")
.test(
"password-match",
"رمز عبور جدید و تکرار آن باید یکسان باشند",
function (value) {
return this.parent.new_password === value;
},
),
current_password: string().required("اجباری"),
new_password: string().required("اجباری"),
repeat_new_password: string()
.required("اجباری")
.test("password-match", "رمز عبور جدید و تکرار آن باید یکسان باشند", function (value) {
return this.parent.new_password === value;
}),
});
const defaultValues = {
current_password: "",
new_password: "",
repeat_new_password: "",
current_password: "",
new_password: "",
repeat_new_password: "",
};
const Form = ({ handleCloseForm, setLoading }) => {
const request = useRequest();
const [showNewPassword, setShowNewPassword] = useState();
const [showRepeatNewPassword, setShowRepeatNewPassword] = useState();
const request = useRequest();
const [showNewPassword, setShowNewPassword] = useState();
const [showRepeatNewPassword, setShowRepeatNewPassword] = useState();
const {
register,
handleSubmit,
formState: { isSubmitting, errors },
} = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
const {
register,
handleSubmit,
formState: { isSubmitting, errors },
} = useForm({ defaultValues, resolver: yupResolver(validationSchema) });
useEffect(() => {
setLoading(isSubmitting);
}, [isSubmitting]);
useEffect(() => {
setLoading(isSubmitting);
}, [isSubmitting]);
const onSubmit = async (data) => {
console.log(data);
const onSubmit = async (data) => {
console.log(data);
const formData = new FormData();
formData.append("current_password", data.current_password);
formData.append("new_password", data.new_password);
try {
await request(CHANGE_USER_PASSWORD, "post", { data: formData });
handleCloseForm();
} catch (error) {}
};
const formData = new FormData();
formData.append("current_password", data.current_password);
formData.append("new_password", data.new_password);
try {
await request(CHANGE_USER_PASSWORD, "post", { data: formData });
handleCloseForm();
} catch (error) {}
};
return (
<>
<Divider sx={{ mb: 3 }}>
<Chip color="primary" variant="outlined" label="تغییر رمز عبور" />
</Divider>
<StyledForm onSubmit={handleSubmit(onSubmit)} id={"ChangePassword"}>
<Grid container columns={1} spacing={3}>
<Grid size={1}>
<FormControl
error={!!errors.current_password}
size="small"
fullWidth
variant="outlined"
>
<InputLabel htmlFor="current_password">رمز عبور فعلی</InputLabel>
<OutlinedInput
id="current_password"
label="رمز عبور فعلی"
autoComplete="off"
{...register("current_password")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="current_password">
{errors.current_password
? errors.current_password.message
: null}
</FormHelperText>
</FormControl>
</Grid>
<Grid size={1}>
<FormControl
error={!!errors.new_password}
size="small"
fullWidth
variant="outlined"
>
<InputLabel htmlFor="new_password">رمز عبور جدید</InputLabel>
<OutlinedInput
id="new_password"
autoComplete="off"
{...register("new_password")}
label="رمز عبور جدید"
size="small"
fullWidth
type={showNewPassword ? "text" : "password"}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() => setShowNewPassword(!showNewPassword)}
onMouseDown={(event) => event.preventDefault()}
edge="end"
>
{showNewPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
<FormHelperText id="new_password">
{errors.new_password ? errors.new_password.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid size={1}>
<FormControl
error={!!errors.repeat_new_password}
size="small"
fullWidth
variant="outlined"
>
<InputLabel htmlFor="repeat_new_password">
تکرار رمز عبور جدید
</InputLabel>
<OutlinedInput
id="repeat_new_password"
autoComplete="off"
{...register("repeat_new_password")}
size="small"
fullWidth
label="تکرار رمز عبور جدید"
type={showRepeatNewPassword ? "text" : "password"}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() =>
setShowRepeatNewPassword(!showRepeatNewPassword)
}
onMouseDown={(event) => event.preventDefault()}
edge="end"
>
{showRepeatNewPassword ? (
<VisibilityOff />
) : (
<Visibility />
)}
</IconButton>
</InputAdornment>
}
/>
<FormHelperText id="repeat_new_password">
{errors.repeat_new_password
? errors.repeat_new_password.message
: null}
</FormHelperText>
</FormControl>
</Grid>
</Grid>
</StyledForm>
</>
);
return (
<>
<Divider sx={{ mb: 3 }}>
<Chip color="primary" variant="outlined" label="تغییر رمز عبور" />
</Divider>
<StyledForm onSubmit={handleSubmit(onSubmit)} id={"ChangePassword"}>
<Grid container columns={1} spacing={3}>
<Grid size={1}>
<FormControl error={!!errors.current_password} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="current_password">رمز عبور فعلی</InputLabel>
<OutlinedInput
id="current_password"
label="رمز عبور فعلی"
autoComplete="off"
{...register("current_password")}
size="small"
fullWidth
type="text"
/>
<FormHelperText id="current_password">
{errors.current_password ? errors.current_password.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid size={1}>
<FormControl error={!!errors.new_password} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="new_password">رمز عبور جدید</InputLabel>
<OutlinedInput
id="new_password"
autoComplete="off"
{...register("new_password")}
label="رمز عبور جدید"
size="small"
fullWidth
type={showNewPassword ? "text" : "password"}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() => setShowNewPassword(!showNewPassword)}
onMouseDown={(event) => event.preventDefault()}
edge="end"
>
{showNewPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
<FormHelperText id="new_password">
{errors.new_password ? errors.new_password.message : null}
</FormHelperText>
</FormControl>
</Grid>
<Grid size={1}>
<FormControl error={!!errors.repeat_new_password} size="small" fullWidth variant="outlined">
<InputLabel htmlFor="repeat_new_password">تکرار رمز عبور جدید</InputLabel>
<OutlinedInput
id="repeat_new_password"
autoComplete="off"
{...register("repeat_new_password")}
size="small"
fullWidth
label="تکرار رمز عبور جدید"
type={showRepeatNewPassword ? "text" : "password"}
endAdornment={
<InputAdornment position="end">
<IconButton
aria-label="toggle password visibility"
onClick={() => setShowRepeatNewPassword(!showRepeatNewPassword)}
onMouseDown={(event) => event.preventDefault()}
edge="end"
>
{showRepeatNewPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
}
/>
<FormHelperText id="repeat_new_password">
{errors.repeat_new_password ? errors.repeat_new_password.message : null}
</FormHelperText>
</FormControl>
</Grid>
</Grid>
</StyledForm>
</>
);
};
export default Form;

View File

@@ -6,40 +6,34 @@ import { useState } from "react";
import Form from "./Form";
const ChangePassword = ({ open, setOpen }) => {
const [loading, setLoading] = useState(false);
const [loading, setLoading] = useState(false);
const handleCloseForm = () => {
setOpen(false);
};
const handleCloseForm = () => {
setOpen(false);
};
return (
<Dialog maxWidth="xs" fullWidth={true} open={open}>
<DialogContent dividers>
<Form handleCloseForm={handleCloseForm} setLoading={setLoading} />
</DialogContent>
<DialogActions>
<Button
disabled={loading}
variant="outlined"
color="secondary"
size="large"
onClick={handleCloseForm}
>
بستن
</Button>
<Button
type="submit"
disabled={loading}
form="ChangePassword"
size="large"
autoFocus
variant="contained"
endIcon={<SaveIcon />}
>
تغییر
</Button>
</DialogActions>
</Dialog>
);
return (
<Dialog maxWidth="xs" fullWidth={true} open={open}>
<DialogContent dividers>
<Form handleCloseForm={handleCloseForm} setLoading={setLoading} />
</DialogContent>
<DialogActions>
<Button disabled={loading} variant="outlined" color="secondary" size="large" onClick={handleCloseForm}>
بستن
</Button>
<Button
type="submit"
disabled={loading}
form="ChangePassword"
size="large"
autoFocus
variant="contained"
endIcon={<SaveIcon />}
>
تغییر
</Button>
</DialogActions>
</Dialog>
);
};
export default ChangePassword;

View File

@@ -10,25 +10,25 @@ import { useState } from "react";
import ChangePassword from "./ChangePassword";
const ProfileActions = () => {
const { getUser, logout } = useAuth();
const requestServer = useRequest();
const [openUpdate, setOpenUpdate] = useState(false);
const [openChangePass, setOpenChangePass] = useState(false);
const { getUser, logout } = useAuth();
const requestServer = useRequest();
const [openUpdate, setOpenUpdate] = useState(false);
const [openChangePass, setOpenChangePass] = useState(false);
const openUpdateProfile = () => {
getUser();
setOpenUpdate(true);
};
const handleLogout = () => {
requestServer(GET_USER_LOGOUT_ROUTE, "post").then(() => {
logout();
});
};
const openUpdateProfile = () => {
getUser();
setOpenUpdate(true);
};
const handleLogout = () => {
requestServer(GET_USER_LOGOUT_ROUTE, "post").then(() => {
logout();
});
};
return (
<>
<Box sx={{ display: "flex", justifyContent: "center" }}>
{/* <Tooltip title="ویرایش پروفایل" arrow>
return (
<>
<Box sx={{ display: "flex", justifyContent: "center" }}>
{/* <Tooltip title="ویرایش پروفایل" arrow>
<IconButton
aria-label="ویرایش پروفایل"
color="success"
@@ -43,32 +43,27 @@ const ProfileActions = () => {
flexItem
sx={{ mx: 1 }}
/> */}
<Tooltip title="خروج" arrow>
<IconButton onClick={handleLogout} aria-label="خروج" color="error">
<PowerSettingsNewIcon />
</IconButton>
</Tooltip>
<Divider
orientation="vertical"
variant="middle"
flexItem
sx={{ mx: 1 }}
/>
<Tooltip title="تغییر رمز عبور" arrow>
<IconButton
aria-label="تغییر رمز عبور"
color="primary"
onClick={() => {
setOpenChangePass(true);
}}
>
<VpnKeyIcon />
</IconButton>
</Tooltip>
</Box>
{/* <Update open={openUpdate} setOpen={setOpenUpdate} /> */}
<ChangePassword open={openChangePass} setOpen={setOpenChangePass} />
</>
);
<Tooltip title="خروج" arrow>
<IconButton onClick={handleLogout} aria-label="خروج" color="error">
<PowerSettingsNewIcon />
</IconButton>
</Tooltip>
<Divider orientation="vertical" variant="middle" flexItem sx={{ mx: 1 }} />
<Tooltip title="تغییر رمز عبور" arrow>
<IconButton
aria-label="تغییر رمز عبور"
color="primary"
onClick={() => {
setOpenChangePass(true);
}}
>
<VpnKeyIcon />
</IconButton>
</Tooltip>
</Box>
{/* <Update open={openUpdate} setOpen={setOpenUpdate} /> */}
<ChangePassword open={openChangePass} setOpen={setOpenChangePass} />
</>
);
};
export default ProfileActions;

View File

@@ -5,45 +5,34 @@ import { Avatar, Box, Chip, Divider, Stack, Typography } from "@mui/material";
import moment from "jalali-moment";
const ProfileInfo = () => {
const { user } = useAuth();
const { user } = useAuth();
return (
<>
<Box sx={{ display: "flex", alignItems: "center", my: 0.5 }}>
<Avatar
alt="User Image"
src={user?.avatar}
sx={{ width: 56, height: 56 }}
/>
<Stack sx={{ ml: 1 }}>
<Box sx={{ display: "flex", alignItems: "end", gap: 0.7 }}>
<Typography variant="h6">{`${user.full_name}`}</Typography>
</Box>
<Typography variant="caption">
شماره تماس داخلی : {user.telephone_id}
</Typography>
</Stack>
</Box>
<Box sx={{ display: "flex", alignItems: "center", my: 0.5 }}>
<Typography variant="button" color="#757575">
آخرین ورود
</Typography>
<Divider sx={{ mx: 2, flexGrow: 1 }} />
<Typography variant="subtitle2" color="#757575">
{moment(user.last_login).locale("fa").fromNow()}
</Typography>
</Box>
<Box sx={{ my: 0.5 }}>
<Divider>
<Chip
size="small"
label={user.username}
color="success"
variant="outlined"
/>
</Divider>
</Box>
</>
);
return (
<>
<Box sx={{ display: "flex", alignItems: "center", my: 0.5 }}>
<Avatar alt="User Image" src={user?.avatar} sx={{ width: 56, height: 56 }} />
<Stack sx={{ ml: 1 }}>
<Box sx={{ display: "flex", alignItems: "end", gap: 0.7 }}>
<Typography variant="h6">{`${user.full_name}`}</Typography>
</Box>
<Typography variant="caption">شماره تماس داخلی : {user.telephone_id}</Typography>
</Stack>
</Box>
<Box sx={{ display: "flex", alignItems: "center", my: 0.5 }}>
<Typography variant="button" color="#757575">
آخرین ورود
</Typography>
<Divider sx={{ mx: 2, flexGrow: 1 }} />
<Typography variant="subtitle2" color="#757575">
{moment(user.last_login).locale("fa").fromNow()}
</Typography>
</Box>
<Box sx={{ my: 0.5 }}>
<Divider>
<Chip size="small" label={user.username} color="success" variant="outlined" />
</Divider>
</Box>
</>
);
};
export default ProfileInfo;

View File

@@ -5,18 +5,18 @@ import ProfileInfo from "./ProfileInfo";
import ProfileActions from "./ProfileActions";
const Profile = () => {
return (
<Stack
sx={{
px: 2,
background: "#f7f7f7",
borderTop: "1px dashed #e1e1e1",
borderBottom: "1px dashed #e1e1e1",
}}
>
<ProfileInfo />
<ProfileActions />
</Stack>
);
return (
<Stack
sx={{
px: 2,
background: "#f7f7f7",
borderTop: "1px dashed #e1e1e1",
borderBottom: "1px dashed #e1e1e1",
}}
>
<ProfileInfo />
<ProfileActions />
</Stack>
);
};
export default Profile;

View File

@@ -1,20 +1,20 @@
import { Box, styled } from "@mui/material";
const ScrollBox = styled(Box)(({ theme }) => ({
flexGrow: 1,
overflowY: "auto",
maxWidth: "450px",
"::-webkit-scrollbar": {
width: "5px",
},
"::-webkit-scrollbar-track": {
boxShadow: "inset 0 0 5px #fff",
borderRadius: "5px",
},
"::-webkit-scrollbar-thumb": {
background: theme.palette.primary.dark,
borderRadius: "0px",
},
flexGrow: 1,
overflowY: "auto",
maxWidth: "450px",
"::-webkit-scrollbar": {
width: "5px",
},
"::-webkit-scrollbar-track": {
boxShadow: "inset 0 0 5px #fff",
borderRadius: "5px",
},
"::-webkit-scrollbar-thumb": {
background: theme.palette.primary.dark,
borderRadius: "0px",
},
}));
export default ScrollBox;

View File

@@ -3,220 +3,214 @@ import { Box, Typography } from "@mui/material";
import { Dangerous } from "@mui/icons-material";
export const errorServerToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{"The request failed due to an internal error."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 5000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{"The request failed due to an internal error."}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 5000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
export const errorUnauthorizedToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{"The user is not authorized to make the request."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{"The user is not authorized to make the request."}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
export const errorAccessDeniedToast = (message, toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message || "Access Denied"}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{message || "Access Denied"}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);
export const errorLogicToast = (message, toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message ||
"The request was well-formed but was unable to be followed due to semantic errors."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message ||
"The request was well-formed but was unable to be followed due to semantic errors."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
export const errorValidationToast = (message, toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message ||
"The request was well-formed but was unable to be followed due to semantic errors."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{message ||
"The request was well-formed but was unable to be followed due to semantic errors."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
export const errorTooManyToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{"Too many requests have been sent within a given time span."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{"Too many requests have been sent within a given time span."}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);
export const errorClientToast = (toastContainer) =>
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{
"The API request is invalid or improperly formed. Consequently, the API server could not understand the request."
}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
},
);
toast.error(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Dangerous color="error" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{
"The API request is invalid or improperly formed. Consequently, the API server could not understand the request."
}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: false,
closeOnClick: false,
draggable: false,
}
);

View File

@@ -3,33 +3,31 @@ import { Box, Typography } from "@mui/material";
import { Beenhere } from "@mui/icons-material";
export const successToast = (toastContainer) =>
toast.success(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Beenhere color="success" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">
{"عملیات با موفقیت انجام شد"}
</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
},
);
toast.success(
() => (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "start",
justifyContent: "start",
}}
>
<Box sx={{ display: "flex", alignItems: "center" }}>
<Beenhere color="success" sx={{ mr: 1.6 }} />
<Box sx={{ display: "flex", flexDirection: "column" }}>
<Typography variant="caption">{"عملیات با موفقیت انجام شد"}</Typography>
</Box>
</Box>
</Box>
),
{
icon: false,
containerId: toastContainer,
autoClose: 3000,
hideProgressBar: true,
pauseOnHover: true,
closeOnClick: false,
draggable: true,
}
);

View File

@@ -2,99 +2,94 @@
import { useTheme } from "@mui/material";
const SvgError = ({ width, height, color = null }) => {
const theme = useTheme();
const fillColor = color || theme.palette.primary.main;
const theme = useTheme();
const fillColor = color || theme.palette.primary.main;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={width}
height={height}
viewBox="0 0 524.67001 418.27099"
>
<path
d="M442.17403,400.47713c2.06599,.12871,3.20692-2.43846,1.64338-3.93389l-.1557-.61814c.0204-.04935,.04089-.09868,.06153-.14794,1.23211-2.94003,4.62545-4.33201,7.57137-3.11404,9.3142,3.85087-.51966,12.69986,.21957,18.68773,.25911,2.06671,8.35473,2.18034,7.89681,4.2086,4.30482-9.41207,6.56835-19.68889,6.56478-30.02306-.0009-2.59653-.14392-5.19297-.43543-7.78281-.23975-2.11845-.56985-4.22389-.9969-6.30999-2.30966-11.27639-7.30614-22.01572-14.51084-30.98461-3.46263-1.89129-1.35074-4.85018-3.09586-8.39544-.62694-1.27868-6.21792-1.30745-6.45092-2.70892,.25019,.03272,3.86434-3.721,2.6705-5.5767-.78555-1.22107-.54106-2.7763,.4681-3.82017,.09887-.1023,.19234-.2103,.27796-.32648,2.98093-4.04443,7.09003-3.33985,9.23695,2.15406,4.58304,2.31107,4.62871,6.14647,1.81834,9.83619-1.78798,2.34745-2.03264,5.52304-3.60129,8.03604,.16157,.20664,.32958,.40684,.49112,.61348,2.96237,3.79686,5.52482,7.87809,7.68524,12.16592-.61182-4.76599,.28705-10.50831,1.8215-14.21023,1.75933-4.24835,5.06953-7.8221,7.96883-11.49665,3.46275-4.38865,10.5104-2.39707,11.12286,3.15951,.00588,.05337,.0116,.10665,.01724,.16003-.42884,.24212-.84895,.49935-1.25929,.77094-2.33882,1.54808-1.52824,5.17442,1.24391,5.60071l.06278,.00965c-.1545,1.54372-5.63258,6.40679-6.01957,7.91187,3.70514,14.30838,.93282,16.19755-10.46624,16.43703l-.59825,.8522c1.08024,3.1058,1.94956,6.2861,2.60235,9.50743,.61462,2.99021,1.042,6.01282,1.28197,9.04845,.29847,3.82994,.27396,7.6795-.04769,11.50325l.01933-.13563c.81879-4.21143,3.1039-8.1457,6.42284-10.87249,4.94421-4.06436,11.93091-5.56281,17.2652-8.83022,2.56778-1.57285,5.85959,.45742,5.41241,3.4352l-.02177,.14262c-.79432,.32315-1.56922,.69808-2.31831,1.11814-.42921,.24237-.84965,.49978-1.26032,.77165-2.33916,1.54848-1.52796,5.1753,1.24498,5.60009l.06281,.00962c.0452,.00645,.08399,.01291,.12913,.0194-1.3617,3.23628-14.33553,7.80147-16.71149,10.39229-2.31031,12.49793-1.17531,12.12596-11.81075,8.49032h-.00647c-1.16085,5.06419-2.8578,10.01225-5.03931,14.72794l-18.0202,.00623c-.06471-.2002-.12288-.40688-.18109-.60712,1.66645,.10285,3.34571,.00534,4.98619-.29875-1.33757-1.64013-2.67509-3.29317-4.01266-4.93324-.0323-.03228-.05819-.06459-.08402-.09686l-.02036-.02517-1.85532-6.10724c.14644-1.35476,.38536-2.69828,.70958-4.02051l.00049-.00037v.00006Z"
fill="#f2f2f2"
/>
<path
d="M251.74443,416.41995l-159.45702,.05516c-8.01074,.00277-15.18649-4.13684-19.19426-11.07295-2.00413-3.46855-3.00642-7.27337-3.00774-11.07904-.00132-3.80518,.99882-7.61119,3.00007-11.08063l79.67786-145.04905c4.00346-6.93937,11.17634-11.08346,19.18708-11.08623s15.18649,4.13635,19.19475,11.07295l79.78843,145.01196c1.99876,3.45927,2.99861,7.25971,2.99894,11.06293-.00015,3.80322-.99981,7.60874-3.00154,11.07868-4.00297,6.93889-11.17585,11.08346-19.1866,11.08623h.00002Zm-179.65463-22.09948c-.00026,3.46387,17.5953-4.00023,19.41817-.8451,3.64623,6.31026-6.50934,21.00225,.77874,20.99973,0,0,173.27016-3.828,176.91202-10.14078,1.82069-3.15639,2.73062-6.61911,2.72942-10.08102s-.91353-6.92351-2.73688-10.07864l-79.78845-145.01196c-3.63597-6.2922-10.16364-10.05801-17.45172-10.05549-7.28467,.00252-99.86105,161.74891-99.86132,165.21326h.00002Z"
fill="#3f3d56"
/>
<path
d="M253.51521,414.41934c-1.99862,4.00069,91.61376,2.7712,92.72051,2.77082,0,0,26.3119-.58131,26.86492-1.53993,.27648-.47931,.41466-1.00515,.41448-1.53084s-.13873-1.05137-.4156-1.5305l-12.11626-22.02074c-.55215-.9555-1.54341-1.52736-2.65013-1.52698-.04608,.00002-.11394,.04093-.20168,.11933-16.16328,14.44385-36.0828,23.99237-57.75707,24.31469-23.047,.34272-46.73217,.6899-46.85919,.94416h.00002Z"
fill="#3f3d56"
/>
<path
d="M0,417.0814c.00023,.66003,.53044,1.18982,1.19047,1.18959l522.28995-.18066c.65997-.00023,1.18982-.53038,1.18959-1.19041-.00023-.65997-.53044-1.18982-1.19041-1.18959l-522.28995,.18066c-.66003,.00023-1.18988,.53044-1.18965,1.19041Z"
fill="#ccc"
/>
<g>
<polygon
points="403.87773 411.30541 394.83299 411.30765 390.51828 376.42194 403.86746 376.41823 403.87773 411.30541"
fill="#a0616a"
/>
<path
d="M372.88925,411.11096h0c-.28145,.4744-.42951,2.00528-.42932,2.55685h0c.00059,1.6954,1.37542,3.06935,3.07089,3.06876l28.01047-.00969c1.15659-.0004,2.09391-.93832,2.09351-2.09496l-.0004-1.16617s1.38444-3.50542-1.46987-7.82444c0,0-3.54448,3.38386-8.84444-1.91244l-1.56336-2.82981-11.30656,8.27506-6.26838,.77377c-1.3714,.16927-2.58738-.02532-3.29241,1.16307h-.00012Z"
fill="#2f2e41"
/>
</g>
<g>
<polygon
points="369.19708 381.46752 360.62951 384.36642 345.36911 352.70019 358.01396 348.42131 369.19708 381.46752"
fill="#a0616a"
/>
<path
d="M339.77867,391.20807h0c-.11468,.53956,.23535,2.03724,.41217,2.5597h0c.54355,1.60589,2.28601,2.46714,3.89196,1.92358l26.53193-8.98019c1.09554-.3708,1.68312-1.55951,1.31228-2.65512l-.37389-1.10461s.18882-3.76416-3.8984-6.94155c0,0-2.27401,4.34084-8.99107,1.02096l-2.38732-2.18005-8.0607,11.46034-5.69037,2.74062c-1.24494,.59958-2.45919,.80471-2.74651,2.15628l-.00009,.00003Z"
fill="#2f2e41"
/>
</g>
<polygon
points="355.22599 179.09003 337.68255 237.19081 316.97199 289.45207 349.76053 364.08569 361.91802 358.67731 347.37062 290.11706 377.87822 243.59436 392.11437 388.82623 404.27349 388.14652 420.76309 212.84336 423.11421 174.67566 355.22599 179.09003"
fill="#2f2e41"
/>
<path
d="M408.20979,50.38513l-25.66813,4.73752-2.02258,11.48454-15.53439,7.43609-8.07702,84.4428s-13.50433,17.56819-2.69414,22.96862l68.9007-6.77904s3.37327-12.4903-.00473-13.67529-3.38832-31.01955-3.38832-31.01955l15.51573-61.36599-22.97048-8.09829-4.05664-10.13141Z"
fill="#e6e6e6"
/>
<circle cx="393.06995" cy="29.43589" r="20.7276" fill="#a0616a" />
<path
d="M406.79605,32.51227c-1.65401,.9055-.08471,5.22869-1.11848,5.60245-1.19492,.43202-5.55162-4.52715-5.60554-10.08176-.01633-1.68115,.37051-2.48839-.00155-4.48164-.48668-2.6073-1.98045-5.68253-3.36317-5.60089-.81965,.04839-1.62013,1.20723-1.67986,2.2414-.0837,1.44941,1.32419,2.01989,1.12139,2.80064-.38627,1.4871-6.29829,2.5138-8.40308,.00291-1.65013-1.9685-.38463-5.4247-1.12236-5.60167-.54378-.13045-1.12759,1.77241-3.35988,3.9226-.84103,.8101-2.09186,2.0149-2.80044,1.68159-1.02397-.48167-.28003-3.87624-.56157-3.92125-.23314-.03727-.37947,2.3487-1.67908,4.48223-1.66968,2.74103-5.11398,4.85374-6.72112,3.92377-.98466-.56978-1.06245-2.15606-1.12158-3.36084-.1245-2.53816-3.81308-8.37644-2.85882-11.09166,1.94221-5.5263,5.2701-1.63078,6.7752-3.47504,2.03756-2.49669,3.86572-1.15434,7.28133-3.92396,3.33668-2.70564,3.36577-5.42504,5.60011-5.604,2.01221-.16116,2.7278,1.98528,5.04242,1.67887,1.96079-.25957,2.38749-1.92436,3.92087-1.68198,1.40389,.2219,1.49646,1.68849,3.36201,2.23966,1.19101,.35188,1.45267-.15743,2.80103-.00097,2.80559,.32556,4.69002,2.88083,5.043,3.35949,1.36081,1.84526,.83282,2.62341,2.24236,4.48086,1.21555,1.6018,3.90913,.9216,4.92189,1.72162,3.30928,2.61409,4.73124,7.43497,4.75994,12.92962,.0201,3.8431-.48103,5.78482-1.59913,10.63564-.84901,3.6834-4.78175,8.44334-6.94987,10.5659-.58199,.56975-2.21351,2.167-3.36066,1.68178-1.08704-.45979-1.11995-2.52764-1.12139-2.80064-.0049-.93901,.24521-2.1009,2.23907-5.04263,2.09442-3.09006,2.92645-3.44271,2.79948-4.48262-.22445-1.83818-3.16424-3.52123-4.48263-2.79948h.00012Z"
fill="#2f2e41"
/>
<g>
<path
d="M334.49457,225.75979c-.64513,5.40264,1.61895,10.11513,5.05699,10.52567s6.7481-3.63632,7.39324-9.03898c.28242-2.36492,.00723-4.59754-.6797-6.39504l2.44642-22.92684-10.7834-.91891-1.26717,22.69891c-1.09088,1.58522-1.88401,3.69026-2.16639,6.05519h.00003Z"
fill="#a0616a"
/>
<path
d="M365.49095,73.49769s-5.58664,.07946-9.28568,7.30383c-1.96565,3.83897-12.48211,75.62767-12.48211,75.62767l-9.68742,58.80847,16.50214,.08313,12.859-55.69302,10.81723-32.30088-8.72315-53.82921Z"
fill="#e6e6e6"
/>
</g>
<path
d="M411.92961,217.13028c-1.58023,5.20651-.17535,10.24237,3.13786,11.24797s7.28015-2.39987,8.86035-7.60638c.69172-2.27906,.81133-4.5254,.44941-6.41533l6.4191-22.14543-10.45641-2.79098-5.21815,22.12729c-1.35133,1.36996-2.50044,3.30383-3.19216,5.58289v-.00003Z"
fill="#a0616a"
/>
<path
d="M423.41564,69.63219s8.10413-6.08248,14.86262,3.37246c6.75846,9.45495,9.48742,87.1388,9.48742,87.1388l-18.89796,47.96845-14.18755-4.72373,13.49008-58.7749-23.65861-44.57614,18.90403-30.40494h-.00003Z"
fill="#e6e6e6"
/>
<g>
<circle cx="218.47958" cy="311.43145" r="73" fill={fillColor} />
<g>
<circle cx="218.49274" cy="349.47878" r="6.70264" fill="#fff" />
<path
d="M218.4641,266.68145c-.6157,4.0912,.48747,4.94727,.49357,22.58508,.0061,17.63782,3.66579,41.28574-.47148,41.28717s-5.65047-48.80276-20.01681-53.12218c-16.89088-5.07846,21.98785-23.99409,19.99471-10.75007Z"
fill="#fff"
/>
</g>
</g>
<path
d="M120.50313,348.70219l-6.59532,13.93527c7.97328-5.71745,20.42715-10.64598,30.3376-13.28567-9.23403-4.46037-20.53313-11.65189-27.2835-18.77194l3.7934,14.72434c-44.47393-9.0585-76.41138-43.17661-76.4249-82.25924l-1.60648-.5527c.01412,40.82281,31.50971,76.96121,77.7792,86.20995Z"
fill="#3f3d56"
/>
</svg>
);
return (
<svg xmlns="http://www.w3.org/2000/svg" width={width} height={height} viewBox="0 0 524.67001 418.27099">
<path
d="M442.17403,400.47713c2.06599,.12871,3.20692-2.43846,1.64338-3.93389l-.1557-.61814c.0204-.04935,.04089-.09868,.06153-.14794,1.23211-2.94003,4.62545-4.33201,7.57137-3.11404,9.3142,3.85087-.51966,12.69986,.21957,18.68773,.25911,2.06671,8.35473,2.18034,7.89681,4.2086,4.30482-9.41207,6.56835-19.68889,6.56478-30.02306-.0009-2.59653-.14392-5.19297-.43543-7.78281-.23975-2.11845-.56985-4.22389-.9969-6.30999-2.30966-11.27639-7.30614-22.01572-14.51084-30.98461-3.46263-1.89129-1.35074-4.85018-3.09586-8.39544-.62694-1.27868-6.21792-1.30745-6.45092-2.70892,.25019,.03272,3.86434-3.721,2.6705-5.5767-.78555-1.22107-.54106-2.7763,.4681-3.82017,.09887-.1023,.19234-.2103,.27796-.32648,2.98093-4.04443,7.09003-3.33985,9.23695,2.15406,4.58304,2.31107,4.62871,6.14647,1.81834,9.83619-1.78798,2.34745-2.03264,5.52304-3.60129,8.03604,.16157,.20664,.32958,.40684,.49112,.61348,2.96237,3.79686,5.52482,7.87809,7.68524,12.16592-.61182-4.76599,.28705-10.50831,1.8215-14.21023,1.75933-4.24835,5.06953-7.8221,7.96883-11.49665,3.46275-4.38865,10.5104-2.39707,11.12286,3.15951,.00588,.05337,.0116,.10665,.01724,.16003-.42884,.24212-.84895,.49935-1.25929,.77094-2.33882,1.54808-1.52824,5.17442,1.24391,5.60071l.06278,.00965c-.1545,1.54372-5.63258,6.40679-6.01957,7.91187,3.70514,14.30838,.93282,16.19755-10.46624,16.43703l-.59825,.8522c1.08024,3.1058,1.94956,6.2861,2.60235,9.50743,.61462,2.99021,1.042,6.01282,1.28197,9.04845,.29847,3.82994,.27396,7.6795-.04769,11.50325l.01933-.13563c.81879-4.21143,3.1039-8.1457,6.42284-10.87249,4.94421-4.06436,11.93091-5.56281,17.2652-8.83022,2.56778-1.57285,5.85959,.45742,5.41241,3.4352l-.02177,.14262c-.79432,.32315-1.56922,.69808-2.31831,1.11814-.42921,.24237-.84965,.49978-1.26032,.77165-2.33916,1.54848-1.52796,5.1753,1.24498,5.60009l.06281,.00962c.0452,.00645,.08399,.01291,.12913,.0194-1.3617,3.23628-14.33553,7.80147-16.71149,10.39229-2.31031,12.49793-1.17531,12.12596-11.81075,8.49032h-.00647c-1.16085,5.06419-2.8578,10.01225-5.03931,14.72794l-18.0202,.00623c-.06471-.2002-.12288-.40688-.18109-.60712,1.66645,.10285,3.34571,.00534,4.98619-.29875-1.33757-1.64013-2.67509-3.29317-4.01266-4.93324-.0323-.03228-.05819-.06459-.08402-.09686l-.02036-.02517-1.85532-6.10724c.14644-1.35476,.38536-2.69828,.70958-4.02051l.00049-.00037v.00006Z"
fill="#f2f2f2"
/>
<path
d="M251.74443,416.41995l-159.45702,.05516c-8.01074,.00277-15.18649-4.13684-19.19426-11.07295-2.00413-3.46855-3.00642-7.27337-3.00774-11.07904-.00132-3.80518,.99882-7.61119,3.00007-11.08063l79.67786-145.04905c4.00346-6.93937,11.17634-11.08346,19.18708-11.08623s15.18649,4.13635,19.19475,11.07295l79.78843,145.01196c1.99876,3.45927,2.99861,7.25971,2.99894,11.06293-.00015,3.80322-.99981,7.60874-3.00154,11.07868-4.00297,6.93889-11.17585,11.08346-19.1866,11.08623h.00002Zm-179.65463-22.09948c-.00026,3.46387,17.5953-4.00023,19.41817-.8451,3.64623,6.31026-6.50934,21.00225,.77874,20.99973,0,0,173.27016-3.828,176.91202-10.14078,1.82069-3.15639,2.73062-6.61911,2.72942-10.08102s-.91353-6.92351-2.73688-10.07864l-79.78845-145.01196c-3.63597-6.2922-10.16364-10.05801-17.45172-10.05549-7.28467,.00252-99.86105,161.74891-99.86132,165.21326h.00002Z"
fill="#3f3d56"
/>
<path
d="M253.51521,414.41934c-1.99862,4.00069,91.61376,2.7712,92.72051,2.77082,0,0,26.3119-.58131,26.86492-1.53993,.27648-.47931,.41466-1.00515,.41448-1.53084s-.13873-1.05137-.4156-1.5305l-12.11626-22.02074c-.55215-.9555-1.54341-1.52736-2.65013-1.52698-.04608,.00002-.11394,.04093-.20168,.11933-16.16328,14.44385-36.0828,23.99237-57.75707,24.31469-23.047,.34272-46.73217,.6899-46.85919,.94416h.00002Z"
fill="#3f3d56"
/>
<path
d="M0,417.0814c.00023,.66003,.53044,1.18982,1.19047,1.18959l522.28995-.18066c.65997-.00023,1.18982-.53038,1.18959-1.19041-.00023-.65997-.53044-1.18982-1.19041-1.18959l-522.28995,.18066c-.66003,.00023-1.18988,.53044-1.18965,1.19041Z"
fill="#ccc"
/>
<g>
<polygon
points="403.87773 411.30541 394.83299 411.30765 390.51828 376.42194 403.86746 376.41823 403.87773 411.30541"
fill="#a0616a"
/>
<path
d="M372.88925,411.11096h0c-.28145,.4744-.42951,2.00528-.42932,2.55685h0c.00059,1.6954,1.37542,3.06935,3.07089,3.06876l28.01047-.00969c1.15659-.0004,2.09391-.93832,2.09351-2.09496l-.0004-1.16617s1.38444-3.50542-1.46987-7.82444c0,0-3.54448,3.38386-8.84444-1.91244l-1.56336-2.82981-11.30656,8.27506-6.26838,.77377c-1.3714,.16927-2.58738-.02532-3.29241,1.16307h-.00012Z"
fill="#2f2e41"
/>
</g>
<g>
<polygon
points="369.19708 381.46752 360.62951 384.36642 345.36911 352.70019 358.01396 348.42131 369.19708 381.46752"
fill="#a0616a"
/>
<path
d="M339.77867,391.20807h0c-.11468,.53956,.23535,2.03724,.41217,2.5597h0c.54355,1.60589,2.28601,2.46714,3.89196,1.92358l26.53193-8.98019c1.09554-.3708,1.68312-1.55951,1.31228-2.65512l-.37389-1.10461s.18882-3.76416-3.8984-6.94155c0,0-2.27401,4.34084-8.99107,1.02096l-2.38732-2.18005-8.0607,11.46034-5.69037,2.74062c-1.24494,.59958-2.45919,.80471-2.74651,2.15628l-.00009,.00003Z"
fill="#2f2e41"
/>
</g>
<polygon
points="355.22599 179.09003 337.68255 237.19081 316.97199 289.45207 349.76053 364.08569 361.91802 358.67731 347.37062 290.11706 377.87822 243.59436 392.11437 388.82623 404.27349 388.14652 420.76309 212.84336 423.11421 174.67566 355.22599 179.09003"
fill="#2f2e41"
/>
<path
d="M408.20979,50.38513l-25.66813,4.73752-2.02258,11.48454-15.53439,7.43609-8.07702,84.4428s-13.50433,17.56819-2.69414,22.96862l68.9007-6.77904s3.37327-12.4903-.00473-13.67529-3.38832-31.01955-3.38832-31.01955l15.51573-61.36599-22.97048-8.09829-4.05664-10.13141Z"
fill="#e6e6e6"
/>
<circle cx="393.06995" cy="29.43589" r="20.7276" fill="#a0616a" />
<path
d="M406.79605,32.51227c-1.65401,.9055-.08471,5.22869-1.11848,5.60245-1.19492,.43202-5.55162-4.52715-5.60554-10.08176-.01633-1.68115,.37051-2.48839-.00155-4.48164-.48668-2.6073-1.98045-5.68253-3.36317-5.60089-.81965,.04839-1.62013,1.20723-1.67986,2.2414-.0837,1.44941,1.32419,2.01989,1.12139,2.80064-.38627,1.4871-6.29829,2.5138-8.40308,.00291-1.65013-1.9685-.38463-5.4247-1.12236-5.60167-.54378-.13045-1.12759,1.77241-3.35988,3.9226-.84103,.8101-2.09186,2.0149-2.80044,1.68159-1.02397-.48167-.28003-3.87624-.56157-3.92125-.23314-.03727-.37947,2.3487-1.67908,4.48223-1.66968,2.74103-5.11398,4.85374-6.72112,3.92377-.98466-.56978-1.06245-2.15606-1.12158-3.36084-.1245-2.53816-3.81308-8.37644-2.85882-11.09166,1.94221-5.5263,5.2701-1.63078,6.7752-3.47504,2.03756-2.49669,3.86572-1.15434,7.28133-3.92396,3.33668-2.70564,3.36577-5.42504,5.60011-5.604,2.01221-.16116,2.7278,1.98528,5.04242,1.67887,1.96079-.25957,2.38749-1.92436,3.92087-1.68198,1.40389,.2219,1.49646,1.68849,3.36201,2.23966,1.19101,.35188,1.45267-.15743,2.80103-.00097,2.80559,.32556,4.69002,2.88083,5.043,3.35949,1.36081,1.84526,.83282,2.62341,2.24236,4.48086,1.21555,1.6018,3.90913,.9216,4.92189,1.72162,3.30928,2.61409,4.73124,7.43497,4.75994,12.92962,.0201,3.8431-.48103,5.78482-1.59913,10.63564-.84901,3.6834-4.78175,8.44334-6.94987,10.5659-.58199,.56975-2.21351,2.167-3.36066,1.68178-1.08704-.45979-1.11995-2.52764-1.12139-2.80064-.0049-.93901,.24521-2.1009,2.23907-5.04263,2.09442-3.09006,2.92645-3.44271,2.79948-4.48262-.22445-1.83818-3.16424-3.52123-4.48263-2.79948h.00012Z"
fill="#2f2e41"
/>
<g>
<path
d="M334.49457,225.75979c-.64513,5.40264,1.61895,10.11513,5.05699,10.52567s6.7481-3.63632,7.39324-9.03898c.28242-2.36492,.00723-4.59754-.6797-6.39504l2.44642-22.92684-10.7834-.91891-1.26717,22.69891c-1.09088,1.58522-1.88401,3.69026-2.16639,6.05519h.00003Z"
fill="#a0616a"
/>
<path
d="M365.49095,73.49769s-5.58664,.07946-9.28568,7.30383c-1.96565,3.83897-12.48211,75.62767-12.48211,75.62767l-9.68742,58.80847,16.50214,.08313,12.859-55.69302,10.81723-32.30088-8.72315-53.82921Z"
fill="#e6e6e6"
/>
</g>
<path
d="M411.92961,217.13028c-1.58023,5.20651-.17535,10.24237,3.13786,11.24797s7.28015-2.39987,8.86035-7.60638c.69172-2.27906,.81133-4.5254,.44941-6.41533l6.4191-22.14543-10.45641-2.79098-5.21815,22.12729c-1.35133,1.36996-2.50044,3.30383-3.19216,5.58289v-.00003Z"
fill="#a0616a"
/>
<path
d="M423.41564,69.63219s8.10413-6.08248,14.86262,3.37246c6.75846,9.45495,9.48742,87.1388,9.48742,87.1388l-18.89796,47.96845-14.18755-4.72373,13.49008-58.7749-23.65861-44.57614,18.90403-30.40494h-.00003Z"
fill="#e6e6e6"
/>
<g>
<circle cx="218.47958" cy="311.43145" r="73" fill={fillColor} />
<g>
<circle cx="218.49274" cy="349.47878" r="6.70264" fill="#fff" />
<path
d="M218.4641,266.68145c-.6157,4.0912,.48747,4.94727,.49357,22.58508,.0061,17.63782,3.66579,41.28574-.47148,41.28717s-5.65047-48.80276-20.01681-53.12218c-16.89088-5.07846,21.98785-23.99409,19.99471-10.75007Z"
fill="#fff"
/>
</g>
</g>
<path
d="M120.50313,348.70219l-6.59532,13.93527c7.97328-5.71745,20.42715-10.64598,30.3376-13.28567-9.23403-4.46037-20.53313-11.65189-27.2835-18.77194l3.7934,14.72434c-44.47393-9.0585-76.41138-43.17661-76.4249-82.25924l-1.60648-.5527c.01412,40.82281,31.50971,76.96121,77.7792,86.20995Z"
fill="#3f3d56"
/>
</svg>
);
};
export default SvgError;

View File

@@ -2,292 +2,292 @@
import { useTheme } from "@mui/material";
const SvgLoading = ({ width, height, color = null }) => {
const theme = useTheme();
const fillColor = color || theme.palette.primary.main;
const theme = useTheme();
const fillColor = color || theme.palette.primary.main;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
data-name="Layer 1"
width={width}
height={height}
viewBox="0 0 693.97296 712.57302"
>
<path
id="a7e0d23c-0c47-41f1-93b9-87dfccd4c0f5-182"
data-name="Path 968"
d="M752.75753,262.60547h-3.9v-106.977a61.915,61.915,0,0,0-61.915-61.915h-226.65a61.915,61.915,0,0,0-61.916,61.914v586.884a61.915,61.915,0,0,0,61.915,61.915h226.648a61.915,61.915,0,0,0,61.915-61.915v-403.758h3.9Z"
transform="translate(-253.01352 -93.71349)"
fill="#3f3d56"
/>
<path
id="a1ad11fc-8226-4675-bbe0-e36020d9de96-183"
data-name="Path 969"
d="M736.15756,151.48149v595.175a46.959,46.959,0,0,1-46.942,46.952h-231.3a46.966,46.966,0,0,1-46.973-46.952v-595.175a46.965,46.965,0,0,1,46.971-46.951h28.058a22.329,22.329,0,0,0,20.656,30.74h131.868a22.329,22.329,0,0,0,20.656-30.74h30.055a46.959,46.959,0,0,1,46.951,46.942Z"
transform="translate(-253.01352 -93.71349)"
fill="#fff"
/>
<path
id="a71e44ec-7616-4081-86af-b6db32cd39f3-184"
data-name="Path 39"
d="M678.82353,494.30947h-205.537a3.81,3.81,0,0,1-3.806-3.806V439.51949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a3f57aef-fb20-4553-8f82-b751eb5ec42c-185"
data-name="Path 40"
d="M536.85153,454.07448a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00221-.11712-.0019h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a617e1da-1a45-4bf0-a146-8b20186fa5b6-186"
data-name="Path 41"
d="M536.85153,470.05846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11712-.00189h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="f83fafa3-5270-49ac-8952-eedc3d6c92ed-187"
data-name="Path 42"
d="M678.82353,579.28947h-205.537a3.81,3.81,0,0,1-3.806-3.806V524.49949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985A3.811,3.811,0,0,1,678.82353,579.28947Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="b1e095e5-1d51-47f4-b1e9-85a21efab4ec-188"
data-name="Path 43"
d="M536.85153,539.33047a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="e7ccabbb-2f45-40c9-adc9-a92013dc0f4d-189"
data-name="Path 44"
d="M536.85153,555.3185a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="ec532991-8ec8-4eba-a86f-87c70c278f41-190"
data-name="Path 39-2"
d="M678.82353,664.54748h-205.537a3.81,3.81,0,0,1-3.806-3.806V609.7575a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a788f10e-f95b-4590-bad9-be702445c232-191"
data-name="Path 40-2"
d="M536.85153,624.59148a2.66449,2.66449,0,1,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11712-.00189h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="f15a5014-9b42-4c0b-a546-80766b911601-192"
data-name="Path 41-2"
d="M536.85153,640.57846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.0022-.11712-.00189h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="b97f850c-7352-4ff9-8496-0f681ff3b244-193"
data-name="Path 970"
d="M945.17252,806.28651h-690.347c-1,0-1.812-.468-1.812-1.045s.812-1.04505,1.812-1.04505H945.17447c1,0,1.812.468,1.812,1.045S946.17252,806.28651,945.17252,806.28651Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<g id="ac055b4e-9afd-48c4-86db-12c8e2993e8d" data-name="Group 58">
<path
id="b77ebe88-e0c7-4a9a-a2fb-b51dce897c46-194"
data-name="Path 438"
d="M282.08554,765.52248a19.47406,19.47406,0,0,0,18.806-3.313c6.587-5.528,8.652-14.637,10.332-23.07l4.97-24.945-10.405,7.165c-7.483,5.152-15.134,10.47-20.316,17.933s-7.443,17.651-3.28,25.727"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a8a7bc76-ff28-4167-bc9c-ebff63445848-195"
data-name="Path 439"
d="M283.69254,797.45852c-1.31-9.542-2.657-19.206-1.738-28.85.816-8.565,3.429-16.93,8.749-23.789a39.57353,39.57353,0,0,1,10.153-9.2c1.015-.641,1.95.968.939,1.606a37.622,37.622,0,0,0-14.885,17.955c-3.24,8.241-3.76,17.224-3.2,25.978.338,5.294,1.053,10.553,1.774,15.806a.964.964,0,0,1-.65,1.144.936.936,0,0,1-1.144-.65Z"
transform="translate(-253.01352 -93.71349)"
fill="#f2f2f2"
/>
<path
id="abfc2b94-a38f-4778-bd11-bd0282c86570-196"
data-name="Path 442"
d="M293.11954,782.1495a14.336,14.336,0,0,0,12.491,6.447c6.323-.3,11.595-4.713,16.34-8.9l14.036-12.392-9.289-.444c-6.68-.32-13.533-.618-19.9,1.442s-12.231,7.018-13.394,13.6"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="ba99c695-899d-4604-b38e-601ed41861fa-197"
data-name="Path 443"
d="M279.99051,802.94448c6.3-11.156,13.618-23.555,26.685-27.518a29.77893,29.77893,0,0,1,11.224-1.159c1.192.1.894,1.94-.3,1.837a27.66479,27.66479,0,0,0-17.912,4.739c-5.051,3.438-8.983,8.217-12.311,13.286-2.039,3.1-3.865,6.341-5.691,9.573C281.10352,804.73452,279.4035,803.98946,279.99051,802.94448Z"
transform="translate(-253.01352 -93.71349)"
fill="#f2f2f2"
/>
</g>
<g id="bf60e786-3805-43a5-8cdd-bbea060079bf" data-name="Group 59">
<circle
id="a323e3dd-8f2c-40f7-a0c1-7a235f78e8b7"
data-name="Ellipse 5"
cx="245.91502"
cy="370.985"
r="15.986"
fill={fillColor}
/>
<path
id="b21d221e-9b86-4bff-9dca-a61a27263db1-198"
data-name="Path 40-3"
d="M491.27554,461.71247c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94306,5.94306,0,0,0-.328-2.708h-15.73Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
</g>
<g id="b51141dd-8175-4f5a-b697-41b89601b37f" data-name="Group 60">
<circle
id="e363222e-d569-47a6-8bf5-edbaac636a07"
data-name="Ellipse 5-2"
cx="245.91502"
cy="456.278"
r="15.986"
fill={fillColor}
/>
<path
id="bf4b9d9b-b2cd-48cd-bc0b-2e6b007ef33d-199"
data-name="Path 40-4"
d="M491.27554,547.00547c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94306,5.94306,0,0,0-.328-2.708h-15.73Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
</g>
<g id="b35aa588-fd9e-4429-8570-fee6b5da93cc" data-name="Group 61">
<circle
id="b896a996-d737-41ee-9642-d5eaf8a9fd6b"
data-name="Ellipse 5-3"
cx="245.91502"
cy="541.53599"
r="15.986"
fill={fillColor}
/>
<path
id="f0c90521-3626-484d-9767-39f7327e6a31-200"
data-name="Path 40-5"
d="M491.27554,632.26346c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.9431,5.9431,0,0,0-.328-2.708h-15.73Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
</g>
<path
d="M625.19989,350.38193a4.48656,4.48656,0,0,1-4.01245-2.4497,52.87438,52.87438,0,0,0-31.37232-26.41114,59.99908,59.99908,0,0,0-8.408-1.9038l-.57959-.08789L610.74725,225.983l.50586.01758c58.12769,15.79492,91.385,62.38134,100.19336,76.2832a4.49382,4.49382,0,0,1-1.79663,6.42334L627.21918,349.9044A4.50685,4.50685,0,0,1,625.19989,350.38193Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="e0f3bbc9-2b9f-408e-80ac-e1d5d48fdbc4-201"
data-name="Path 2881"
d="M804.63654,549.70647a9.27592,9.27592,0,0,1,12.711-6.383l22.283-24.293,4.164,16.616-21.8,20.521a9.326,9.326,0,0,1-17.359-6.462Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="b7278a0b-1b02-42c5-a26a-5568eba21726-202"
data-name="Path 2882"
d="M852.49454,792.04449h-13.613l-6.478-52.517h20.1Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="ae5e3f59-c07c-4936-a848-b4ed4a22f493-203"
data-name="Path 2883"
d="M855.96756,787.5985h-26.815a17.089,17.089,0,0,0-17.088,17.087v.556h43.9Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<path
id="e2dcac65-80ca-45a3-9c58-68329f82aa19-204"
data-name="Path 2884"
d="M930.68353,778.55646l-12.729,4.832-24.693-46.8,18.787-7.13Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="e33efd2e-5dad-4e18-8ce5-ea4b13e613d2-205"
data-name="Path 2885"
d="M932.35455,773.16747l-25.069,9.515h0a17.089,17.089,0,0,0-9.911,22.039l.2.519,41.045-15.578Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<path
id="aea1be6b-88fd-4404-a4b2-fdb70dea932e-206"
data-name="Path 2886"
d="M885.86453,617.36046l11.283,60.71405s30.625,85.428,28.476,87.577-31.7,9.671-30.088,4.836-35.461-77.369-35.461-77.369Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<path
id="a45d4c0e-5c31-49a4-b00c-14ea50dd8cbe-207"
data-name="Path 2887"
d="M840.10855,507.03047s-22.777,29.774-19.792,31.4,14.547,10.236,14.547,10.236l11.764-32.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e4e4e4"
/>
<path
id="ababf4ae-7dbc-4717-bb50-ecd0b5fac405-208"
data-name="Path 2888"
d="M833.74753,537.0825s-3.761,27.939-2.149,33.849.537,173.543-.537,176.229-4.3,11.82-2.686,16.118,23.64,15.044,26.864,11.283,26.866-140.768,26.866-140.768,33.312-82.742,25.79-90.8S833.74753,537.0825,833.74753,537.0825Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<circle
id="a4a0a325-f198-46ef-8204-e1264a7da486"
data-name="Ellipse 542"
cx="629.07161"
cy="237.48247"
r="26.32701"
fill="#feb8b8"
/>
<path
id="f1bcc5ff-8c37-42ba-ac71-fb7b653723a6-209"
data-name="Path 2890"
d="M854.57553,390.69649a18.66405,18.66405,0,0,1,6-11.04l4.8-14.675h28.209l7.861,12.335c8.5,3.661,14.8,9.467,15.039,16.311,1.3,4.545-4.3,148.828-5.91,154.2-.473,1.564-6.9,2.4-15.936,2.772-8.285.338-18.756.29-28.809.059-16.645-.387-32.162-1.279-34.773-1.757C825.15152,547.82848,853.99054,394.08647,854.57553,390.69649Z"
transform="translate(-253.01352 -93.71349)"
fill="#e4e4e4"
/>
<path
id="f2ae932d-f3ee-421e-b804-f39bdd3d1485-210"
data-name="Path 2891"
d="M879.51553,582.02647a9.276,9.276,0,0,0,1.826-14.106l15.569-29.056-17.059,1.558-12.168,27.352a9.326,9.326,0,0,0,11.833,14.251Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="a13bc27c-3d22-450d-9b6a-4857ac9e22b6-211"
data-name="Path 2893"
d="M882.10355,374.82347s-24.715,10.208-15.581,36,19.342,56.415,19.342,56.415-12.895,69.31-12.895,72-8.059,17.193-4.836,19.88,24.715,8.059,25.252,5.373a181.71945,181.71945,0,0,1,5.91-18.268c1.075-2.149,26.327-69.31,23.1-75.22-2.372-4.349-4.454-44.2-5.388-64.939a34.107,34.107,0,0,0-17.781-28.715C894.22256,374.68749,888.39056,373.25148,882.10355,374.82347Z"
transform="translate(-253.01352 -93.71349)"
fill="#e4e4e4"
/>
<path
id="a3aad1c3-1778-4515-92de-8de9e018032c-212"
data-name="Path 2800"
d="M892.21851,342.96248c-2-.922-4.317-1.113-6.479-1.686-7.734-2.052-12.916-9.689-11.261-16.6a7.47905,7.47905,0,0,0,.406-2.736c-.289-2.047-2.687-3.368-4.986-3.837s-4.746-.4-6.943-1.155a9.39,9.39,0,0,1-6.136-7.366,13.67394,13.67394,0,0,1,2.327-9.171l.831,2.088a7.77124,7.77124,0,0,0,2.714-3.545,5.5,5.5,0,0,1,4.26,2.992c1.333.687,1.525-2.133,3-2.549a2.945,2.945,0,0,1,1.838.4c2.967,1.209,6.414.175,9.6-.495a41.22185,41.22185,0,0,1,16.771-.017c3.663.763,7.29,2.093,9.912,4.455a20.35,20.35,0,0,1,4.636,6.96c2.812,6.182,4.669,12.871,3.741,19.473a26.05108,26.05108,0,0,1-7.436,14.6c-2.123,2.137-9.05,9.591-12.848,8.321C891.38751,351.49449,897.84155,345.5595,892.21851,342.96248Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<circle cx="321.97861" cy="266.45946" r="8" fill="#3f3d56" />
<path
d="M521.30463,350.26524a4.492,4.492,0,0,1-2.1001-.52442l-81.95288-43.23437a4.5,4.5,0,0,1-1.74121-6.32471,181.66635,181.66635,0,0,1,40.991-45.9751c28.30152-22.43066,60.4939-33.68408,95.678-33.49512a151.88378,151.88378,0,0,1,39.064,5.28858l.50464.13672-29.927,93.541-.42114-.06347a66.68158,66.68158,0,0,0-8.13867-.72168c-30.45068-.85938-43.64649,19.876-47.90772,28.82959a4.41453,4.41453,0,0,1-2.62011,2.31005A4.52734,4.52734,0,0,1,521.30463,350.26524Z"
transform="translate(-253.01352 -93.71349)"
fill={fillColor}
/>
<path
d="M611.122,226.483l-21.15967,94.56a60.38421,60.38421,0,0,0-8.48-1.92l29.62988-92.64Z"
transform="translate(-253.01352 -93.71349)"
fill="#3f3d56"
/>
</svg>
);
return (
<svg
xmlns="http://www.w3.org/2000/svg"
data-name="Layer 1"
width={width}
height={height}
viewBox="0 0 693.97296 712.57302"
>
<path
id="a7e0d23c-0c47-41f1-93b9-87dfccd4c0f5-182"
data-name="Path 968"
d="M752.75753,262.60547h-3.9v-106.977a61.915,61.915,0,0,0-61.915-61.915h-226.65a61.915,61.915,0,0,0-61.916,61.914v586.884a61.915,61.915,0,0,0,61.915,61.915h226.648a61.915,61.915,0,0,0,61.915-61.915v-403.758h3.9Z"
transform="translate(-253.01352 -93.71349)"
fill="#3f3d56"
/>
<path
id="a1ad11fc-8226-4675-bbe0-e36020d9de96-183"
data-name="Path 969"
d="M736.15756,151.48149v595.175a46.959,46.959,0,0,1-46.942,46.952h-231.3a46.966,46.966,0,0,1-46.973-46.952v-595.175a46.965,46.965,0,0,1,46.971-46.951h28.058a22.329,22.329,0,0,0,20.656,30.74h131.868a22.329,22.329,0,0,0,20.656-30.74h30.055a46.959,46.959,0,0,1,46.951,46.942Z"
transform="translate(-253.01352 -93.71349)"
fill="#fff"
/>
<path
id="a71e44ec-7616-4081-86af-b6db32cd39f3-184"
data-name="Path 39"
d="M678.82353,494.30947h-205.537a3.81,3.81,0,0,1-3.806-3.806V439.51949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a3f57aef-fb20-4553-8f82-b751eb5ec42c-185"
data-name="Path 40"
d="M536.85153,454.07448a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00221-.11712-.0019h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a617e1da-1a45-4bf0-a146-8b20186fa5b6-186"
data-name="Path 41"
d="M536.85153,470.05846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11712-.00189h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="f83fafa3-5270-49ac-8952-eedc3d6c92ed-187"
data-name="Path 42"
d="M678.82353,579.28947h-205.537a3.81,3.81,0,0,1-3.806-3.806V524.49949a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985A3.811,3.811,0,0,1,678.82353,579.28947Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="b1e095e5-1d51-47f4-b1e9-85a21efab4ec-188"
data-name="Path 43"
d="M536.85153,539.33047a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="e7ccabbb-2f45-40c9-adc9-a92013dc0f4d-189"
data-name="Path 44"
d="M536.85153,555.3185a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.087-5.328h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="ec532991-8ec8-4eba-a86f-87c70c278f41-190"
data-name="Path 39-2"
d="M678.82353,664.54748h-205.537a3.81,3.81,0,0,1-3.806-3.806V609.7575a3.811,3.811,0,0,1,3.806-3.806h205.537a3.811,3.811,0,0,1,3.806,3.806v50.985a3.811,3.811,0,0,1-3.806,3.806Zm-205.537-57.074a2.286,2.286,0,0,0-2.284,2.284v50.985a2.286,2.286,0,0,0,2.284,2.284h205.537a2.286,2.286,0,0,0,2.284-2.284v-50.985a2.286,2.286,0,0,0-2.284-2.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a788f10e-f95b-4590-bad9-be702445c232-191"
data-name="Path 40-2"
d="M536.85153,624.59148a2.66449,2.66449,0,1,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.00219-.11712-.00189h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="f15a5014-9b42-4c0b-a546-80766b911601-192"
data-name="Path 41-2"
d="M536.85153,640.57846a2.66449,2.66449,0,0,0,0,5.329h125.605a2.665,2.665,0,0,0,.2041-5.32611q-.0585-.0022-.11712-.00189h-125.692Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="b97f850c-7352-4ff9-8496-0f681ff3b244-193"
data-name="Path 970"
d="M945.17252,806.28651h-690.347c-1,0-1.812-.468-1.812-1.045s.812-1.04505,1.812-1.04505H945.17447c1,0,1.812.468,1.812,1.045S946.17252,806.28651,945.17252,806.28651Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<g id="ac055b4e-9afd-48c4-86db-12c8e2993e8d" data-name="Group 58">
<path
id="b77ebe88-e0c7-4a9a-a2fb-b51dce897c46-194"
data-name="Path 438"
d="M282.08554,765.52248a19.47406,19.47406,0,0,0,18.806-3.313c6.587-5.528,8.652-14.637,10.332-23.07l4.97-24.945-10.405,7.165c-7.483,5.152-15.134,10.47-20.316,17.933s-7.443,17.651-3.28,25.727"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="a8a7bc76-ff28-4167-bc9c-ebff63445848-195"
data-name="Path 439"
d="M283.69254,797.45852c-1.31-9.542-2.657-19.206-1.738-28.85.816-8.565,3.429-16.93,8.749-23.789a39.57353,39.57353,0,0,1,10.153-9.2c1.015-.641,1.95.968.939,1.606a37.622,37.622,0,0,0-14.885,17.955c-3.24,8.241-3.76,17.224-3.2,25.978.338,5.294,1.053,10.553,1.774,15.806a.964.964,0,0,1-.65,1.144.936.936,0,0,1-1.144-.65Z"
transform="translate(-253.01352 -93.71349)"
fill="#f2f2f2"
/>
<path
id="abfc2b94-a38f-4778-bd11-bd0282c86570-196"
data-name="Path 442"
d="M293.11954,782.1495a14.336,14.336,0,0,0,12.491,6.447c6.323-.3,11.595-4.713,16.34-8.9l14.036-12.392-9.289-.444c-6.68-.32-13.533-.618-19.9,1.442s-12.231,7.018-13.394,13.6"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="ba99c695-899d-4604-b38e-601ed41861fa-197"
data-name="Path 443"
d="M279.99051,802.94448c6.3-11.156,13.618-23.555,26.685-27.518a29.77893,29.77893,0,0,1,11.224-1.159c1.192.1.894,1.94-.3,1.837a27.66479,27.66479,0,0,0-17.912,4.739c-5.051,3.438-8.983,8.217-12.311,13.286-2.039,3.1-3.865,6.341-5.691,9.573C281.10352,804.73452,279.4035,803.98946,279.99051,802.94448Z"
transform="translate(-253.01352 -93.71349)"
fill="#f2f2f2"
/>
</g>
<g id="bf60e786-3805-43a5-8cdd-bbea060079bf" data-name="Group 59">
<circle
id="a323e3dd-8f2c-40f7-a0c1-7a235f78e8b7"
data-name="Ellipse 5"
cx="245.91502"
cy="370.985"
r="15.986"
fill={fillColor}
/>
<path
id="b21d221e-9b86-4bff-9dca-a61a27263db1-198"
data-name="Path 40-3"
d="M491.27554,461.71247c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94306,5.94306,0,0,0-.328-2.708h-15.73Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
</g>
<g id="b51141dd-8175-4f5a-b697-41b89601b37f" data-name="Group 60">
<circle
id="e363222e-d569-47a6-8bf5-edbaac636a07"
data-name="Ellipse 5-2"
cx="245.91502"
cy="456.278"
r="15.986"
fill={fillColor}
/>
<path
id="bf4b9d9b-b2cd-48cd-bc0b-2e6b007ef33d-199"
data-name="Path 40-4"
d="M491.27554,547.00547c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.94306,5.94306,0,0,0-.328-2.708h-15.73Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
</g>
<g id="b35aa588-fd9e-4429-8570-fee6b5da93cc" data-name="Group 61">
<circle
id="b896a996-d737-41ee-9642-d5eaf8a9fd6b"
data-name="Ellipse 5-3"
cx="245.91502"
cy="541.53599"
r="15.986"
fill={fillColor}
/>
<path
id="f0c90521-3626-484d-9767-39f7327e6a31-200"
data-name="Path 40-5"
d="M491.27554,632.26346c-.184,0-.333,1.193-.333,2.664s.149,2.665.333,2.665h15.719c.184.024.336-1.149.339-2.62a5.9431,5.9431,0,0,0-.328-2.708h-15.73Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
</g>
<path
d="M625.19989,350.38193a4.48656,4.48656,0,0,1-4.01245-2.4497,52.87438,52.87438,0,0,0-31.37232-26.41114,59.99908,59.99908,0,0,0-8.408-1.9038l-.57959-.08789L610.74725,225.983l.50586.01758c58.12769,15.79492,91.385,62.38134,100.19336,76.2832a4.49382,4.49382,0,0,1-1.79663,6.42334L627.21918,349.9044A4.50685,4.50685,0,0,1,625.19989,350.38193Z"
transform="translate(-253.01352 -93.71349)"
fill="#e6e6e6"
/>
<path
id="e0f3bbc9-2b9f-408e-80ac-e1d5d48fdbc4-201"
data-name="Path 2881"
d="M804.63654,549.70647a9.27592,9.27592,0,0,1,12.711-6.383l22.283-24.293,4.164,16.616-21.8,20.521a9.326,9.326,0,0,1-17.359-6.462Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="b7278a0b-1b02-42c5-a26a-5568eba21726-202"
data-name="Path 2882"
d="M852.49454,792.04449h-13.613l-6.478-52.517h20.1Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="ae5e3f59-c07c-4936-a848-b4ed4a22f493-203"
data-name="Path 2883"
d="M855.96756,787.5985h-26.815a17.089,17.089,0,0,0-17.088,17.087v.556h43.9Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<path
id="e2dcac65-80ca-45a3-9c58-68329f82aa19-204"
data-name="Path 2884"
d="M930.68353,778.55646l-12.729,4.832-24.693-46.8,18.787-7.13Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="e33efd2e-5dad-4e18-8ce5-ea4b13e613d2-205"
data-name="Path 2885"
d="M932.35455,773.16747l-25.069,9.515h0a17.089,17.089,0,0,0-9.911,22.039l.2.519,41.045-15.578Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<path
id="aea1be6b-88fd-4404-a4b2-fdb70dea932e-206"
data-name="Path 2886"
d="M885.86453,617.36046l11.283,60.71405s30.625,85.428,28.476,87.577-31.7,9.671-30.088,4.836-35.461-77.369-35.461-77.369Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<path
id="a45d4c0e-5c31-49a4-b00c-14ea50dd8cbe-207"
data-name="Path 2887"
d="M840.10855,507.03047s-22.777,29.774-19.792,31.4,14.547,10.236,14.547,10.236l11.764-32.284Z"
transform="translate(-253.01352 -93.71349)"
fill="#e4e4e4"
/>
<path
id="ababf4ae-7dbc-4717-bb50-ecd0b5fac405-208"
data-name="Path 2888"
d="M833.74753,537.0825s-3.761,27.939-2.149,33.849.537,173.543-.537,176.229-4.3,11.82-2.686,16.118,23.64,15.044,26.864,11.283,26.866-140.768,26.866-140.768,33.312-82.742,25.79-90.8S833.74753,537.0825,833.74753,537.0825Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<circle
id="a4a0a325-f198-46ef-8204-e1264a7da486"
data-name="Ellipse 542"
cx="629.07161"
cy="237.48247"
r="26.32701"
fill="#feb8b8"
/>
<path
id="f1bcc5ff-8c37-42ba-ac71-fb7b653723a6-209"
data-name="Path 2890"
d="M854.57553,390.69649a18.66405,18.66405,0,0,1,6-11.04l4.8-14.675h28.209l7.861,12.335c8.5,3.661,14.8,9.467,15.039,16.311,1.3,4.545-4.3,148.828-5.91,154.2-.473,1.564-6.9,2.4-15.936,2.772-8.285.338-18.756.29-28.809.059-16.645-.387-32.162-1.279-34.773-1.757C825.15152,547.82848,853.99054,394.08647,854.57553,390.69649Z"
transform="translate(-253.01352 -93.71349)"
fill="#e4e4e4"
/>
<path
id="f2ae932d-f3ee-421e-b804-f39bdd3d1485-210"
data-name="Path 2891"
d="M879.51553,582.02647a9.276,9.276,0,0,0,1.826-14.106l15.569-29.056-17.059,1.558-12.168,27.352a9.326,9.326,0,0,0,11.833,14.251Z"
transform="translate(-253.01352 -93.71349)"
fill="#feb8b8"
/>
<path
id="a13bc27c-3d22-450d-9b6a-4857ac9e22b6-211"
data-name="Path 2893"
d="M882.10355,374.82347s-24.715,10.208-15.581,36,19.342,56.415,19.342,56.415-12.895,69.31-12.895,72-8.059,17.193-4.836,19.88,24.715,8.059,25.252,5.373a181.71945,181.71945,0,0,1,5.91-18.268c1.075-2.149,26.327-69.31,23.1-75.22-2.372-4.349-4.454-44.2-5.388-64.939a34.107,34.107,0,0,0-17.781-28.715C894.22256,374.68749,888.39056,373.25148,882.10355,374.82347Z"
transform="translate(-253.01352 -93.71349)"
fill="#e4e4e4"
/>
<path
id="a3aad1c3-1778-4515-92de-8de9e018032c-212"
data-name="Path 2800"
d="M892.21851,342.96248c-2-.922-4.317-1.113-6.479-1.686-7.734-2.052-12.916-9.689-11.261-16.6a7.47905,7.47905,0,0,0,.406-2.736c-.289-2.047-2.687-3.368-4.986-3.837s-4.746-.4-6.943-1.155a9.39,9.39,0,0,1-6.136-7.366,13.67394,13.67394,0,0,1,2.327-9.171l.831,2.088a7.77124,7.77124,0,0,0,2.714-3.545,5.5,5.5,0,0,1,4.26,2.992c1.333.687,1.525-2.133,3-2.549a2.945,2.945,0,0,1,1.838.4c2.967,1.209,6.414.175,9.6-.495a41.22185,41.22185,0,0,1,16.771-.017c3.663.763,7.29,2.093,9.912,4.455a20.35,20.35,0,0,1,4.636,6.96c2.812,6.182,4.669,12.871,3.741,19.473a26.05108,26.05108,0,0,1-7.436,14.6c-2.123,2.137-9.05,9.591-12.848,8.321C891.38751,351.49449,897.84155,345.5595,892.21851,342.96248Z"
transform="translate(-253.01352 -93.71349)"
fill="#2f2e41"
/>
<circle cx="321.97861" cy="266.45946" r="8" fill="#3f3d56" />
<path
d="M521.30463,350.26524a4.492,4.492,0,0,1-2.1001-.52442l-81.95288-43.23437a4.5,4.5,0,0,1-1.74121-6.32471,181.66635,181.66635,0,0,1,40.991-45.9751c28.30152-22.43066,60.4939-33.68408,95.678-33.49512a151.88378,151.88378,0,0,1,39.064,5.28858l.50464.13672-29.927,93.541-.42114-.06347a66.68158,66.68158,0,0,0-8.13867-.72168c-30.45068-.85938-43.64649,19.876-47.90772,28.82959a4.41453,4.41453,0,0,1-2.62011,2.31005A4.52734,4.52734,0,0,1,521.30463,350.26524Z"
transform="translate(-253.01352 -93.71349)"
fill={fillColor}
/>
<path
d="M611.122,226.483l-21.15967,94.56a60.38421,60.38421,0,0,0-8.48-1.92l29.62988-92.64Z"
transform="translate(-253.01352 -93.71349)"
fill="#3f3d56"
/>
</svg>
);
};
export default SvgLoading;

View File

@@ -1,162 +1,162 @@
import { useTheme } from "@mui/material";
const SvgNotFound = ({ width, height, color = null }) => {
const theme = useTheme();
const fillColor = color || theme.palette.primary.main;
const theme = useTheme();
const fillColor = color || theme.palette.primary.main;
return (
<svg
xmlns="http://www.w3.org/2000/svg"
data-name="Layer 1"
width={width}
height={height}
viewBox="0 0 860.13137 571.14799"
>
<path
d="M605.66974,324.95306c-7.66934-12.68446-16.7572-26.22768-30.98954-30.36953-16.482-4.7965-33.4132,4.73193-47.77473,14.13453a1392.15692,1392.15692,0,0,0-123.89338,91.28311l.04331.49238q46.22556-3.1878,92.451-6.37554c22.26532-1.53546,45.29557-3.2827,64.97195-13.8156,7.46652-3.99683,14.74475-9.33579,23.20555-9.70782,10.51175-.46217,19.67733,6.87923,26.8802,14.54931,42.60731,45.371,54.937,114.75409,102.73817,154.61591A1516.99453,1516.99453,0,0,0,605.66974,324.95306Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M867.57068,709.78146c-4.71167-5.94958-6.6369-7.343-11.28457-13.34761q-56.7644-73.41638-106.70791-151.79237-33.92354-53.23-64.48275-108.50439-14.54864-26.2781-28.29961-52.96872-10.67044-20.6952-20.8646-41.63793c-1.94358-3.98782-3.8321-7.99393-5.71122-12.00922-4.42788-9.44232-8.77341-18.93047-13.43943-28.24449-5.31686-10.61572-11.789-21.74485-21.55259-28.877a29.40493,29.40493,0,0,0-15.31855-5.89458c-7.948-.51336-15.28184,2.76855-22.17568,6.35295-50.43859,26.301-97.65922,59.27589-140.3696,96.79771A730.77816,730.77816,0,0,0,303.32241,496.24719c-1.008,1.43927-3.39164.06417-2.37419-1.38422q6.00933-8.49818,12.25681-16.81288A734.817,734.817,0,0,1,500.80465,303.06436q18.24824-11.82581,37.18269-22.54245c6.36206-3.60275,12.75188-7.15967,19.25136-10.49653,6.37146-3.27274,13.13683-6.21547,20.41563-6.32547,24.7701-.385,37.59539,27.66695,46.40506,46.54248q4.15283,8.9106,8.40636,17.76626,16.0748,33.62106,33.38729,66.628,10.68453,20.379,21.83683,40.51955,34.7071,62.71816,73.77854,122.897c34.5059,53.1429,68.73651,100.08874,108.04585,149.78472C870.59617,709.21309,868.662,711.17491,867.57068,709.78146Z"
transform="translate(-169.93432 -164.42601)"
fill="#e4e4e4"
/>
<path
d="M414.91613,355.804c-1.43911-1.60428-2.86927-3.20856-4.31777-4.81284-11.42244-12.63259-23.6788-25.11847-39.3644-32.36067a57.11025,57.11025,0,0,0-23.92679-5.54622c-8.56213.02753-16.93178,2.27348-24.84306,5.41792-3.74034,1.49427-7.39831,3.1902-11.00078,4.99614-4.11634,2.07182-8.15927,4.28118-12.1834,6.50883q-11.33112,6.27044-22.36816,13.09089-21.9606,13.57221-42.54566,29.21623-10.67111,8.11311-20.90174,16.75788-9.51557,8.03054-18.64618,16.492c-1.30169,1.20091-3.24527-.74255-1.94358-1.94347,1.60428-1.49428,3.22691-2.97938,4.84955-4.44613q6.87547-6.21546,13.9712-12.19257,12.93921-10.91827,26.54851-20.99312,21.16293-15.67614,43.78288-29.22541,11.30361-6.76545,22.91829-12.96259c2.33794-1.24675,4.70318-2.466,7.09572-3.6211a113.11578,113.11578,0,0,1,16.86777-6.86632,60.0063,60.0063,0,0,1,25.476-2.50265,66.32706,66.32706,0,0,1,23.50512,8.1314c15.40091,8.60812,27.34573,21.919,38.97,34.90915C418.03337,355.17141,416.09875,357.12405,414.91613,355.804Z"
transform="translate(-169.93432 -164.42601)"
fill="#e4e4e4"
/>
<path
d="M730.47659,486.71092l36.90462-13.498,18.32327-6.70183c5.96758-2.18267,11.92082-4.66747,18.08988-6.23036a28.53871,28.53871,0,0,1,16.37356.20862,37.73753,37.73753,0,0,1,12.771,7.91666,103.63965,103.63965,0,0,1,10.47487,11.18643c3.98932,4.79426,7.91971,9.63877,11.86772,14.46706q24.44136,29.89094,48.56307,60.04134,24.12117,30.14991,47.91981,60.556,23.85681,30.48041,47.38548,61.21573,2.88229,3.76518,5.75966,7.53415c1.0598,1.38809,3.44949.01962,2.37472-1.38808Q983.582,650.9742,959.54931,620.184q-24.09177-30.86383-48.51647-61.46586-24.42421-30.60141-49.17853-60.93743-6.16706-7.55761-12.35445-15.09858c-3.47953-4.24073-6.91983-8.52718-10.73628-12.47427-7.00539-7.24516-15.75772-13.64794-26.23437-13.82166-6.15972-.10214-12.121,1.85248-17.844,3.92287-6.16968,2.232-12.32455,4.50571-18.48633,6.75941l-37.16269,13.59243-9.29067,3.3981c-1.64875.603-.93651,3.2619.73111,2.652Z"
transform="translate(-169.93432 -164.42601)"
fill="#e4e4e4"
/>
<path
d="M366.37741,334.52609c-18.75411-9.63866-42.77137-7.75087-60.00508,4.29119a855.84708,855.84708,0,0,1,97.37056,22.72581C390.4603,353.75916,380.07013,341.5635,366.37741,334.52609Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M306.18775,338.7841l-3.61042,2.93462c1.22123-1.02713,2.4908-1.99013,3.795-2.90144C306.31073,338.80665,306.24935,338.79473,306.18775,338.7841Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M831.54929,486.84576c-3.6328-4.42207-7.56046-9.05222-12.99421-10.84836l-5.07308.20008A575.436,575.436,0,0,0,966.74929,651.418Q899.14929,569.13192,831.54929,486.84576Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M516.08388,450.36652A37.4811,37.4811,0,0,0,531.015,471.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M749.08388,653.36652A37.4811,37.4811,0,0,0,764.015,674.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M284.08388,639.36652A37.4811,37.4811,0,0,0,299.015,660.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<circle cx="649.24878" cy="51" r="51" fill={fillColor} />
<path
d="M911.21851,176.29639c-24.7168-3.34094-52.93512,10.01868-59.34131,34.12353a21.59653,21.59653,0,0,0-41.09351,2.10871l2.82972,2.02667a372.27461,372.27461,0,0,0,160.65881-.72638C957.07935,195.76,935.93537,179.63727,911.21851,176.29639Z"
transform="translate(-169.93432 -164.42601)"
fill="#f0f0f0"
/>
<path
d="M805.21851,244.29639c-24.7168-3.34094-52.93512,10.01868-59.34131,34.12353a21.59653,21.59653,0,0,0-41.09351,2.10871l2.82972,2.02667a372.27461,372.27461,0,0,0,160.65881-.72638C851.07935,263.76,829.93537,247.63727,805.21851,244.29639Z"
transform="translate(-169.93432 -164.42601)"
fill="#f0f0f0"
/>
<path
d="M1020.94552,257.15423a.98189.98189,0,0,1-.30176-.04688C756.237,173.48919,523.19942,184.42376,374.26388,208.32122c-20.26856,3.251-40.59131,7.00586-60.40381,11.16113-5.05811,1.05957-10.30567,2.19532-15.59668,3.37793-6.31885,1.40723-12.55371,2.85645-18.53223,4.30567q-3.873.917-7.59472,1.84863c-3.75831.92773-7.57178,1.89453-11.65967,2.957-4.56787,1.17774-9.209,2.41309-13.79737,3.67188a.44239.44239,0,0,1-.05127.01465l.00049.001c-5.18261,1.415-10.33789,2.8711-15.32324,4.3252-2.69824.77929-5.30371,1.54785-7.79932,2.30664-.2788.07715-.52587.15136-.77636.22754l-.53614.16308c-.31054.09473-.61718.1875-.92382.27539l-.01953.00586.00048.001-.81152.252c-.96777.293-1.91211.5791-2.84082.86426-24.54492,7.56641-38.03809,12.94922-38.17139,13.00195a1,1,0,1,1-.74414-1.85644c.13428-.05274,13.69336-5.46289,38.32764-13.05762.93213-.28613,1.87891-.57226,2.84961-.86621l.7539-.23438c.02588-.00976.05176-.01757.07813-.02539.30518-.08691.60986-.17968.91943-.27343l.53711-.16309c.26758-.08105.53125-.16113.80127-.23535,2.47852-.75391,5.09278-1.52441,7.79785-2.30664,4.98731-1.45508,10.14746-2.91113,15.334-4.32813.01611-.00586.03271-.00976.04883-.01464v-.001c4.60449-1.2627,9.26269-2.50293,13.84521-3.68457,4.09424-1.06348,7.915-2.03223,11.67969-2.96192q3.73755-.93017,7.60937-1.85253c5.98536-1.45118,12.23291-2.90235,18.563-4.3125,5.29932-1.1836,10.55567-2.32227,15.62207-3.38282,19.84326-4.16211,40.19776-7.92285,60.49707-11.17871C523.09591,182.415,756.46749,171.46282,1021.2463,255.2011a.99974.99974,0,0,1-.30078,1.95313Z"
transform="translate(-169.93432 -164.42601)"
fill="#ccc"
/>
<path
d="M432.92309,584.266a6.72948,6.72948,0,0,0-1.7-2.67,6.42983,6.42983,0,0,0-.92-.71c-2.61-1.74-6.51-2.13-8.99,0a5.81012,5.81012,0,0,0-.69.71q-1.11,1.365-2.28,2.67c-1.28,1.46-2.59,2.87-3.96,4.24-.39.38-.78.77-1.18,1.15-.23.23-.46.45-.69.67-.88.84-1.78,1.65-2.69,2.45-.48.43-.96.85-1.45,1.26-.73.61-1.46,1.22-2.2,1.81-.07.05-.14.1-.21.16-.02.01-.03.03-.05.04-.01,0-.02,0-.03.02a.17861.17861,0,0,0-.07.05c-.22.15-.37.25-.48.34.04-.01995.08-.05.12-.07-.18.14-.37.28-.55.42-1.75,1.29-3.54,2.53-5.37,3.69a99.21022,99.21022,0,0,1-14.22,7.55c-.33.13-.67.27-1.01.4a85.96993,85.96993,0,0,1-40.85,6.02q-2.13008-.165-4.26-.45c-1.64-.24-3.27-.53-4.89-.86a97.93186,97.93186,0,0,1-18.02-5.44,118.65185,118.65185,0,0,1-20.66-12.12c-1-.71-2.01-1.42-3.02-2.11,1.15-2.82,2.28-5.64,3.38-8.48.55-1.37,1.08-2.74,1.6-4.12,4.09-10.63,7.93-21.36,11.61-32.13q5.58-16.365,10.53-32.92.51-1.68.99-3.36,2.595-8.745,4.98-17.53c.15-.56994.31-1.12994.45-1.7q.68994-2.52,1.35-5.04c1-3.79-1.26-8.32-5.24-9.23a7.63441,7.63441,0,0,0-9.22,5.24c-.43,1.62-.86,3.23-1.3,4.85q-3.165,11.74494-6.66,23.41-.51,1.68-1.02,3.36-7.71,25.41-16.93,50.31-1.11,3.015-2.25,6.01c-.37.98-.74,1.96-1.12,2.94-.73,1.93-1.48,3.86-2.23,5.79-.43006,1.13-.87006,2.26-1.31,3.38-.29.71-.57,1.42-.85,2.12a41.80941,41.80941,0,0,0-8.81-2.12l-.48-.06a27.397,27.397,0,0,0-7.01.06,23.91419,23.91419,0,0,0-17.24,10.66c-4.77,7.51-4.71,18.25,1.98,24.63,6.89,6.57,17.32,6.52,25.43,2.41a28.35124,28.35124,0,0,0,10.52-9.86,50.56939,50.56939,0,0,0,2.74-4.65c.21.14.42.28.63.43.8.56,1.6,1.13,2.39,1.69a111.73777,111.73777,0,0,0,14.51,8.91,108.35887,108.35887,0,0,0,34.62,10.47c.27.03.53.07.8.1,1.33.17,2.67.3,4.01.41a103.78229,103.78229,0,0,0,55.58-11.36q2.175-1.125,4.31-2.36,3.315-1.92,6.48-4.08c1.15-.78,2.27-1.57,3.38-2.4a101.04244,101.04244,0,0,0,13.51-11.95q2.35491-2.475,4.51-5.11005a8.0612,8.0612,0,0,0,2.2-5.3A7.5644,7.5644,0,0,0,432.92309,584.266Zm-165.59,23.82c.21-.15.42-.31.62-.47C267.89312,607.766,267.60308,607.936,267.33312,608.086Zm3.21-3.23c-.23.26-.44.52-.67.78a23.36609,23.36609,0,0,1-2.25,2.2c-.11.1-.23.2-.35.29a.00976.00976,0,0,0-.01.01,3.80417,3.80417,0,0,0-.42005.22q-.645.39-1.31994.72a17.00459,17.00459,0,0,1-2.71.75,16.79925,16.79925,0,0,1-2.13.02h-.02a14.82252,14.82252,0,0,1-1.45-.4c-.24-.12-.47-.25994-.7-.4-.09-.08-.17005-.16-.22-.21a2.44015,2.44015,0,0,1-.26995-.29.0098.0098,0,0,0-.01-.01c-.11005-.2-.23005-.4-.34-.6a.031.031,0,0,1-.01-.02c-.08-.25-.15-.51-.21-.77a12.51066,12.51066,0,0,1,.01-1.37,13.4675,13.4675,0,0,1,.54-1.88,11.06776,11.06776,0,0,1,.69-1.26c.02-.04.12-.2.23-.38.01-.01.01-.01.01-.02.15-.17.3-.35.46-.51.27-.3.56-.56.85-.83a18.02212,18.02212,0,0,1,1.75-1.01,19.48061,19.48061,0,0,1,2.93-.79,24.98945,24.98945,0,0,1,4.41.04,30.30134,30.30134,0,0,1,4.1,1.01,36.94452,36.94452,0,0,1-2.77,4.54C270.6231,604.746,270.58312,604.806,270.54308,604.856Zm-11.12-3.29a2.18029,2.18029,0,0,1-.31.38995A1.40868,1.40868,0,0,1,259.42309,601.566Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M402.86309,482.136q-.13494,4.71-.27,9.42-.285,10.455-.59,20.92-.315,11.775-.66,23.54-.165,6.07507-.34,12.15-.465,16.365-.92,32.72c-.03,1.13-.07,2.25-.1,3.38q-.225,8.11506-.45,16.23-.255,8.805-.5,17.61-.18,6.59994-.37,13.21-1.34994,47.895-2.7,95.79a7.64844,7.64844,0,0,1-7.5,7.5,7.56114,7.56114,0,0,1-7.5-7.5q.75-26.94,1.52-53.88.675-24.36,1.37-48.72.225-8.025.45-16.06.345-12.09.68-24.18c.03-1.13.07-2.25.1-3.38.02-.99.05-1.97.08-2.96q.66-23.475,1.32-46.96.27-9.24.52-18.49.3-10.545.6-21.08c.09-3.09.17005-6.17.26-9.26a7.64844,7.64844,0,0,1,7.5-7.5A7.56116,7.56116,0,0,1,402.86309,482.136Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M814.29118,484.2172a893.23753,893.23753,0,0,1-28.16112,87.94127c-3.007,7.94641-6.08319,15.877-9.3715,23.71185l.75606-1.7916a54.58274,54.58274,0,0,1-5.58953,10.61184q-.22935.32119-.46685.63642,1.16559-1.49043.4428-.589c-.25405.30065-.5049.60219-.7676.89546a23.66436,23.66436,0,0,1-2.2489,2.20318q-.30139.25767-.61188.5043l.93783-.729c-.10884.25668-.87275.59747-1.11067.74287a18.25362,18.25362,0,0,1-2.40479,1.21853l1.7916-.75606a19.0859,19.0859,0,0,1-4.23122,1.16069l1.9938-.26791a17.02055,17.02055,0,0,1-4.29785.046l1.99379.2679a14.0022,14.0022,0,0,1-3.40493-.917l1.79159.75606a12.01175,12.01175,0,0,1-1.67882-.89614c-.27135-.17688-1.10526-.80852-.01487.02461,1.13336.86595.14562.07434-.08763-.15584-.19427-.19171-.36962-.4-.55974-.595-.88208-.90454.99637,1.55662.39689.49858a18.18179,18.18179,0,0,1-.87827-1.63672l.75606,1.7916a11.92493,11.92493,0,0,1-.728-2.65143l.26791,1.9938a13.65147,13.65147,0,0,1-.00316-3.40491l-.2679,1.9938a15.96371,15.96371,0,0,1,.99486-3.68011l-.75606,1.7916a16.72914,16.72914,0,0,1,1.17794-2.29848,6.72934,6.72934,0,0,1,.72851-1.0714c.04915.01594-1.26865,1.51278-.56937.757.1829-.19767.354-.40592.539-.602.29617-.31382.61354-.60082.92561-.89791,1.04458-.99442-1.46188.966-.25652.17907a19.0489,19.0489,0,0,1,2.74925-1.49923l-1.79159.75606a20.31136,20.31136,0,0,1,4.99523-1.33984l-1.9938.2679a25.62828,25.62828,0,0,1,6.46062.07647l-1.9938-.2679a33.21056,33.21056,0,0,1,7.89178,2.2199l-1.7916-.75606c5.38965,2.31383,10.16308,5.74926,14.928,9.118a111.94962,111.94962,0,0,0,14.50615,8.9065,108.38849,108.38849,0,0,0,34.62226,10.47371,103.93268,103.93268,0,0,0,92.58557-36.75192,8.07773,8.07773,0,0,0,2.1967-5.3033,7.63232,7.63232,0,0,0-2.1967-5.3033c-2.75154-2.52586-7.94926-3.239-10.6066,0a95.63575,95.63575,0,0,1-8.10664,8.72692q-2.01736,1.914-4.14232,3.70983-1.21364,1.02588-2.46086,2.01121c-.3934.31081-1.61863,1.13807.26309-.19744-.43135.30614-.845.64036-1.27058.95478a99.26881,99.26881,0,0,1-20.33215,11.56478l1.79159-.75606a96.8364,96.8364,0,0,1-24.17119,6.62249l1.99379-.2679a97.64308,97.64308,0,0,1-25.75362-.03807l1.99379.2679a99.79982,99.79982,0,0,1-24.857-6.77027l1.7916.75607a116.02515,116.02515,0,0,1-21.7364-12.59112,86.87725,86.87725,0,0,0-11.113-6.99417,42.8238,42.8238,0,0,0-14.43784-4.38851c-9.43884-1.11076-19.0571,2.56562-24.24624,10.72035-4.77557,7.50482-4.71394,18.24362,1.97369,24.62519,6.8877,6.5725,17.31846,6.51693,25.43556,2.40567,7.81741-3.95946,12.51288-12.18539,15.815-19.94186,7.43109-17.45514,14.01023-35.31364,20.1399-53.263q9.09651-26.63712,16.49855-53.81332.91661-3.36581,1.80683-6.73869c1.001-3.78869-1.26094-8.32-5.23829-9.22589a7.63317,7.63317,0,0,0-9.22589,5.23829Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M889.12382,482.13557l-2.69954,95.79311-2.68548,95.29418-1.5185,53.88362a7.56465,7.56465,0,0,0,7.5,7.5,7.64923,7.64923,0,0,0,7.5-7.5l2.69955-95.79311,2.68548-95.29418,1.51849-53.88362a7.56465,7.56465,0,0,0-7.5-7.5,7.64923,7.64923,0,0,0-7.5,7.5Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M629.52566,700.36106h2.32885V594.31942h54.32863v-2.32291H631.85451V547.25214H673.8102q-.92256-1.17339-1.89893-2.31694H631.85451V515.38231c-.7703-.32846-1.54659-.64493-2.32885-.9435V544.9352h-45.652V507.07c-.78227.03583-1.55258.08959-2.3289.15527v37.71h-36.4201V516.68409c-.78227.34636-1.55258.71061-2.31694,1.0928V544.9352h-30.6158v2.31694h30.6158v44.74437h-30.6158v2.32291h30.6158V700.36106h2.31694V594.31942a36.41283,36.41283,0,0,1,36.4201,36.42007v69.62157h2.3289V594.31942h45.652Zm-84.401-108.36455V547.25214h36.4201v44.74437Zm38.749,0V547.25214h.91362a44.74135,44.74135,0,0,1,44.73842,44.74437Z"
transform="translate(-169.93432 -164.42601)"
opacity="0.2"
/>
<path
d="M615.30309,668.566a63.05854,63.05854,0,0,1-20.05,33.7c-.74.64-1.48,1.26-2.25,1.87q-2.805.25506-5.57.52c-1.53.14-3.04.29-4.54.43l-.27.03-.19-1.64-.76-6.64a37.623,37.623,0,0,1-3.3-32.44c2.64-7.12,7.42-13.41,12.12-19.65,6.49-8.62,12.8-17.14,13.03-27.65a60.54415,60.54415,0,0,1,7.9,13.33,16.432,16.432,0,0,0-5.12,3.76995c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39,1,.11,2,.21,3,.32a63.99025,63.99025,0,0,1,2.45,12.18A61.18851,61.18851,0,0,1,615.30309,668.566Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M648.50311,642.356c-5.9,4.29-9.35,10.46-12.03,17.26a16.62776,16.62776,0,0,0-7.17,4.58c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39-2.68,8.04-5.14,16.36-9.88,23.15a36.98942,36.98942,0,0,1-12.03,10.91,38.49166,38.49166,0,0,1-4.02,1.99q-7.62.585-14.95,1.25-2.805.25506-5.57.52c-1.53.14-3.04.29-4.54.43q-.015-.825,0-1.65a63.30382,63.30382,0,0,1,15.25-39.86c.45-.52.91-1.03,1.38-1.54a61.7925,61.7925,0,0,1,16.81-12.7A62.65425,62.65425,0,0,1,648.50311,642.356Z"
transform="translate(-169.93432 -164.42601)"
fill={fillColor}
/>
<path
d="M589.16308,699.526l-1.15,3.4-.58,1.73c-1.53.14-3.04.29-4.54.43l-.27.03c-1.66.17-3.31.34-4.96.51-.43-.5-.86-1.01-1.28-1.53a62.03045,62.03045,0,0,1,8.07-87.11c-1.32,6.91.22,13.53,2.75,20.1-.27.11-.53.22-.78.34a16.432,16.432,0,0,0-5.12,3.76995c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39,1,.11,2,.21,3,.32q.705.075,1.41.15c.07.15.13.29.2.44,2.85,6.18,5.92,12.39,7.65,18.83a43.66591,43.66591,0,0,1,1.02,4.91A37.604,37.604,0,0,1,589.16308,699.526Z"
transform="translate(-169.93432 -164.42601)"
fill={fillColor}
/>
<path
d="M689.82123,554.48655c-8.60876-16.79219-21.94605-30.92088-37.63219-41.30357a114.2374,114.2374,0,0,0-52.5626-18.37992q-3.69043-.33535-7.399-.39281c-2.92141-.04371-46.866,12.63176-61.58712,22.98214a114.29462,114.29462,0,0,0-35.333,39.527,102.49972,102.49972,0,0,0-12.12557,51.6334,113.56387,113.56387,0,0,0,14.70268,51.47577,110.47507,110.47507,0,0,0,36.44425,38.74592C549.66655,708.561,565.07375,734.51,583.1831,735.426c18.24576.923,39.05418-23.55495,55.6951-30.98707a104.42533,104.42533,0,0,0,41.72554-34.005,110.24964,110.24964,0,0,0,19.599-48.94777c2.57368-18.08313,1.37415-36.73271-4.80123-54.01627a111.85969,111.85969,0,0,0-5.58024-12.9833c-1.77961-3.50519-6.996-4.7959-10.26142-2.69063a7.67979,7.67979,0,0,0-2.69064,10.26142q1.56766,3.08773,2.91536,6.27758l-.75606-1.7916a101.15088,101.15088,0,0,1,6.87641,25.53816l-.26791-1.99379a109.2286,109.2286,0,0,1-.06613,28.68252l.26791-1.9938a109.73379,109.73379,0,0,1-7.55462,27.67419l.75606-1.79159a104.212,104.212,0,0,1-6.67151,13.09835q-1.92308,3.18563-4.08062,6.22159c-.63172.8881-1.28287,1.761-1.939,2.63114-.85625,1.13555,1.16691-1.48321.28228-.36941-.15068.18972-.30049.3801-.45182.5693q-.68121.85165-1.3818,1.68765a93.61337,93.61337,0,0,1-10.17647,10.38359q-1.36615,1.19232-2.77786,2.33115c-.46871.37832-.932.77269-1.42079,1.12472.01861-.0134,1.57956-1.19945.65556-.511-.2905.21644-.57851.43619-.86961.65184q-2.90994,2.1558-5.97433,4.092a103.48509,103.48509,0,0,1-14.75565,7.7131l1.7916-.75606a109.21493,109.21493,0,0,1-27.59663,7.55154l1.9938-.26791a108.15361,108.15361,0,0,1-28.58907.0506l1.99379.2679a99.835,99.835,0,0,1-25.09531-6.78448l1.79159.75607a93.64314,93.64314,0,0,1-13.41605-6.99094q-3.17437-2-6.18358-4.24743c-.2862-.21359-.56992-.43038-.855-.64549-.9155-.69088.65765.50965.67021.51787a19.16864,19.16864,0,0,1-1.535-1.22469q-1.45353-1.18358-2.86136-2.4218a101.98931,101.98931,0,0,1-10.49319-10.70945q-1.21308-1.43379-2.37407-2.91054c-.33524-.4263-.9465-1.29026.40424.5289-.17775-.23939-.36206-.47414-.54159-.71223q-.64657-.85751-1.27568-1.72793-2.203-3.048-4.18787-6.24586a109.29037,109.29037,0,0,1-7.8054-15.10831l.75606,1.7916a106.58753,106.58753,0,0,1-7.34039-26.837l.26791,1.9938a97.86589,97.86589,0,0,1-.04843-25.63587l-.2679,1.9938A94.673,94.673,0,0,1,505.27587,570.55l-.75606,1.7916a101.55725,101.55725,0,0,1,7.19519-13.85624q2.0655-3.32328,4.37767-6.4847.52528-.71832,1.06244-1.42786c.324-.4279,1.215-1.49333-.30537.38842.14906-.18449.29252-.37428.43942-.56041q1.26882-1.60756,2.59959-3.1649A107.40164,107.40164,0,0,1,530.772,536.21508q1.47408-1.29171,2.99464-2.52906.6909-.56218,1.39108-1.11284c.18664-.14673.37574-.29073.56152-.43858-1.99743,1.58953-.555.43261-.10157.09288q3.13393-2.34833,6.43534-4.46134a103.64393,103.64393,0,0,1,15.38655-8.10791l-1.7916.75606c7.76008-3.25839,42.14086-10.9492,48.394-10.10973l-1.99379-.26791A106.22471,106.22471,0,0,1,628.768,517.419l-1.7916-.75606a110.31334,110.31334,0,0,1,12.6002,6.32922q3.04344,1.78405,5.96742,3.76252,1.38351.93658,2.73809,1.915.677.48917,1.34626.98885c.24789.185.49386.37253.74135.558,1.03924.779-1.43148-1.1281-.34209-.26655a110.84261,110.84261,0,0,1,10.36783,9.2532q2.401,2.445,4.63686,5.04515,1.14659,1.33419,2.24643,2.70757c.36436.45495,1.60506,2.101.08448.08457.37165.49285.74744.98239,1.11436,1.47884a97.97718,97.97718,0,0,1,8.39161,13.53807c1.79317,3.49775,6.98675,4.80186,10.26142,2.69064A7.67666,7.67666,0,0,0,689.82123,554.48655Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M602.43116,676.88167a3.77983,3.77983,0,0,1-2.73939-6.55137c.09531-.37882.16368-.65085.259-1.02968q-.05115-.12366-.1029-.24717c-3.47987-8.29769-25.685,14.83336-26.645,22.63179a30.029,30.029,0,0,0,.52714,10.32752A120.39223,120.39223,0,0,1,562.77838,652.01a116.20247,116.20247,0,0,1,.72078-12.96332q.59712-5.293,1.65679-10.51055a121.78667,121.78667,0,0,1,24.1515-51.61646c6.87378.38364,12.898-.66348,13.47967-13.98532.10346-2.36972,1.86113-4.42156,2.24841-6.756-.65621.08607-1.32321.13985-1.97941.18285-.20444.0107-.41958.02149-.624.03228l-.07709.00346a3.745,3.745,0,0,1-3.07566-6.10115q.425-.52305.85054-1.04557c.43036-.53793.87143-1.06507,1.30171-1.60292a1.865,1.865,0,0,0,.13986-.16144c.49494-.61322.98971-1.21564,1.48465-1.82885a10.82911,10.82911,0,0,0-3.55014-3.43169c-4.95941-2.90463-11.80146-.89293-15.38389,3.59313-3.59313,4.486-4.27083,10.77947-3.023,16.3843a43.39764,43.39764,0,0,0,6.003,13.3828c-.269.34429-.54872.67779-.81765,1.02209a122.57366,122.57366,0,0,0-12.79359,20.2681c1.0163-7.93863-11.41159-36.60795-16.21776-42.68052-5.773-7.29409-17.61108-4.11077-18.62815,5.13562q-.01476.13428-.02884.26849,1.07082.60411,2.0964,1.28237a5.12707,5.12707,0,0,1-2.06713,9.33031l-.10452.01613c-9.55573,13.64367,21.07745,49.1547,28.74518,41.18139a125.11045,125.11045,0,0,0-6.73449,31.69282,118.66429,118.66429,0,0,0,.08607,19.15986l-.03231-.22593C558.90163,648.154,529.674,627.51374,521.139,629.233c-4.91675.99041-9.75952.76525-9.01293,5.72484q.01788.11874.03635.2375a34.4418,34.4418,0,0,1,3.862,1.86105q1.07082.60423,2.09639,1.28237a5.12712,5.12712,0,0,1-2.06712,9.33039l-.10464.01606c-.07528.01079-.13987.02157-.21507.03237-4.34967,14.96631,27.90735,39.12,47.5177,31.43461h.01081a125.07484,125.07484,0,0,0,8.402,24.52806H601.679c.10765-.3335.20443-.67779.3013-1.01129a34.102,34.102,0,0,1-8.30521-.49477c2.22693-2.73257,4.45377-5.48664,6.6807-8.21913a1.86122,1.86122,0,0,0,.13986-.16135c1.12956-1.39849,2.26992-2.78627,3.39948-4.18476l.00061-.00173a49.95232,49.95232,0,0,0-1.46367-12.72495Zm-34.37066-67.613.0158-.02133-.0158.04282Zm-6.64832,59.93237-.25822-.58084c.01079-.41957.01079-.83914,0-1.26942,0-.11845-.0215-.23672-.0215-.35508.09678.74228.18285,1.48464.29042,2.22692Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<circle cx="95.24878" cy="439" r="11" fill="#3f3d56" />
<circle cx="227.24878" cy="559" r="11" fill="#3f3d56" />
<circle cx="728.24878" cy="559" r="11" fill="#3f3d56" />
<circle cx="755.24878" cy="419" r="11" fill="#3f3d56" />
<circle cx="723.24878" cy="317" r="11" fill="#3f3d56" />
<path
d="M434.1831,583.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,434.1831,583.426Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<circle cx="484.24878" cy="349" r="11" fill="#3f3d56" />
<path
d="M545.1831,513.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,545.1831,513.426Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M403.1831,481.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,403.1831,481.426Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<circle cx="599.24878" cy="443" r="11" fill="#3f3d56" />
<circle cx="426.24878" cy="338" r="16" fill="#3f3d56" />
<path
d="M1028.875,735.26666l-857.75.30733a1.19068,1.19068,0,1,1,0-2.38136l857.75-.30734a1.19069,1.19069,0,0,1,0,2.38137Z"
transform="translate(-169.93432 -164.42601)"
fill="#cacaca"
/>
</svg>
);
return (
<svg
xmlns="http://www.w3.org/2000/svg"
data-name="Layer 1"
width={width}
height={height}
viewBox="0 0 860.13137 571.14799"
>
<path
d="M605.66974,324.95306c-7.66934-12.68446-16.7572-26.22768-30.98954-30.36953-16.482-4.7965-33.4132,4.73193-47.77473,14.13453a1392.15692,1392.15692,0,0,0-123.89338,91.28311l.04331.49238q46.22556-3.1878,92.451-6.37554c22.26532-1.53546,45.29557-3.2827,64.97195-13.8156,7.46652-3.99683,14.74475-9.33579,23.20555-9.70782,10.51175-.46217,19.67733,6.87923,26.8802,14.54931,42.60731,45.371,54.937,114.75409,102.73817,154.61591A1516.99453,1516.99453,0,0,0,605.66974,324.95306Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M867.57068,709.78146c-4.71167-5.94958-6.6369-7.343-11.28457-13.34761q-56.7644-73.41638-106.70791-151.79237-33.92354-53.23-64.48275-108.50439-14.54864-26.2781-28.29961-52.96872-10.67044-20.6952-20.8646-41.63793c-1.94358-3.98782-3.8321-7.99393-5.71122-12.00922-4.42788-9.44232-8.77341-18.93047-13.43943-28.24449-5.31686-10.61572-11.789-21.74485-21.55259-28.877a29.40493,29.40493,0,0,0-15.31855-5.89458c-7.948-.51336-15.28184,2.76855-22.17568,6.35295-50.43859,26.301-97.65922,59.27589-140.3696,96.79771A730.77816,730.77816,0,0,0,303.32241,496.24719c-1.008,1.43927-3.39164.06417-2.37419-1.38422q6.00933-8.49818,12.25681-16.81288A734.817,734.817,0,0,1,500.80465,303.06436q18.24824-11.82581,37.18269-22.54245c6.36206-3.60275,12.75188-7.15967,19.25136-10.49653,6.37146-3.27274,13.13683-6.21547,20.41563-6.32547,24.7701-.385,37.59539,27.66695,46.40506,46.54248q4.15283,8.9106,8.40636,17.76626,16.0748,33.62106,33.38729,66.628,10.68453,20.379,21.83683,40.51955,34.7071,62.71816,73.77854,122.897c34.5059,53.1429,68.73651,100.08874,108.04585,149.78472C870.59617,709.21309,868.662,711.17491,867.57068,709.78146Z"
transform="translate(-169.93432 -164.42601)"
fill="#e4e4e4"
/>
<path
d="M414.91613,355.804c-1.43911-1.60428-2.86927-3.20856-4.31777-4.81284-11.42244-12.63259-23.6788-25.11847-39.3644-32.36067a57.11025,57.11025,0,0,0-23.92679-5.54622c-8.56213.02753-16.93178,2.27348-24.84306,5.41792-3.74034,1.49427-7.39831,3.1902-11.00078,4.99614-4.11634,2.07182-8.15927,4.28118-12.1834,6.50883q-11.33112,6.27044-22.36816,13.09089-21.9606,13.57221-42.54566,29.21623-10.67111,8.11311-20.90174,16.75788-9.51557,8.03054-18.64618,16.492c-1.30169,1.20091-3.24527-.74255-1.94358-1.94347,1.60428-1.49428,3.22691-2.97938,4.84955-4.44613q6.87547-6.21546,13.9712-12.19257,12.93921-10.91827,26.54851-20.99312,21.16293-15.67614,43.78288-29.22541,11.30361-6.76545,22.91829-12.96259c2.33794-1.24675,4.70318-2.466,7.09572-3.6211a113.11578,113.11578,0,0,1,16.86777-6.86632,60.0063,60.0063,0,0,1,25.476-2.50265,66.32706,66.32706,0,0,1,23.50512,8.1314c15.40091,8.60812,27.34573,21.919,38.97,34.90915C418.03337,355.17141,416.09875,357.12405,414.91613,355.804Z"
transform="translate(-169.93432 -164.42601)"
fill="#e4e4e4"
/>
<path
d="M730.47659,486.71092l36.90462-13.498,18.32327-6.70183c5.96758-2.18267,11.92082-4.66747,18.08988-6.23036a28.53871,28.53871,0,0,1,16.37356.20862,37.73753,37.73753,0,0,1,12.771,7.91666,103.63965,103.63965,0,0,1,10.47487,11.18643c3.98932,4.79426,7.91971,9.63877,11.86772,14.46706q24.44136,29.89094,48.56307,60.04134,24.12117,30.14991,47.91981,60.556,23.85681,30.48041,47.38548,61.21573,2.88229,3.76518,5.75966,7.53415c1.0598,1.38809,3.44949.01962,2.37472-1.38808Q983.582,650.9742,959.54931,620.184q-24.09177-30.86383-48.51647-61.46586-24.42421-30.60141-49.17853-60.93743-6.16706-7.55761-12.35445-15.09858c-3.47953-4.24073-6.91983-8.52718-10.73628-12.47427-7.00539-7.24516-15.75772-13.64794-26.23437-13.82166-6.15972-.10214-12.121,1.85248-17.844,3.92287-6.16968,2.232-12.32455,4.50571-18.48633,6.75941l-37.16269,13.59243-9.29067,3.3981c-1.64875.603-.93651,3.2619.73111,2.652Z"
transform="translate(-169.93432 -164.42601)"
fill="#e4e4e4"
/>
<path
d="M366.37741,334.52609c-18.75411-9.63866-42.77137-7.75087-60.00508,4.29119a855.84708,855.84708,0,0,1,97.37056,22.72581C390.4603,353.75916,380.07013,341.5635,366.37741,334.52609Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M306.18775,338.7841l-3.61042,2.93462c1.22123-1.02713,2.4908-1.99013,3.795-2.90144C306.31073,338.80665,306.24935,338.79473,306.18775,338.7841Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M831.54929,486.84576c-3.6328-4.42207-7.56046-9.05222-12.99421-10.84836l-5.07308.20008A575.436,575.436,0,0,0,966.74929,651.418Q899.14929,569.13192,831.54929,486.84576Z"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M516.08388,450.36652A37.4811,37.4811,0,0,0,531.015,471.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M749.08388,653.36652A37.4811,37.4811,0,0,0,764.015,674.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<path
d="M284.08388,639.36652A37.4811,37.4811,0,0,0,299.015,660.32518c2.82017,1.92011,6.15681,3.76209,7.12158,7.03463a8.37858,8.37858,0,0,1-.87362,6.1499,24.88351,24.88351,0,0,1-3.86126,5.04137l-.13667.512c-6.99843-4.14731-13.65641-9.3934-17.52227-16.55115s-4.40553-16.53895.34116-23.14544"
transform="translate(-169.93432 -164.42601)"
fill="#f2f2f2"
/>
<circle cx="649.24878" cy="51" r="51" fill={fillColor} />
<path
d="M911.21851,176.29639c-24.7168-3.34094-52.93512,10.01868-59.34131,34.12353a21.59653,21.59653,0,0,0-41.09351,2.10871l2.82972,2.02667a372.27461,372.27461,0,0,0,160.65881-.72638C957.07935,195.76,935.93537,179.63727,911.21851,176.29639Z"
transform="translate(-169.93432 -164.42601)"
fill="#f0f0f0"
/>
<path
d="M805.21851,244.29639c-24.7168-3.34094-52.93512,10.01868-59.34131,34.12353a21.59653,21.59653,0,0,0-41.09351,2.10871l2.82972,2.02667a372.27461,372.27461,0,0,0,160.65881-.72638C851.07935,263.76,829.93537,247.63727,805.21851,244.29639Z"
transform="translate(-169.93432 -164.42601)"
fill="#f0f0f0"
/>
<path
d="M1020.94552,257.15423a.98189.98189,0,0,1-.30176-.04688C756.237,173.48919,523.19942,184.42376,374.26388,208.32122c-20.26856,3.251-40.59131,7.00586-60.40381,11.16113-5.05811,1.05957-10.30567,2.19532-15.59668,3.37793-6.31885,1.40723-12.55371,2.85645-18.53223,4.30567q-3.873.917-7.59472,1.84863c-3.75831.92773-7.57178,1.89453-11.65967,2.957-4.56787,1.17774-9.209,2.41309-13.79737,3.67188a.44239.44239,0,0,1-.05127.01465l.00049.001c-5.18261,1.415-10.33789,2.8711-15.32324,4.3252-2.69824.77929-5.30371,1.54785-7.79932,2.30664-.2788.07715-.52587.15136-.77636.22754l-.53614.16308c-.31054.09473-.61718.1875-.92382.27539l-.01953.00586.00048.001-.81152.252c-.96777.293-1.91211.5791-2.84082.86426-24.54492,7.56641-38.03809,12.94922-38.17139,13.00195a1,1,0,1,1-.74414-1.85644c.13428-.05274,13.69336-5.46289,38.32764-13.05762.93213-.28613,1.87891-.57226,2.84961-.86621l.7539-.23438c.02588-.00976.05176-.01757.07813-.02539.30518-.08691.60986-.17968.91943-.27343l.53711-.16309c.26758-.08105.53125-.16113.80127-.23535,2.47852-.75391,5.09278-1.52441,7.79785-2.30664,4.98731-1.45508,10.14746-2.91113,15.334-4.32813.01611-.00586.03271-.00976.04883-.01464v-.001c4.60449-1.2627,9.26269-2.50293,13.84521-3.68457,4.09424-1.06348,7.915-2.03223,11.67969-2.96192q3.73755-.93017,7.60937-1.85253c5.98536-1.45118,12.23291-2.90235,18.563-4.3125,5.29932-1.1836,10.55567-2.32227,15.62207-3.38282,19.84326-4.16211,40.19776-7.92285,60.49707-11.17871C523.09591,182.415,756.46749,171.46282,1021.2463,255.2011a.99974.99974,0,0,1-.30078,1.95313Z"
transform="translate(-169.93432 -164.42601)"
fill="#ccc"
/>
<path
d="M432.92309,584.266a6.72948,6.72948,0,0,0-1.7-2.67,6.42983,6.42983,0,0,0-.92-.71c-2.61-1.74-6.51-2.13-8.99,0a5.81012,5.81012,0,0,0-.69.71q-1.11,1.365-2.28,2.67c-1.28,1.46-2.59,2.87-3.96,4.24-.39.38-.78.77-1.18,1.15-.23.23-.46.45-.69.67-.88.84-1.78,1.65-2.69,2.45-.48.43-.96.85-1.45,1.26-.73.61-1.46,1.22-2.2,1.81-.07.05-.14.1-.21.16-.02.01-.03.03-.05.04-.01,0-.02,0-.03.02a.17861.17861,0,0,0-.07.05c-.22.15-.37.25-.48.34.04-.01995.08-.05.12-.07-.18.14-.37.28-.55.42-1.75,1.29-3.54,2.53-5.37,3.69a99.21022,99.21022,0,0,1-14.22,7.55c-.33.13-.67.27-1.01.4a85.96993,85.96993,0,0,1-40.85,6.02q-2.13008-.165-4.26-.45c-1.64-.24-3.27-.53-4.89-.86a97.93186,97.93186,0,0,1-18.02-5.44,118.65185,118.65185,0,0,1-20.66-12.12c-1-.71-2.01-1.42-3.02-2.11,1.15-2.82,2.28-5.64,3.38-8.48.55-1.37,1.08-2.74,1.6-4.12,4.09-10.63,7.93-21.36,11.61-32.13q5.58-16.365,10.53-32.92.51-1.68.99-3.36,2.595-8.745,4.98-17.53c.15-.56994.31-1.12994.45-1.7q.68994-2.52,1.35-5.04c1-3.79-1.26-8.32-5.24-9.23a7.63441,7.63441,0,0,0-9.22,5.24c-.43,1.62-.86,3.23-1.3,4.85q-3.165,11.74494-6.66,23.41-.51,1.68-1.02,3.36-7.71,25.41-16.93,50.31-1.11,3.015-2.25,6.01c-.37.98-.74,1.96-1.12,2.94-.73,1.93-1.48,3.86-2.23,5.79-.43006,1.13-.87006,2.26-1.31,3.38-.29.71-.57,1.42-.85,2.12a41.80941,41.80941,0,0,0-8.81-2.12l-.48-.06a27.397,27.397,0,0,0-7.01.06,23.91419,23.91419,0,0,0-17.24,10.66c-4.77,7.51-4.71,18.25,1.98,24.63,6.89,6.57,17.32,6.52,25.43,2.41a28.35124,28.35124,0,0,0,10.52-9.86,50.56939,50.56939,0,0,0,2.74-4.65c.21.14.42.28.63.43.8.56,1.6,1.13,2.39,1.69a111.73777,111.73777,0,0,0,14.51,8.91,108.35887,108.35887,0,0,0,34.62,10.47c.27.03.53.07.8.1,1.33.17,2.67.3,4.01.41a103.78229,103.78229,0,0,0,55.58-11.36q2.175-1.125,4.31-2.36,3.315-1.92,6.48-4.08c1.15-.78,2.27-1.57,3.38-2.4a101.04244,101.04244,0,0,0,13.51-11.95q2.35491-2.475,4.51-5.11005a8.0612,8.0612,0,0,0,2.2-5.3A7.5644,7.5644,0,0,0,432.92309,584.266Zm-165.59,23.82c.21-.15.42-.31.62-.47C267.89312,607.766,267.60308,607.936,267.33312,608.086Zm3.21-3.23c-.23.26-.44.52-.67.78a23.36609,23.36609,0,0,1-2.25,2.2c-.11.1-.23.2-.35.29a.00976.00976,0,0,0-.01.01,3.80417,3.80417,0,0,0-.42005.22q-.645.39-1.31994.72a17.00459,17.00459,0,0,1-2.71.75,16.79925,16.79925,0,0,1-2.13.02h-.02a14.82252,14.82252,0,0,1-1.45-.4c-.24-.12-.47-.25994-.7-.4-.09-.08-.17005-.16-.22-.21a2.44015,2.44015,0,0,1-.26995-.29.0098.0098,0,0,0-.01-.01c-.11005-.2-.23005-.4-.34-.6a.031.031,0,0,1-.01-.02c-.08-.25-.15-.51-.21-.77a12.51066,12.51066,0,0,1,.01-1.37,13.4675,13.4675,0,0,1,.54-1.88,11.06776,11.06776,0,0,1,.69-1.26c.02-.04.12-.2.23-.38.01-.01.01-.01.01-.02.15-.17.3-.35.46-.51.27-.3.56-.56.85-.83a18.02212,18.02212,0,0,1,1.75-1.01,19.48061,19.48061,0,0,1,2.93-.79,24.98945,24.98945,0,0,1,4.41.04,30.30134,30.30134,0,0,1,4.1,1.01,36.94452,36.94452,0,0,1-2.77,4.54C270.6231,604.746,270.58312,604.806,270.54308,604.856Zm-11.12-3.29a2.18029,2.18029,0,0,1-.31.38995A1.40868,1.40868,0,0,1,259.42309,601.566Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M402.86309,482.136q-.13494,4.71-.27,9.42-.285,10.455-.59,20.92-.315,11.775-.66,23.54-.165,6.07507-.34,12.15-.465,16.365-.92,32.72c-.03,1.13-.07,2.25-.1,3.38q-.225,8.11506-.45,16.23-.255,8.805-.5,17.61-.18,6.59994-.37,13.21-1.34994,47.895-2.7,95.79a7.64844,7.64844,0,0,1-7.5,7.5,7.56114,7.56114,0,0,1-7.5-7.5q.75-26.94,1.52-53.88.675-24.36,1.37-48.72.225-8.025.45-16.06.345-12.09.68-24.18c.03-1.13.07-2.25.1-3.38.02-.99.05-1.97.08-2.96q.66-23.475,1.32-46.96.27-9.24.52-18.49.3-10.545.6-21.08c.09-3.09.17005-6.17.26-9.26a7.64844,7.64844,0,0,1,7.5-7.5A7.56116,7.56116,0,0,1,402.86309,482.136Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M814.29118,484.2172a893.23753,893.23753,0,0,1-28.16112,87.94127c-3.007,7.94641-6.08319,15.877-9.3715,23.71185l.75606-1.7916a54.58274,54.58274,0,0,1-5.58953,10.61184q-.22935.32119-.46685.63642,1.16559-1.49043.4428-.589c-.25405.30065-.5049.60219-.7676.89546a23.66436,23.66436,0,0,1-2.2489,2.20318q-.30139.25767-.61188.5043l.93783-.729c-.10884.25668-.87275.59747-1.11067.74287a18.25362,18.25362,0,0,1-2.40479,1.21853l1.7916-.75606a19.0859,19.0859,0,0,1-4.23122,1.16069l1.9938-.26791a17.02055,17.02055,0,0,1-4.29785.046l1.99379.2679a14.0022,14.0022,0,0,1-3.40493-.917l1.79159.75606a12.01175,12.01175,0,0,1-1.67882-.89614c-.27135-.17688-1.10526-.80852-.01487.02461,1.13336.86595.14562.07434-.08763-.15584-.19427-.19171-.36962-.4-.55974-.595-.88208-.90454.99637,1.55662.39689.49858a18.18179,18.18179,0,0,1-.87827-1.63672l.75606,1.7916a11.92493,11.92493,0,0,1-.728-2.65143l.26791,1.9938a13.65147,13.65147,0,0,1-.00316-3.40491l-.2679,1.9938a15.96371,15.96371,0,0,1,.99486-3.68011l-.75606,1.7916a16.72914,16.72914,0,0,1,1.17794-2.29848,6.72934,6.72934,0,0,1,.72851-1.0714c.04915.01594-1.26865,1.51278-.56937.757.1829-.19767.354-.40592.539-.602.29617-.31382.61354-.60082.92561-.89791,1.04458-.99442-1.46188.966-.25652.17907a19.0489,19.0489,0,0,1,2.74925-1.49923l-1.79159.75606a20.31136,20.31136,0,0,1,4.99523-1.33984l-1.9938.2679a25.62828,25.62828,0,0,1,6.46062.07647l-1.9938-.2679a33.21056,33.21056,0,0,1,7.89178,2.2199l-1.7916-.75606c5.38965,2.31383,10.16308,5.74926,14.928,9.118a111.94962,111.94962,0,0,0,14.50615,8.9065,108.38849,108.38849,0,0,0,34.62226,10.47371,103.93268,103.93268,0,0,0,92.58557-36.75192,8.07773,8.07773,0,0,0,2.1967-5.3033,7.63232,7.63232,0,0,0-2.1967-5.3033c-2.75154-2.52586-7.94926-3.239-10.6066,0a95.63575,95.63575,0,0,1-8.10664,8.72692q-2.01736,1.914-4.14232,3.70983-1.21364,1.02588-2.46086,2.01121c-.3934.31081-1.61863,1.13807.26309-.19744-.43135.30614-.845.64036-1.27058.95478a99.26881,99.26881,0,0,1-20.33215,11.56478l1.79159-.75606a96.8364,96.8364,0,0,1-24.17119,6.62249l1.99379-.2679a97.64308,97.64308,0,0,1-25.75362-.03807l1.99379.2679a99.79982,99.79982,0,0,1-24.857-6.77027l1.7916.75607a116.02515,116.02515,0,0,1-21.7364-12.59112,86.87725,86.87725,0,0,0-11.113-6.99417,42.8238,42.8238,0,0,0-14.43784-4.38851c-9.43884-1.11076-19.0571,2.56562-24.24624,10.72035-4.77557,7.50482-4.71394,18.24362,1.97369,24.62519,6.8877,6.5725,17.31846,6.51693,25.43556,2.40567,7.81741-3.95946,12.51288-12.18539,15.815-19.94186,7.43109-17.45514,14.01023-35.31364,20.1399-53.263q9.09651-26.63712,16.49855-53.81332.91661-3.36581,1.80683-6.73869c1.001-3.78869-1.26094-8.32-5.23829-9.22589a7.63317,7.63317,0,0,0-9.22589,5.23829Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M889.12382,482.13557l-2.69954,95.79311-2.68548,95.29418-1.5185,53.88362a7.56465,7.56465,0,0,0,7.5,7.5,7.64923,7.64923,0,0,0,7.5-7.5l2.69955-95.79311,2.68548-95.29418,1.51849-53.88362a7.56465,7.56465,0,0,0-7.5-7.5,7.64923,7.64923,0,0,0-7.5,7.5Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M629.52566,700.36106h2.32885V594.31942h54.32863v-2.32291H631.85451V547.25214H673.8102q-.92256-1.17339-1.89893-2.31694H631.85451V515.38231c-.7703-.32846-1.54659-.64493-2.32885-.9435V544.9352h-45.652V507.07c-.78227.03583-1.55258.08959-2.3289.15527v37.71h-36.4201V516.68409c-.78227.34636-1.55258.71061-2.31694,1.0928V544.9352h-30.6158v2.31694h30.6158v44.74437h-30.6158v2.32291h30.6158V700.36106h2.31694V594.31942a36.41283,36.41283,0,0,1,36.4201,36.42007v69.62157h2.3289V594.31942h45.652Zm-84.401-108.36455V547.25214h36.4201v44.74437Zm38.749,0V547.25214h.91362a44.74135,44.74135,0,0,1,44.73842,44.74437Z"
transform="translate(-169.93432 -164.42601)"
opacity="0.2"
/>
<path
d="M615.30309,668.566a63.05854,63.05854,0,0,1-20.05,33.7c-.74.64-1.48,1.26-2.25,1.87q-2.805.25506-5.57.52c-1.53.14-3.04.29-4.54.43l-.27.03-.19-1.64-.76-6.64a37.623,37.623,0,0,1-3.3-32.44c2.64-7.12,7.42-13.41,12.12-19.65,6.49-8.62,12.8-17.14,13.03-27.65a60.54415,60.54415,0,0,1,7.9,13.33,16.432,16.432,0,0,0-5.12,3.76995c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39,1,.11,2,.21,3,.32a63.99025,63.99025,0,0,1,2.45,12.18A61.18851,61.18851,0,0,1,615.30309,668.566Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M648.50311,642.356c-5.9,4.29-9.35,10.46-12.03,17.26a16.62776,16.62776,0,0,0-7.17,4.58c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39-2.68,8.04-5.14,16.36-9.88,23.15a36.98942,36.98942,0,0,1-12.03,10.91,38.49166,38.49166,0,0,1-4.02,1.99q-7.62.585-14.95,1.25-2.805.25506-5.57.52c-1.53.14-3.04.29-4.54.43q-.015-.825,0-1.65a63.30382,63.30382,0,0,1,15.25-39.86c.45-.52.91-1.03,1.38-1.54a61.7925,61.7925,0,0,1,16.81-12.7A62.65425,62.65425,0,0,1,648.50311,642.356Z"
transform="translate(-169.93432 -164.42601)"
fill={fillColor}
/>
<path
d="M589.16308,699.526l-1.15,3.4-.58,1.73c-1.53.14-3.04.29-4.54.43l-.27.03c-1.66.17-3.31.34-4.96.51-.43-.5-.86-1.01-1.28-1.53a62.03045,62.03045,0,0,1,8.07-87.11c-1.32,6.91.22,13.53,2.75,20.1-.27.11-.53.22-.78.34a16.432,16.432,0,0,0-5.12,3.76995c-.41.45-.82,1.08-.54,1.62006.24.46.84.57,1.36.62994,1.25.13,2.51.26,3.76.39,1,.11,2,.21,3,.32q.705.075,1.41.15c.07.15.13.29.2.44,2.85,6.18,5.92,12.39,7.65,18.83a43.66591,43.66591,0,0,1,1.02,4.91A37.604,37.604,0,0,1,589.16308,699.526Z"
transform="translate(-169.93432 -164.42601)"
fill={fillColor}
/>
<path
d="M689.82123,554.48655c-8.60876-16.79219-21.94605-30.92088-37.63219-41.30357a114.2374,114.2374,0,0,0-52.5626-18.37992q-3.69043-.33535-7.399-.39281c-2.92141-.04371-46.866,12.63176-61.58712,22.98214a114.29462,114.29462,0,0,0-35.333,39.527,102.49972,102.49972,0,0,0-12.12557,51.6334,113.56387,113.56387,0,0,0,14.70268,51.47577,110.47507,110.47507,0,0,0,36.44425,38.74592C549.66655,708.561,565.07375,734.51,583.1831,735.426c18.24576.923,39.05418-23.55495,55.6951-30.98707a104.42533,104.42533,0,0,0,41.72554-34.005,110.24964,110.24964,0,0,0,19.599-48.94777c2.57368-18.08313,1.37415-36.73271-4.80123-54.01627a111.85969,111.85969,0,0,0-5.58024-12.9833c-1.77961-3.50519-6.996-4.7959-10.26142-2.69063a7.67979,7.67979,0,0,0-2.69064,10.26142q1.56766,3.08773,2.91536,6.27758l-.75606-1.7916a101.15088,101.15088,0,0,1,6.87641,25.53816l-.26791-1.99379a109.2286,109.2286,0,0,1-.06613,28.68252l.26791-1.9938a109.73379,109.73379,0,0,1-7.55462,27.67419l.75606-1.79159a104.212,104.212,0,0,1-6.67151,13.09835q-1.92308,3.18563-4.08062,6.22159c-.63172.8881-1.28287,1.761-1.939,2.63114-.85625,1.13555,1.16691-1.48321.28228-.36941-.15068.18972-.30049.3801-.45182.5693q-.68121.85165-1.3818,1.68765a93.61337,93.61337,0,0,1-10.17647,10.38359q-1.36615,1.19232-2.77786,2.33115c-.46871.37832-.932.77269-1.42079,1.12472.01861-.0134,1.57956-1.19945.65556-.511-.2905.21644-.57851.43619-.86961.65184q-2.90994,2.1558-5.97433,4.092a103.48509,103.48509,0,0,1-14.75565,7.7131l1.7916-.75606a109.21493,109.21493,0,0,1-27.59663,7.55154l1.9938-.26791a108.15361,108.15361,0,0,1-28.58907.0506l1.99379.2679a99.835,99.835,0,0,1-25.09531-6.78448l1.79159.75607a93.64314,93.64314,0,0,1-13.41605-6.99094q-3.17437-2-6.18358-4.24743c-.2862-.21359-.56992-.43038-.855-.64549-.9155-.69088.65765.50965.67021.51787a19.16864,19.16864,0,0,1-1.535-1.22469q-1.45353-1.18358-2.86136-2.4218a101.98931,101.98931,0,0,1-10.49319-10.70945q-1.21308-1.43379-2.37407-2.91054c-.33524-.4263-.9465-1.29026.40424.5289-.17775-.23939-.36206-.47414-.54159-.71223q-.64657-.85751-1.27568-1.72793-2.203-3.048-4.18787-6.24586a109.29037,109.29037,0,0,1-7.8054-15.10831l.75606,1.7916a106.58753,106.58753,0,0,1-7.34039-26.837l.26791,1.9938a97.86589,97.86589,0,0,1-.04843-25.63587l-.2679,1.9938A94.673,94.673,0,0,1,505.27587,570.55l-.75606,1.7916a101.55725,101.55725,0,0,1,7.19519-13.85624q2.0655-3.32328,4.37767-6.4847.52528-.71832,1.06244-1.42786c.324-.4279,1.215-1.49333-.30537.38842.14906-.18449.29252-.37428.43942-.56041q1.26882-1.60756,2.59959-3.1649A107.40164,107.40164,0,0,1,530.772,536.21508q1.47408-1.29171,2.99464-2.52906.6909-.56218,1.39108-1.11284c.18664-.14673.37574-.29073.56152-.43858-1.99743,1.58953-.555.43261-.10157.09288q3.13393-2.34833,6.43534-4.46134a103.64393,103.64393,0,0,1,15.38655-8.10791l-1.7916.75606c7.76008-3.25839,42.14086-10.9492,48.394-10.10973l-1.99379-.26791A106.22471,106.22471,0,0,1,628.768,517.419l-1.7916-.75606a110.31334,110.31334,0,0,1,12.6002,6.32922q3.04344,1.78405,5.96742,3.76252,1.38351.93658,2.73809,1.915.677.48917,1.34626.98885c.24789.185.49386.37253.74135.558,1.03924.779-1.43148-1.1281-.34209-.26655a110.84261,110.84261,0,0,1,10.36783,9.2532q2.401,2.445,4.63686,5.04515,1.14659,1.33419,2.24643,2.70757c.36436.45495,1.60506,2.101.08448.08457.37165.49285.74744.98239,1.11436,1.47884a97.97718,97.97718,0,0,1,8.39161,13.53807c1.79317,3.49775,6.98675,4.80186,10.26142,2.69064A7.67666,7.67666,0,0,0,689.82123,554.48655Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M602.43116,676.88167a3.77983,3.77983,0,0,1-2.73939-6.55137c.09531-.37882.16368-.65085.259-1.02968q-.05115-.12366-.1029-.24717c-3.47987-8.29769-25.685,14.83336-26.645,22.63179a30.029,30.029,0,0,0,.52714,10.32752A120.39223,120.39223,0,0,1,562.77838,652.01a116.20247,116.20247,0,0,1,.72078-12.96332q.59712-5.293,1.65679-10.51055a121.78667,121.78667,0,0,1,24.1515-51.61646c6.87378.38364,12.898-.66348,13.47967-13.98532.10346-2.36972,1.86113-4.42156,2.24841-6.756-.65621.08607-1.32321.13985-1.97941.18285-.20444.0107-.41958.02149-.624.03228l-.07709.00346a3.745,3.745,0,0,1-3.07566-6.10115q.425-.52305.85054-1.04557c.43036-.53793.87143-1.06507,1.30171-1.60292a1.865,1.865,0,0,0,.13986-.16144c.49494-.61322.98971-1.21564,1.48465-1.82885a10.82911,10.82911,0,0,0-3.55014-3.43169c-4.95941-2.90463-11.80146-.89293-15.38389,3.59313-3.59313,4.486-4.27083,10.77947-3.023,16.3843a43.39764,43.39764,0,0,0,6.003,13.3828c-.269.34429-.54872.67779-.81765,1.02209a122.57366,122.57366,0,0,0-12.79359,20.2681c1.0163-7.93863-11.41159-36.60795-16.21776-42.68052-5.773-7.29409-17.61108-4.11077-18.62815,5.13562q-.01476.13428-.02884.26849,1.07082.60411,2.0964,1.28237a5.12707,5.12707,0,0,1-2.06713,9.33031l-.10452.01613c-9.55573,13.64367,21.07745,49.1547,28.74518,41.18139a125.11045,125.11045,0,0,0-6.73449,31.69282,118.66429,118.66429,0,0,0,.08607,19.15986l-.03231-.22593C558.90163,648.154,529.674,627.51374,521.139,629.233c-4.91675.99041-9.75952.76525-9.01293,5.72484q.01788.11874.03635.2375a34.4418,34.4418,0,0,1,3.862,1.86105q1.07082.60423,2.09639,1.28237a5.12712,5.12712,0,0,1-2.06712,9.33039l-.10464.01606c-.07528.01079-.13987.02157-.21507.03237-4.34967,14.96631,27.90735,39.12,47.5177,31.43461h.01081a125.07484,125.07484,0,0,0,8.402,24.52806H601.679c.10765-.3335.20443-.67779.3013-1.01129a34.102,34.102,0,0,1-8.30521-.49477c2.22693-2.73257,4.45377-5.48664,6.6807-8.21913a1.86122,1.86122,0,0,0,.13986-.16135c1.12956-1.39849,2.26992-2.78627,3.39948-4.18476l.00061-.00173a49.95232,49.95232,0,0,0-1.46367-12.72495Zm-34.37066-67.613.0158-.02133-.0158.04282Zm-6.64832,59.93237-.25822-.58084c.01079-.41957.01079-.83914,0-1.26942,0-.11845-.0215-.23672-.0215-.35508.09678.74228.18285,1.48464.29042,2.22692Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<circle cx="95.24878" cy="439" r="11" fill="#3f3d56" />
<circle cx="227.24878" cy="559" r="11" fill="#3f3d56" />
<circle cx="728.24878" cy="559" r="11" fill="#3f3d56" />
<circle cx="755.24878" cy="419" r="11" fill="#3f3d56" />
<circle cx="723.24878" cy="317" r="11" fill="#3f3d56" />
<path
d="M434.1831,583.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,434.1831,583.426Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<circle cx="484.24878" cy="349" r="11" fill="#3f3d56" />
<path
d="M545.1831,513.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,545.1831,513.426Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<path
d="M403.1831,481.426a10.949,10.949,0,1,1-.21-2.16A10.9921,10.9921,0,0,1,403.1831,481.426Z"
transform="translate(-169.93432 -164.42601)"
fill="#3f3d56"
/>
<circle cx="599.24878" cy="443" r="11" fill="#3f3d56" />
<circle cx="426.24878" cy="338" r="16" fill="#3f3d56" />
<path
d="M1028.875,735.26666l-857.75.30733a1.19068,1.19068,0,1,1,0-2.38136l857.75-.30734a1.19069,1.19069,0,0,1,0,2.38137Z"
transform="translate(-169.93432 -164.42601)"
fill="#cacaca"
/>
</svg>
);
};
export default SvgNotFound;

View File

@@ -6,39 +6,36 @@ import LoadingHardPage from "../components/LoadingHardPage";
import { Stack, Typography } from "@mui/material";
function WithAuthMiddleware({ children }) {
const router = useRouter();
const pathName = usePathname();
const { isAuth, initAuthState, errorState } = useAuth();
const router = useRouter();
const pathName = usePathname();
const { isAuth, initAuthState, errorState } = useAuth();
useEffect(() => {
if (!initAuthState) return;
if (!isAuth) {
router.replace(`/login?redirect=${encodeURIComponent(pathName)}`);
}
}, [isAuth, initAuthState]);
if (!initAuthState || !isAuth)
return (
<LoadingHardPage
authState={errorState.status}
label={
errorState.status ? (
<Stack justifyContent={"center"} alignItems={"center"}>
<Typography variant={"body1"}>{errorState.message}</Typography>
<Typography variant={"body1"}>
{" "}
کد : {errorState.status}
</Typography>
</Stack>
) : (
<Typography variant={"body1"}>درحال احراز هویت...</Typography>
)
useEffect(() => {
if (!initAuthState) return;
if (!isAuth) {
router.replace(`/login?redirect=${encodeURIComponent(pathName)}`);
}
loading={true}
/>
);
}, [isAuth, initAuthState]);
return <>{children}</>;
if (!initAuthState || !isAuth)
return (
<LoadingHardPage
authState={errorState.status}
label={
errorState.status ? (
<Stack justifyContent={"center"} alignItems={"center"}>
<Typography variant={"body1"}>{errorState.message}</Typography>
<Typography variant={"body1"}> کد : {errorState.status}</Typography>
</Stack>
) : (
<Typography variant={"body1"}>درحال احراز هویت...</Typography>
)
}
loading={true}
/>
);
return <>{children}</>;
}
export default WithAuthMiddleware;

View File

@@ -5,43 +5,39 @@ import { usePermissions } from "@/lib/hooks/usePermissions";
import { useEffect, useState } from "react";
function WithPermission({ children, permission_name }) {
const { data, isLoading } = usePermissions();
const [cachedData, setCachedData] = useState(null);
const { data, isLoading } = usePermissions();
const [cachedData, setCachedData] = useState(null);
useEffect(() => {
if (data) {
setCachedData(data);
useEffect(() => {
if (data) {
setCachedData(data);
}
}, [data]);
if (isLoading || !cachedData || !permission_name) {
return null;
}
}, [data]);
if (isLoading || !cachedData || !permission_name) {
return null;
}
const hasPermission =
permission_name.includes("all") || permission_name.some((permission) => cachedData.includes(permission));
const hasPermission =
permission_name.includes("all") ||
permission_name.some((permission) => cachedData.includes(permission));
if (!hasPermission) {
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
<Typography
variant="h5"
sx={{ letterSpacing: "2px", color: "error.main" }}
>
شما دسترسی لازم به این صفحه را ندارید
</Typography>
</Box>
);
}
return <>{children}</>;
if (!hasPermission) {
return (
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
height: "100%",
}}
>
<Typography variant="h5" sx={{ letterSpacing: "2px", color: "error.main" }}>
شما دسترسی لازم به این صفحه را ندارید
</Typography>
</Box>
);
}
return <>{children}</>;
}
export default WithPermission;

View File

@@ -1,5 +1,5 @@
const WithWidgetMiddleware = ({ children, enable }) => {
return enable ? <>{children}</> : null;
return enable ? <>{children}</> : null;
};
export default WithWidgetMiddleware;

View File

@@ -6,40 +6,37 @@ import LoadingHardPage from "../components/LoadingHardPage";
import { Stack, Typography } from "@mui/material";
function WithoutAuthMiddleware({ children }) {
const router = useRouter();
const { isAuth, initAuthState, errorState } = useAuth();
const searchParams = useSearchParams();
const router = useRouter();
const { isAuth, initAuthState, errorState } = useAuth();
const searchParams = useSearchParams();
const redirect = searchParams.get("redirect");
const redirect = searchParams.get("redirect");
useEffect(() => {
if (!initAuthState) return;
if (isAuth) {
router.replace(redirect ? decodeURIComponent(redirect) : "/dashboard");
}
}, [isAuth, initAuthState]);
if (!initAuthState || isAuth)
return (
<LoadingHardPage
authState={errorState.status}
label={
errorState.status ? (
<Stack justifyContent={"center"} alignItems={"center"}>
<Typography variant={"body1"}>{errorState.message}</Typography>
<Typography variant={"body1"}>
{" "}
کد : {errorState.status}
</Typography>
</Stack>
) : (
<Typography variant={"body1"}>درحال احراز هویت...</Typography>
)
useEffect(() => {
if (!initAuthState) return;
if (isAuth) {
router.replace(redirect ? decodeURIComponent(redirect) : "/dashboard");
}
loading={true}
/>
);
return <>{children}</>;
}, [isAuth, initAuthState]);
if (!initAuthState || isAuth)
return (
<LoadingHardPage
authState={errorState.status}
label={
errorState.status ? (
<Stack justifyContent={"center"} alignItems={"center"}>
<Typography variant={"body1"}>{errorState.message}</Typography>
<Typography variant={"body1"}> کد : {errorState.status}</Typography>
</Stack>
) : (
<Typography variant={"body1"}>درحال احراز هویت...</Typography>
)
}
loading={true}
/>
);
return <>{children}</>;
}
export default WithoutAuthMiddleware;

View File

@@ -1,10 +1,10 @@
export default function DataTableFilterDataStructure(filterData, isValueEmpty) {
return Object.values(filterData)
.filter((filter) => !isValueEmpty(filter.value))
.map(({ filterMode, id, datatype, value }) => ({
id: id.replace(/__/g, "."),
fn: filterMode,
datatype,
value,
}));
return Object.values(filterData)
.filter((filter) => !isValueEmpty(filter.value))
.map(({ filterMode, id, datatype, value }) => ({
id: id.replace(/__/g, "."),
fn: filterMode,
datatype,
value,
}));
}

View File

@@ -6,10 +6,10 @@ import rtlPlugin from "stylis-plugin-rtl";
// Create rtl cache
export const rtlCache = createCache({
key: "mui-rtl",
stylisPlugins: [prefixer, rtlPlugin],
key: "mui-rtl",
stylisPlugins: [prefixer, rtlPlugin],
});
export function Rtl(props) {
return <CacheProvider value={rtlCache}>{props.children}</CacheProvider>;
return <CacheProvider value={rtlCache}>{props.children}</CacheProvider>;
}

View File

@@ -1,72 +1,65 @@
"use client";
import { toast } from "react-toastify";
import {
errorAccessDeniedToast,
errorClientToast,
errorLogicToast,
errorServerToast,
errorTooManyToast,
errorUnauthorizedToast,
errorValidationToast,
errorAccessDeniedToast,
errorClientToast,
errorLogicToast,
errorServerToast,
errorTooManyToast,
errorUnauthorizedToast,
errorValidationToast,
} from "@/core/components/Toasts/error";
const isServerError = (status) => status >= 500 && status <= 599;
const isClientError = (status) => status >= 400 && status <= 499;
const errorServer = (response, notification, toastContainer) => {
if (notification) errorServerToast(toastContainer);
if (notification) errorServerToast(toastContainer);
};
const errorClient = (response, notification, toastContainer, logout) => {
switch (response.status) {
case 401:
logout();
if (notification) errorUnauthorizedToast(toastContainer);
break;
case 403:
if (notification)
errorAccessDeniedToast(response.data.message, toastContainer);
break;
case 422:
if ("type" in response.data) {
if (Array.isArray(response.data.message)) {
response.data.message.map((item) => {
if (notification) errorLogicToast(item, toastContainer);
});
} else {
if (notification)
errorLogicToast(response.data.message, toastContainer);
}
break;
}
if (notification) {
const errorsMap = Object.keys(response.data.errors);
const errorsArray = response.data.errors;
switch (response.status) {
case 401:
logout();
if (notification) errorUnauthorizedToast(toastContainer);
break;
case 403:
if (notification) errorAccessDeniedToast(response.data.message, toastContainer);
break;
case 422:
if ("type" in response.data) {
if (Array.isArray(response.data.message)) {
response.data.message.map((item) => {
if (notification) errorLogicToast(item, toastContainer);
});
} else {
if (notification) errorLogicToast(response.data.message, toastContainer);
}
break;
}
if (notification) {
const errorsMap = Object.keys(response.data.errors);
const errorsArray = response.data.errors;
errorsMap.map((item, index) => {
errorValidationToast(errorsArray[item][0], toastContainer);
});
}
break;
case 429:
if (notification) errorTooManyToast(toastContainer);
break;
default:
if (notification) errorClientToast(toastContainer);
break;
}
errorsMap.map((item, index) => {
errorValidationToast(errorsArray[item][0], toastContainer);
});
}
break;
case 429:
if (notification) errorTooManyToast(toastContainer);
break;
default:
if (notification) errorClientToast(toastContainer);
break;
}
};
export const errorResponse = (
response,
notification,
toastContainer,
logout,
) => {
if (notification) toast.dismiss({ containerId: toastContainer });
if (isServerError(response.status)) {
errorServer(response, notification, toastContainer);
} else if (isClientError(response.status)) {
errorClient(response, notification, toastContainer, logout);
}
export const errorResponse = (response, notification, toastContainer, logout) => {
if (notification) toast.dismiss({ containerId: toastContainer });
if (isServerError(response.status)) {
errorServer(response, notification, toastContainer);
} else if (isClientError(response.status)) {
errorClient(response, notification, toastContainer, logout);
}
};

View File

@@ -1,19 +1,17 @@
export function filterMenuItems(items, _permissions = []) {
return items.reduce((acc, item) => {
if (item.permissions) {
if (
item.permissions.some((permission) => _permissions.includes(permission))
) {
acc.push(item);
}
} else if (item.hasSubitems) {
const filteredSubItems = filterMenuItems(item.Subitems, _permissions);
if (filteredSubItems.length > 0) {
acc.push({ ...item, Subitems: filteredSubItems });
}
} else {
acc.push(item);
}
return acc;
}, []);
return items.reduce((acc, item) => {
if (item.permissions) {
if (item.permissions.some((permission) => _permissions.includes(permission))) {
acc.push(item);
}
} else if (item.hasSubitems) {
const filteredSubItems = filterMenuItems(item.Subitems, _permissions);
if (filteredSubItems.length > 0) {
acc.push({ ...item, Subitems: filteredSubItems });
}
} else {
acc.push(item);
}
return acc;
}, []);
}

View File

@@ -1,9 +1,9 @@
export const flattenArrayOfObjects = (array, key) => {
return array.reduce((acc, obj) => {
acc.push(obj);
if (Array.isArray(obj[key])) {
acc.push(...flattenArrayOfObjects(obj[key], key));
}
return acc;
}, []);
return array.reduce((acc, obj) => {
acc.push(obj);
if (Array.isArray(obj[key])) {
acc.push(...flattenArrayOfObjects(obj[key], key));
}
return acc;
}, []);
};

View File

@@ -1,12 +1,12 @@
export const flattenObjectOfObjects = (obj, res = {}) => {
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object" && obj[key] !== null) {
flattenObjectOfObjects(obj[key], res);
} else {
res[key] = obj[key];
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
if (typeof obj[key] === "object" && obj[key] !== null) {
flattenObjectOfObjects(obj[key], res);
} else {
res[key] = obj[key];
}
}
}
}
return res;
return res;
};

View File

@@ -1,14 +1,14 @@
export const getValueByPath = (obj, path) => {
const keys = path.split(".");
const keys = path.split(".");
let value = obj;
let value = obj;
for (const key of keys) {
if (value === undefined) {
return undefined;
for (const key of keys) {
if (value === undefined) {
return undefined;
}
value = value[key];
}
value = value[key];
}
return value;
return value;
};

View File

@@ -1,15 +1,15 @@
const api = process.env.NEXT_PUBLIC_API_URL;
export const headerMenu = [
// {
// title: "تصادفات",
// subMenu: [
// [
// {
// title: "تصادفات روزانه",
// href: api + "/v2/daily_accidents/create",
// },
// ],
// ],
// },
// {
// title: "تصادفات",
// subMenu: [
// [
// {
// title: "تصادفات روزانه",
// href: api + "/v2/daily_accidents/create",
// },
// ],
// ],
// },
];

View File

@@ -1,6 +1,6 @@
export default function isArrayEmpty(value) {
if (Array.isArray(value)) {
return value.length === 0 || value.every((v) => v === "");
}
return value === "" || value === null || value === undefined;
if (Array.isArray(value)) {
return value.length === 0 || value.every((v) => v === "");
}
return value === "" || value === null || value === undefined;
}

View File

@@ -1,30 +1,30 @@
function validateNationalCode(code) {
const invalidCodes = [
"1111111111",
"2222222222",
"3333333333",
"4444444444",
"5555555555",
"6666666666",
"7777777777",
"8888888888",
"9999999999",
];
if (invalidCodes.includes(code)) return false;
const invalidCodes = [
"1111111111",
"2222222222",
"3333333333",
"4444444444",
"5555555555",
"6666666666",
"7777777777",
"8888888888",
"9999999999",
];
if (invalidCodes.includes(code)) return false;
const L = code.length;
if (L < 8 || parseInt(code, 10) === 0) return false;
const L = code.length;
if (L < 8 || parseInt(code, 10) === 0) return false;
code = code.padStart(10, "0");
if (parseInt(code.substr(3, 6), 10) === 0) return false;
code = code.padStart(10, "0");
if (parseInt(code.substr(3, 6), 10) === 0) return false;
const c = parseInt(code.charAt(9), 10);
let s = 0;
for (let i = 0; i < 9; i++) {
s += parseInt(code.charAt(i), 10) * (10 - i);
}
s = s % 11;
return (s < 2 && c === s) || (s >= 2 && c === 11 - s);
const c = parseInt(code.charAt(9), 10);
let s = 0;
for (let i = 0; i < 9; i++) {
s += parseInt(code.charAt(i), 10) * (10 - i);
}
s = s % 11;
return (s < 2 && c === s) || (s >= 2 && c === 11 - s);
}
export default validateNationalCode;

View File

@@ -2,28 +2,28 @@ import { Settings } from "@mui/icons-material";
import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard";
export const pageMenu = [
{
id: "dashboard",
label: "پیشخوان",
type: "page",
route: "/dashboard",
icon: <SpaceDashboardIcon sx={{ width: "inherit", height: "inherit" }} />,
permissions: ["all"],
},
{
id: "systemManagment",
label: "مدیریت سامانه",
type: "menu",
icon: <Settings sx={{ width: "inherit", height: "inherit" }} />,
hasSubitems: true,
Subitems: [
{
id: "systemManagment-users",
label: "کاربران",
{
id: "dashboard",
label: "پیشخوان",
type: "page",
route: "/dashboard/users",
permissions: ["manage_users"],
},
],
},
route: "/dashboard",
icon: <SpaceDashboardIcon sx={{ width: "inherit", height: "inherit" }} />,
permissions: ["all"],
},
{
id: "systemManagment",
label: "مدیریت سامانه",
type: "menu",
icon: <Settings sx={{ width: "inherit", height: "inherit" }} />,
hasSubitems: true,
Subitems: [
{
id: "systemManagment-users",
label: "کاربران",
type: "page",
route: "/dashboard/users",
permissions: ["manage_users"],
},
],
},
];

View File

@@ -3,8 +3,8 @@ import { toast } from "react-toastify";
import { successToast } from "@/core/components/Toasts/success";
export const successRequest = (notification, toastContainer) => {
if (notification) {
toast.dismiss({ containerId: toastContainer });
successToast(toastContainer);
}
if (notification) {
toast.dismiss({ containerId: toastContainer });
successToast(toastContainer);
}
};

View File

@@ -2,31 +2,31 @@
import { createTheme } from "@mui/material";
const theme = createTheme({
direction: "rtl",
typography: {
fontFamily: `IRANSansFaNum, sans-serif`,
fontSize: 12,
},
palette: {
primary: {
main: "#1b4332",
contrastText: "#FFFFFF",
direction: "rtl",
typography: {
fontFamily: `IRANSansFaNum, sans-serif`,
fontSize: 12,
},
secondary: {
main: "#1B4043",
contrastText: "#FFFFFF",
},
},
components: {
MuiBackdrop: {
styleOverrides: {
root: {
backdropFilter: "blur(3px)",
backgroundColor: "rgba(0, 0, 0, 0.3)",
palette: {
primary: {
main: "#1b4332",
contrastText: "#FFFFFF",
},
secondary: {
main: "#1B4043",
contrastText: "#FFFFFF",
},
},
components: {
MuiBackdrop: {
styleOverrides: {
root: {
backdropFilter: "blur(3px)",
backgroundColor: "rgba(0, 0, 0, 0.3)",
},
},
},
},
},
},
});
export default theme;

View File

@@ -2,148 +2,119 @@ import { alpha, darken } from "@mui/material";
export const parseCSSVarId = (id) => id.replace(/[^a-zA-Z0-9]/g, "_");
export const parseFromValuesOrFunc = (fn, arg) =>
fn instanceof Function ? fn(arg) : fn;
export const parseFromValuesOrFunc = (fn, arg) => (fn instanceof Function ? fn(arg) : fn);
export const getCommonToolbarStyles = ({ table }) => ({
alignItems: "flex-start",
backgroundColor: table.options.mrtTheme.baseBackgroundColor,
display: "grid",
flexWrap: "wrap-reverse",
minHeight: "3.5rem",
overflow: "hidden",
position: "relative",
transition: "all 150ms ease-in-out",
zIndex: 1,
alignItems: "flex-start",
backgroundColor: table.options.mrtTheme.baseBackgroundColor,
display: "grid",
flexWrap: "wrap-reverse",
minHeight: "3.5rem",
overflow: "hidden",
position: "relative",
transition: "all 150ms ease-in-out",
zIndex: 1,
});
export const getCommonTooltipProps = (placement) => ({
disableInteractive: true,
enterDelay: 500,
enterNextDelay: 500,
placement,
disableInteractive: true,
enterDelay: 500,
enterNextDelay: 500,
placement,
});
export const flipIconStyles = (theme) =>
theme.direction === "rtl"
? { style: { transform: "scaleX(-1)" } }
: undefined;
theme.direction === "rtl" ? { style: { transform: "scaleX(-1)" } } : undefined;
export const getCommonPinnedCellStyles = ({ column, table, theme }) => {
const { baseBackgroundColor } = table.options.mrtTheme;
const isPinned = column?.getIsPinned();
const { baseBackgroundColor } = table.options.mrtTheme;
const isPinned = column?.getIsPinned();
return {
'&[data-pinned="true"]': {
"&:before": {
backgroundColor: alpha(
darken(
baseBackgroundColor,
theme.palette.mode === "dark" ? 0.05 : 0.01,
),
0.97,
),
boxShadow: column
? isPinned === "left" && column.getIsLastColumn(isPinned)
? `-4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset`
: isPinned === "right" && column.getIsFirstColumn(isPinned)
? `4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset`
: undefined
: undefined,
...commonCellBeforeAfterStyles,
},
},
};
return {
'&[data-pinned="true"]': {
"&:before": {
backgroundColor: alpha(darken(baseBackgroundColor, theme.palette.mode === "dark" ? 0.05 : 0.01), 0.97),
boxShadow: column
? isPinned === "left" && column.getIsLastColumn(isPinned)
? `-4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset`
: isPinned === "right" && column.getIsFirstColumn(isPinned)
? `4px 0 4px -4px ${alpha(theme.palette.grey[700], 0.5)} inset`
: undefined
: undefined,
...commonCellBeforeAfterStyles,
},
},
};
};
export const getCommonMRTCellStyles = ({
column,
header,
table,
tableCellProps,
theme,
}) => {
const {
getState,
options: { enableColumnVirtualization, layoutMode },
} = table;
const { draggingColumn } = getState();
const { columnDef } = column;
const { columnDefType } = columnDef;
export const getCommonMRTCellStyles = ({ column, header, table, tableCellProps, theme }) => {
const {
getState,
options: { enableColumnVirtualization, layoutMode },
} = table;
const { draggingColumn } = getState();
const { columnDef } = column;
const { columnDefType } = columnDef;
const isColumnPinned =
columnDef.columnDefType !== "group" && column.getIsPinned();
const isColumnPinned = columnDef.columnDefType !== "group" && column.getIsPinned();
const widthStyles = {
minWidth: `max(calc(var(--${header ? "header" : "col"}-${parseCSSVarId(
header?.id ?? column.id,
)}-size) * 1px), ${columnDef.minSize ?? 30}px)`,
width: `calc(var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size) * 1px)`,
};
const widthStyles = {
minWidth: `max(calc(var(--${header ? "header" : "col"}-${parseCSSVarId(
header?.id ?? column.id
)}-size) * 1px), ${columnDef.minSize ?? 30}px)`,
width: `calc(var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size) * 1px)`,
};
if (layoutMode === "grid") {
widthStyles.flex = `${
[0, false].includes(columnDef.grow)
? 0
: `var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size)`
} 0 auto`;
} else if (layoutMode === "grid-no-grow") {
widthStyles.flex = `${+(columnDef.grow || 0)} 0 auto`;
}
if (layoutMode === "grid") {
widthStyles.flex = `${
[0, false].includes(columnDef.grow)
? 0
: `var(--${header ? "header" : "col"}-${parseCSSVarId(header?.id ?? column.id)}-size)`
} 0 auto`;
} else if (layoutMode === "grid-no-grow") {
widthStyles.flex = `${+(columnDef.grow || 0)} 0 auto`;
}
const pinnedStyles = isColumnPinned
? {
...getCommonPinnedCellStyles({ column, table, theme }),
left:
isColumnPinned === "left"
? `${column.getStart("left")}px`
: undefined,
opacity: 0.97,
position: "sticky",
right:
isColumnPinned === "right"
? `${column.getAfter("right")}px`
: undefined,
}
: {};
const pinnedStyles = isColumnPinned
? {
...getCommonPinnedCellStyles({ column, table, theme }),
left: isColumnPinned === "left" ? `${column.getStart("left")}px` : undefined,
opacity: 0.97,
position: "sticky",
right: isColumnPinned === "right" ? `${column.getAfter("right")}px` : undefined,
}
: {};
return {
backgroundColor: "inherit",
backgroundImage: "inherit",
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
justifyContent:
columnDefType === "group"
? "center"
: layoutMode?.startsWith("grid")
? tableCellProps.align
: undefined,
opacity:
table.getState().draggingColumn?.id === column.id ||
table.getState().hoveredColumn?.id === column.id
? 0.5
: 1,
position: "relative",
transition: enableColumnVirtualization
? "none"
: `padding 150ms ease-in-out`,
zIndex:
column.getIsResizing() || draggingColumn?.id === column.id
? 2
: columnDefType !== "group" && isColumnPinned
? 1
: 0,
...pinnedStyles,
...widthStyles,
...parseFromValuesOrFunc(tableCellProps?.sx, theme),
};
return {
backgroundColor: "inherit",
backgroundImage: "inherit",
display: layoutMode?.startsWith("grid") ? "flex" : undefined,
justifyContent:
columnDefType === "group" ? "center" : layoutMode?.startsWith("grid") ? tableCellProps.align : undefined,
opacity:
table.getState().draggingColumn?.id === column.id || table.getState().hoveredColumn?.id === column.id
? 0.5
: 1,
position: "relative",
transition: enableColumnVirtualization ? "none" : `padding 150ms ease-in-out`,
zIndex:
column.getIsResizing() || draggingColumn?.id === column.id
? 2
: columnDefType !== "group" && isColumnPinned
? 1
: 0,
...pinnedStyles,
...widthStyles,
...parseFromValuesOrFunc(tableCellProps?.sx, theme),
};
};
export const commonCellBeforeAfterStyles = {
content: '""',
height: "100%",
left: 0,
position: "absolute",
top: 0,
width: "100%",
zIndex: -1,
content: '""',
height: "100%",
left: 0,
position: "absolute",
top: 0,
width: "100%",
zIndex: -1,
};