Files
cpost-front/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx
Samandar Turg'unboev 1c57e2a9ee exel name
2025-05-28 15:13:12 +05:00

397 lines
14 KiB
TypeScript

'use client';
import ActionPopMenu from '@/components/common/ActionPopMenu';
import { MyTable, ColumnData } from '@/components/common/MyTable';
import StatusChangePopup from '@/components/common/StatusChangePopup';
import BaseButton from '@/components/ui-kit/BaseButton';
import BaseIconButton from '@/components/ui-kit/BaseIconButton';
import BaseInput from '@/components/ui-kit/BaseInput';
import BasePagination from '@/components/ui-kit/BasePagination';
import { useAuthContext } from '@/context/auth-context';
import { BoxStatus, BoxStatusList, IBox } from '@/data/box/box.model';
import { box_requests } from '@/data/box/box.requests';
import { IRealBox } from '@/data/real-box/real-box.model';
import { real_box_requests } from '@/data/real-box/real-box.requests';
import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
import useDebouncedInput from '@/hooks/useDebouncedInput';
import useInput from '@/hooks/useInput';
import { useMyNavigation } from '@/hooks/useMyNavigation';
import { useMyTranslation } from '@/hooks/useMyTranslation';
import useRequest from '@/hooks/useRequest';
import { file_service } from '@/services/file-service';
import { notifyUnknownError } from '@/services/notification';
import { getBoxStatusStyles, getStatusColor } from '@/theme/getStatusBoxStyles';
import { Add, QrCode, AddCircleOutline, Circle, Delete, Download, Edit, FilterList, FilterListOff, Search, PlusOne } from '@mui/icons-material';
import { Box, Button, Stack, Tooltip, Typography } from '@mui/material';
import { useRouter } from 'next/navigation';
import { log } from 'node:console';
import React, { useEffect, useMemo, useState } from 'react';
type Props = {};
const DashboardRealBoxesPage = (props: Props) => {
const t = useMyTranslation();
const navigation = useMyNavigation();
const { isAdmin } = useAuthContext();
const [page, setPage] = useState(1);
const [pageSize] = useState(DEFAULT_PAGE_SIZE);
const { value: keyword, onChange: handleKeyword, setValue: setKeyword } = useInput('');
const [boxStatusFilter, setBoxStatusFilter] = useState<BoxStatus | undefined>(undefined);
const [deleteIds, setDeleteIds] = useState<number[]>([]);
const [downloadIds, setDownloadIds] = useState<number[]>([]);
const [changeStatusIds, setChangeStatusIds] = useState<number[]>([]);
const boxStatusOptions = useMemo(() => {
const p = ['READY_TO_INVOICE'] as BoxStatus[];
if (isAdmin) {
p.push('READY');
}
return p;
}, [isAdmin]);
const getBoxesQuery = useRequest(
() =>
real_box_requests.getAll({
page: page,
cargoId: keyword,
status: boxStatusFilter,
direction: 'desc',
sort: 'id',
}),
{
dependencies: [page, boxStatusFilter],
selectData(data) {
return data.data.data;
},
}
);
const {
data: list,
totalElements,
totalPages,
} = useMemo(() => {
if (getBoxesQuery.data?.data) {
return {
data: getBoxesQuery.data.data,
totalElements: getBoxesQuery.data.totalElements,
totalPages: getBoxesQuery.data.totalPages,
};
} else {
return {
data: [],
totalElements: 0,
totalPages: 0,
};
}
}, [getBoxesQuery]);
const loading = getBoxesQuery.loading;
const handleChange = (newPage: number) => {
setTimeout(() => {
setPage(newPage);
}, 100);
};
const resetFilter = () => {
setPage(1);
setKeyword('');
setBoxStatusFilter(undefined);
};
const onDelete = async (id: number) => {
if (deleteIds.includes(id)) return;
try {
setDeleteIds(p => [...p, id]);
await real_box_requests.delete({ boxId: id });
getBoxesQuery.refetch();
} catch (error) {
notifyUnknownError(error);
} finally {
setDeleteIds(prev => prev.filter(i => i !== id));
}
};
const onDownloadExcel = async (id: number, name: string) => {
if (downloadIds.includes(id)) return;
try {
setDownloadIds(p => [...p, id]);
const response = await real_box_requests.downloadExcel({ boxId: id });
const file = new File([response.data], `${name}.xlsx`, { type: response.data.type });
file_service.download(file);
} catch (error) {
notifyUnknownError(error);
} finally {
setDownloadIds(prev => prev.filter(i => i !== id));
}
};
const onDownloadQrCode = async (id: number) => {
if (downloadIds.includes(id)) return;
try {
setDownloadIds(p => [...p, id]);
const response = await real_box_requests.downloadQrCode({ boxId: id });
console.log(response, "rres");
const file = new File([response.data], 'qr.png', { type: response.data.type });
file_service.download(file);
} catch (error) {
notifyUnknownError(error);
console.log(error);
} finally {
setDownloadIds(prev => prev.filter(i => i !== id));
}
};
const onChangeStatus = async (id: number, newStatus: BoxStatus) => {
if (changeStatusIds.includes(id)) return;
try {
setChangeStatusIds(p => [...p, id]);
await box_requests.changeStatus({ packetId: id, status: newStatus });
getBoxesQuery.refetch();
} catch (error) {
notifyUnknownError(error);
} finally {
setChangeStatusIds(prev => prev.filter(i => i !== id));
}
};
useEffect(() => {
const timeoutId = setTimeout(() => {
setPage(1);
getBoxesQuery.refetch();
}, 350);
return () => clearTimeout(timeoutId);
}, [keyword]);
// No, PartyName, PacketName, PartyTozaOg'irlik, CountOfItems, WeightOfItems, CargoID, PassportNameFamily - PacketStatusForInvoice
const columns: ColumnData<IRealBox>[] = [
{
label: t('No'),
width: 100,
renderCell(data, rowIndex) {
return (page - 1) * pageSize + rowIndex + 1;
},
},
{
label: t("qr_code"),
width: 120,
renderCell: data => {
return <Button
onClick={() =>
onDownloadQrCode(data.id)
}>
<QrCode />
</Button >;
},
},
{
dataKey: 'id',
label: t("add_more"),
width: 120,
renderCell: data => {
return <Button onClick={() => navigation.push(pageLinks.dashboard.real_boxes.edit(data.id))}>
<Add />
</Button>;
},
},
{
dataKey: 'boxName',
label: t('cargo_id'),
width: 120,
},
{
dataKey: "boxName",
label: t('party_name'),
width: 120,
},
// {
// dataKey: 'name',
// label: t('name'),
// width: 120,
// },
// {
// dataKey: 'packetNetWeight',
// label: t("weight"),
// width: 120,
// },
{
dataKey: 'packetsCount',
label: t('count_of_items'),
width: 120,
},
// {
// dataKey: 'totalNetWeight',
// label: t("party_weight"),
// width: 120,
// },
// {
// dataKey: 'passportName',
// label: t('client'),
// width: 120,
// },
// {
// dataKey: 'status',
// label: t('status'),
// width: 240,
// renderHeaderCell(rowIndex) {
// return (
// <Stack direction={'row'} alignItems={'center'}>
// <span>{t('box_status')}</span>
// <ActionPopMenu
// buttons={BoxStatusList.map(stat => {
// return {
// icon: <Circle sx={{ path: { color: getStatusColor(stat) } }} />,
// label: t(stat),
// onClick() {
// setBoxStatusFilter(stat);
// setPage(1);
// },
// };
// })}
// mainIcon={<FilterList />}
// placement={{
// anchorOrigin: {
// vertical: 'bottom',
// horizontal: 'center',
// },
// transformOrigin: {
// horizontal: 'center',
// vertical: 'top',
// },
// }}
// />
// </Stack>
// );
// },
// renderCell(data) {
// return (
// <StatusChangePopup
// anchor={{
// status: data.status,
// text: t(data.status),
// }}
// loading={changeStatusIds.includes(data.id)}
// buttons={boxStatusOptions.map(stat => {
// return {
// icon: (
// <Circle
// sx={{
// path: {
// color: getStatusColor(stat),
// },
// }}
// />
// ),
// label: t(stat),
// onClick: () => {
// onChangeStatus(data.id, stat);
// },
// };
// })}
// />
// );
// },
// },
{
label: '',
width: 100,
numeric: true,
renderCell(data, rowIndex) {
return (
<ActionPopMenu
buttons={[
{
icon: <Edit sx={{ path: { color: '#3489E4' } }} />,
label: t('edit'),
onClick: () => {
navigation.push(pageLinks.dashboard.real_boxes.edit(data.id));
},
},
{
icon: <Delete sx={{ path: { color: '#3489E4' } }} />,
label: t('delete'),
onClick: () => {
onDelete(data.id);
},
dontCloseOnClick: true,
loading: deleteIds.includes(data.id),
},
{
icon: <Download sx={{ path: { color: '#3489E4' } }} />,
label: t('download_excel'),
onClick: () => {
onDownloadExcel(data.id, data.boxName);
},
loading: downloadIds.includes(data.id),
dontCloseOnClick: true,
},
]}
/>
);
},
},
];
return (
<Box>
<Stack direction={'row'} mb={3} spacing={3}>
<BaseButton colorVariant='blue' startIcon={<Add />} href={pageLinks.dashboard.real_boxes.create}>
{t('create_box')}
</BaseButton>
</Stack>
<Box
width={1}
mb={3}
sx={{
padding: '28px',
borderRadius: '16px',
backgroundColor: '#fff',
}}
>
<Stack mb={3.5} direction={'row'} justifyContent={'space-between'} alignItems={'center'}>
<Typography
sx={{
fontSize: '20px',
lineHeight: '24px',
fontWeight: 600,
textTransform: 'capitalize',
color: '#000',
}}
>
{t('boxes')}
</Typography>
<Stack direction={'row'} alignItems={'center'} spacing={2}>
<BaseInput
InputProps={{
startAdornment: <Search color='primary' />,
}}
placeholder={t('filter_packet_name')}
value={keyword}
onChange={e => {
setKeyword(e.target.value);
}}
/>
<BaseButton colorVariant='gray' startIcon={<FilterListOff />} size='small' onClick={resetFilter}>
{t('reset_filter')}
</BaseButton>
</Stack>
</Stack>
<Box mb={6}>
<MyTable columns={columns as any} data={list} loading={loading} />
</Box>
<Stack direction={'row'} justifyContent={'center'}>
<BasePagination page={page} pageSize={pageSize} totalCount={totalElements} onChange={handleChange} />
</Stack>
</Box>
</Box>
);
};
export default DashboardRealBoxesPage;