feat: products page

This commit is contained in:
2025-10-08 22:32:16 +04:00
parent 820d9b4d33
commit 8af4fcce2f
25 changed files with 664 additions and 58 deletions

View File

@ -0,0 +1,86 @@
import { FC, useCallback } from "react";
import { IconMoodSad } from "@tabler/icons-react";
import { Group, Pagination, Stack, Text } from "@mantine/core";
import useDealsTableColumns from "@/app/deals/components/shared/DealsTable/useDealsTableColumns";
import { useDealsContext } from "@/app/deals/contexts/DealsContext";
import { useProjectsContext } from "@/app/deals/contexts/ProjectsContext";
import BaseTable from "@/components/ui/BaseTable/BaseTable";
import { useDrawersContext } from "@/drawers/DrawersContext";
import useIsMobile from "@/hooks/utils/useIsMobile";
import { DealSchema } from "@/lib/client";
const DealsTable: FC = () => {
const isMobile = useIsMobile();
const { selectedProject } = useProjectsContext();
const { deals, paginationInfo, page, setPage, sortingForm, dealsCrud } =
useDealsContext();
const { openDrawer } = useDrawersContext();
const onEditClick = useCallback(
(deal: DealSchema) => {
openDrawer({
key: "dealEditorDrawer",
props: {
value: deal,
onChange: deal => dealsCrud.onUpdate(deal.id, deal),
onDelete: dealsCrud.onDelete,
project: selectedProject,
},
});
},
[openDrawer, dealsCrud]
);
const columns = useDealsTableColumns({ onEditClick });
return (
<Stack
p={isMobile ? "xs" : ""}
gap={"xs"}
h={"100%"}>
<BaseTable
withTableBorder
records={[...deals]}
columns={columns}
sortStatus={{
columnAccessor: sortingForm.values.sortingField ?? "",
direction: sortingForm.values.sortingDirection,
}}
onSortStatusChange={sorting => {
sortingForm.setFieldValue(
"sortingField",
sorting.columnAccessor
);
sortingForm.setFieldValue(
"sortingDirection",
sorting.direction
);
}}
emptyState={
<Group
align={"center"}
gap={"xs"}>
<Text>Нет сделок</Text>
<IconMoodSad />
</Group>
}
groups={undefined}
style={{
height: "100%",
}}
/>
{paginationInfo && paginationInfo.totalPages > 1 && (
<Group justify={"flex-end"}>
<Pagination
withEdges
total={paginationInfo.totalPages}
value={page}
onChange={setPage}
/>
</Group>
)}
</Stack>
);
};
export default DealsTable;

View File

@ -0,0 +1,57 @@
import { useMemo } from "react";
import { IconEdit } from "@tabler/icons-react";
import { DataTableColumn } from "mantine-datatable";
import ActionIconWithTip from "@/components/ui/ActionIconWithTip/ActionIconWithTip";
import useIsMobile from "@/hooks/utils/useIsMobile";
import { DealSchema } from "@/lib/client";
import { utcDateTimeToLocalString } from "@/utils/datetime";
type Props = {
onEditClick: (deal: DealSchema) => void;
};
const useDealsTableColumns = ({ onEditClick }: Props) => {
const isMobile = useIsMobile();
return useMemo(
() =>
[
{
accessor: "actions",
title: isMobile ? "" : "Действия",
sortable: false,
textAlign: "center",
width: "0%",
render: deal => (
<ActionIconWithTip
tipLabel={"Редактировать"}
onClick={() => onEditClick(deal)}
variant={isMobile ? "subtle" : "default"}>
<IconEdit />
</ActionIconWithTip>
),
},
{
accessor: "id",
title: isMobile ? "№" : "Номер",
sortable: true,
width: "20%",
},
{
accessor: "name",
title: "Название",
width: "45%",
},
{
title: "Дата создания",
accessor: "createdAt",
render: deal => utcDateTimeToLocalString(deal.createdAt),
sortable: true,
width: "35%",
},
] as DataTableColumn<DealSchema>[],
[onEditClick]
);
};
export default useDealsTableColumns;