shift
This commit is contained in:
@@ -938,9 +938,6 @@
|
|||||||
"close_shift": "بستن شیفت",
|
"close_shift": "بستن شیفت",
|
||||||
"open_title": "باز کردن شیفت صندوق",
|
"open_title": "باز کردن شیفت صندوق",
|
||||||
"close_title": "بستن شیفت صندوق",
|
"close_title": "بستن شیفت صندوق",
|
||||||
"edit_title": "ویرایش شیفت صندوق",
|
|
||||||
"edit_shift": "ویرایش شیفت",
|
|
||||||
"save_changes": "ذخیره تغییرات",
|
|
||||||
"detail_title": "جزئیات شیفت صندوق",
|
"detail_title": "جزئیات شیفت صندوق",
|
||||||
"summary_title": "خلاصه شیفت",
|
"summary_title": "خلاصه شیفت",
|
||||||
"operator": "اپراتور",
|
"operator": "اپراتور",
|
||||||
@@ -962,7 +959,6 @@
|
|||||||
"view_details": "مشاهده جزئیات",
|
"view_details": "مشاهده جزئیات",
|
||||||
"opened_success": "شیفت صندوق با موفقیت باز شد",
|
"opened_success": "شیفت صندوق با موفقیت باز شد",
|
||||||
"closed_success": "شیفت صندوق با موفقیت بسته شد",
|
"closed_success": "شیفت صندوق با موفقیت بسته شد",
|
||||||
"updated_success": "شیفت صندوق با موفقیت ویرایش شد",
|
|
||||||
"status_values": {
|
"status_values": {
|
||||||
"open": "باز",
|
"open": "باز",
|
||||||
"closed": "بسته"
|
"closed": "بسته"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { type FC, useMemo, useState } from "react";
|
import { type FC, useMemo, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Add, Edit, Lock1 } from "iconsax-react";
|
import { Add, Lock1 } from "iconsax-react";
|
||||||
import Table from "@/components/Table";
|
import Table from "@/components/Table";
|
||||||
import Filters from "@/components/Filters";
|
import Filters from "@/components/Filters";
|
||||||
import Button from "@/components/Button";
|
import Button from "@/components/Button";
|
||||||
@@ -16,7 +16,6 @@ import { useCashShiftFiltersFields } from "./components/CashShiftFiltersFields";
|
|||||||
import CashShiftSummaryCard from "./components/CashShiftSummaryCard";
|
import CashShiftSummaryCard from "./components/CashShiftSummaryCard";
|
||||||
import OpenCashShiftModal from "./components/OpenCashShiftModal";
|
import OpenCashShiftModal from "./components/OpenCashShiftModal";
|
||||||
import CloseCashShiftModal from "./components/CloseCashShiftModal";
|
import CloseCashShiftModal from "./components/CloseCashShiftModal";
|
||||||
import EditCashShiftModal from "./components/EditCashShiftModal";
|
|
||||||
import CashShiftDetailModal from "./components/CashShiftDetailModal";
|
import CashShiftDetailModal from "./components/CashShiftDetailModal";
|
||||||
import type { CashShift } from "./types/Types";
|
import type { CashShift } from "./types/Types";
|
||||||
import { CashShiftStatus } from "./enum/Enum";
|
import { CashShiftStatus } from "./enum/Enum";
|
||||||
@@ -28,7 +27,6 @@ const CashShiftsList: FC = () => {
|
|||||||
const { t } = useTranslation("global");
|
const { t } = useTranslation("global");
|
||||||
const [isOpenModalVisible, setIsOpenModalVisible] = useState(false);
|
const [isOpenModalVisible, setIsOpenModalVisible] = useState(false);
|
||||||
const [isCloseModalVisible, setIsCloseModalVisible] = useState(false);
|
const [isCloseModalVisible, setIsCloseModalVisible] = useState(false);
|
||||||
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
|
||||||
const [isDetailModalVisible, setIsDetailModalVisible] = useState(false);
|
const [isDetailModalVisible, setIsDetailModalVisible] = useState(false);
|
||||||
const [selectedShift, setSelectedShift] = useState<CashShift | null>(null);
|
const [selectedShift, setSelectedShift] = useState<CashShift | null>(null);
|
||||||
|
|
||||||
@@ -61,10 +59,6 @@ const CashShiftsList: FC = () => {
|
|||||||
setSelectedShift(shift);
|
setSelectedShift(shift);
|
||||||
setIsDetailModalVisible(true);
|
setIsDetailModalVisible(true);
|
||||||
},
|
},
|
||||||
onEdit: (shift) => {
|
|
||||||
setSelectedShift(shift);
|
|
||||||
setIsEditModalVisible(true);
|
|
||||||
},
|
|
||||||
onClose: (shift) => {
|
onClose: (shift) => {
|
||||||
setSelectedShift(shift);
|
setSelectedShift(shift);
|
||||||
setIsCloseModalVisible(true);
|
setIsCloseModalVisible(true);
|
||||||
@@ -129,18 +123,6 @@ const CashShiftsList: FC = () => {
|
|||||||
variant="warning"
|
variant="warning"
|
||||||
label={t(`cash_shift.status_values.${CashShiftStatus.OPEN}`)}
|
label={t(`cash_shift.status_values.${CashShiftStatus.OPEN}`)}
|
||||||
/>
|
/>
|
||||||
<Button
|
|
||||||
className="w-fit px-5 bg-gray-100 text-gray-700"
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedShift(currentShift);
|
|
||||||
setIsEditModalVisible(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex gap-2 items-center">
|
|
||||||
<Edit color="#374151" size={18} />
|
|
||||||
<span>{t("cash_shift.edit_shift")}</span>
|
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
<Button
|
<Button
|
||||||
className="w-fit px-5"
|
className="w-fit px-5"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -199,15 +181,6 @@ const CashShiftsList: FC = () => {
|
|||||||
shift={selectedShift}
|
shift={selectedShift}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EditCashShiftModal
|
|
||||||
open={isEditModalVisible}
|
|
||||||
onClose={() => {
|
|
||||||
setIsEditModalVisible(false);
|
|
||||||
setSelectedShift(null);
|
|
||||||
}}
|
|
||||||
shift={selectedShift}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<CashShiftDetailModal
|
<CashShiftDetailModal
|
||||||
open={isDetailModalVisible}
|
open={isDetailModalVisible}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Edit, Eye, Lock1 } from "iconsax-react";
|
import { Eye, Lock1 } from "iconsax-react";
|
||||||
import type { ColumnType } from "@/components/types/TableTypes";
|
import type { ColumnType } from "@/components/types/TableTypes";
|
||||||
import type { CashShift } from "../types/Types";
|
import type { CashShift } from "../types/Types";
|
||||||
import {
|
import {
|
||||||
@@ -13,7 +13,6 @@ import type { TFunction } from "i18next";
|
|||||||
interface GetCashShiftTableColumnsParams {
|
interface GetCashShiftTableColumnsParams {
|
||||||
t: TFunction;
|
t: TFunction;
|
||||||
onView: (shift: CashShift) => void;
|
onView: (shift: CashShift) => void;
|
||||||
onEdit?: (shift: CashShift) => void;
|
|
||||||
onClose?: (shift: CashShift) => void;
|
onClose?: (shift: CashShift) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +26,6 @@ const getAdminName = (shift: CashShift) => {
|
|||||||
export const getCashShiftTableColumns = ({
|
export const getCashShiftTableColumns = ({
|
||||||
t,
|
t,
|
||||||
onView,
|
onView,
|
||||||
onEdit,
|
|
||||||
onClose,
|
onClose,
|
||||||
}: GetCashShiftTableColumnsParams): ColumnType<CashShift>[] => [
|
}: GetCashShiftTableColumnsParams): ColumnType<CashShift>[] => [
|
||||||
{
|
{
|
||||||
@@ -112,15 +110,6 @@ export const getCashShiftTableColumns = ({
|
|||||||
>
|
>
|
||||||
<Eye size={20} color="#8C90A3" />
|
<Eye size={20} color="#8C90A3" />
|
||||||
</button>
|
</button>
|
||||||
{onEdit && (
|
|
||||||
<button
|
|
||||||
onClick={() => onEdit(item)}
|
|
||||||
className="cursor-pointer hover:opacity-70 transition-opacity"
|
|
||||||
title={t("cash_shift.edit_shift")}
|
|
||||||
>
|
|
||||||
<Edit size={20} color="#8C90A3" />
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
{item.status === CashShiftStatus.OPEN && onClose && (
|
{item.status === CashShiftStatus.OPEN && onClose && (
|
||||||
<button
|
<button
|
||||||
onClick={() => onClose(item)}
|
onClick={() => onClose(item)}
|
||||||
|
|||||||
@@ -1,125 +0,0 @@
|
|||||||
import { type FC, useEffect, useState } from "react";
|
|
||||||
import DefaulModal from "@/components/DefaulModal";
|
|
||||||
import Input from "@/components/Input";
|
|
||||||
import Textarea from "@/components/Textarea";
|
|
||||||
import Button from "@/components/Button";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import { extractErrorMessage } from "@/config/func";
|
|
||||||
import { useUpdateCashShift } from "../hooks/useCashShiftData";
|
|
||||||
import type { CashShift } from "../types/Types";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
open: boolean;
|
|
||||||
onClose: () => void;
|
|
||||||
shift: CashShift | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const EditCashShiftModal: FC<Props> = ({ open, onClose, shift }) => {
|
|
||||||
const { t } = useTranslation("global");
|
|
||||||
const [openingAmount, setOpeningAmount] = useState("");
|
|
||||||
const [notes, setNotes] = useState("");
|
|
||||||
const [error, setError] = useState("");
|
|
||||||
const updateShift = useUpdateCashShift();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (open && shift) {
|
|
||||||
setOpeningAmount(String(shift.openingAmount));
|
|
||||||
setNotes(shift.notes ?? "");
|
|
||||||
setError("");
|
|
||||||
}
|
|
||||||
}, [open, shift]);
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setOpeningAmount("");
|
|
||||||
setNotes("");
|
|
||||||
setError("");
|
|
||||||
onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSubmit = () => {
|
|
||||||
if (!shift) return;
|
|
||||||
|
|
||||||
const numericAmount = Number(openingAmount);
|
|
||||||
|
|
||||||
if (Number.isNaN(numericAmount) || numericAmount < 0) {
|
|
||||||
setError(t("cash_shift.opening_amount_required"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateShift.mutate(
|
|
||||||
{
|
|
||||||
shiftId: shift.id,
|
|
||||||
payload: {
|
|
||||||
openingAmount: numericAmount,
|
|
||||||
notes: notes.trim() || undefined,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
onSuccess: () => {
|
|
||||||
toast.success(t("cash_shift.updated_success"));
|
|
||||||
handleClose();
|
|
||||||
},
|
|
||||||
onError: (err) => {
|
|
||||||
toast.error(extractErrorMessage(err));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!shift) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DefaulModal
|
|
||||||
open={open}
|
|
||||||
close={handleClose}
|
|
||||||
isHeader
|
|
||||||
title_header={t("cash_shift.edit_title")}
|
|
||||||
width={480}
|
|
||||||
>
|
|
||||||
<div className="mt-6">
|
|
||||||
<Input
|
|
||||||
name="openingAmount"
|
|
||||||
label={t("cash_shift.opening_amount")}
|
|
||||||
placeholder={t("cash_shift.opening_amount_placeholder")}
|
|
||||||
type="number"
|
|
||||||
seprator
|
|
||||||
value={openingAmount}
|
|
||||||
onChange={(e) => {
|
|
||||||
setOpeningAmount(e.target.value);
|
|
||||||
setError("");
|
|
||||||
}}
|
|
||||||
error_text={error}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className="mt-4">
|
|
||||||
<Textarea
|
|
||||||
name="notes"
|
|
||||||
label={t("cash_shift.notes")}
|
|
||||||
placeholder={t("cash_shift.notes_placeholder")}
|
|
||||||
value={notes}
|
|
||||||
onChange={(e) => setNotes(e.target.value)}
|
|
||||||
isNotRequired
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex gap-3 mt-6">
|
|
||||||
<Button
|
|
||||||
label={t("cash_shift.cancel")}
|
|
||||||
type="button"
|
|
||||||
onClick={handleClose}
|
|
||||||
className="bg-gray-100 text-gray-700"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
label={t("cash_shift.save_changes")}
|
|
||||||
type="button"
|
|
||||||
onClick={handleSubmit}
|
|
||||||
isloading={updateShift.isPending}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</DefaulModal>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EditCashShiftModal;
|
|
||||||
@@ -3,7 +3,6 @@ import * as api from "../service/CashShiftService";
|
|||||||
import type {
|
import type {
|
||||||
CloseCashShiftPayload,
|
CloseCashShiftPayload,
|
||||||
OpenCashShiftPayload,
|
OpenCashShiftPayload,
|
||||||
UpdateCashShiftPayload,
|
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
import type { GetCashShiftsParams } from "../service/CashShiftService";
|
import type { GetCashShiftsParams } from "../service/CashShiftService";
|
||||||
|
|
||||||
@@ -65,17 +64,3 @@ export const useCloseCashShift = () => {
|
|||||||
onSuccess: () => invalidateCashShiftQueries(queryClient),
|
onSuccess: () => invalidateCashShiftQueries(queryClient),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUpdateCashShift = () => {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: ({
|
|
||||||
shiftId,
|
|
||||||
payload,
|
|
||||||
}: {
|
|
||||||
shiftId: string;
|
|
||||||
payload: UpdateCashShiftPayload;
|
|
||||||
}) => api.updateCashShift(shiftId, payload),
|
|
||||||
onSuccess: () => invalidateCashShiftQueries(queryClient),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import type {
|
|||||||
GetCashShiftsResponse,
|
GetCashShiftsResponse,
|
||||||
GetCashShiftSummaryResponse,
|
GetCashShiftSummaryResponse,
|
||||||
OpenCashShiftPayload,
|
OpenCashShiftPayload,
|
||||||
UpdateCashShiftPayload,
|
|
||||||
} from "../types/Types";
|
} from "../types/Types";
|
||||||
|
|
||||||
export interface GetCashShiftsParams {
|
export interface GetCashShiftsParams {
|
||||||
@@ -81,14 +80,3 @@ export const closeCashShift = async (
|
|||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateCashShift = async (
|
|
||||||
shiftId: string,
|
|
||||||
payload: UpdateCashShiftPayload
|
|
||||||
): Promise<GetCashShiftResponse> => {
|
|
||||||
const { data } = await axios.patch<GetCashShiftResponse>(
|
|
||||||
`/admin/cash-shifts/${shiftId}`,
|
|
||||||
payload
|
|
||||||
);
|
|
||||||
return data;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -58,8 +58,3 @@ export interface CloseCashShiftPayload {
|
|||||||
countedAmount: number;
|
countedAmount: number;
|
||||||
notes?: string;
|
notes?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateCashShiftPayload {
|
|
||||||
openingAmount?: number;
|
|
||||||
notes?: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import { DocumentDownload } from 'iconsax-react';
|
|||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import Filters from '@/components/Filters';
|
import Filters from '@/components/Filters';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
import PageLoading from '@/components/PageLoading';
|
||||||
|
import { usePermissions } from '@/hooks/usePermissions';
|
||||||
|
import { PermissionEnum } from '@/pages/roles/enum/Enum';
|
||||||
import { useGetDailyOrderReport } from './hooks/useDailyOrderReportData';
|
import { useGetDailyOrderReport } from './hooks/useDailyOrderReportData';
|
||||||
import { useDailyOrderReportFilters } from './hooks/useDailyOrderReportFilters';
|
import { useDailyOrderReportFilters } from './hooks/useDailyOrderReportFilters';
|
||||||
import { getDailyOrderReportTableColumns } from './components/DailyOrderReportTableColumns';
|
import { getDailyOrderReportTableColumns } from './components/DailyOrderReportTableColumns';
|
||||||
@@ -15,6 +18,7 @@ import type { RowDataType } from '@/components/types/TableTypes';
|
|||||||
|
|
||||||
const DailyOrderReport: FC = () => {
|
const DailyOrderReport: FC = () => {
|
||||||
const { t } = useTranslation('global');
|
const { t } = useTranslation('global');
|
||||||
|
const { checkPermission, isLoading: isPermissionsLoading } = usePermissions();
|
||||||
const { filters, apiParams, handleFiltersChange } = useDailyOrderReportFilters();
|
const { filters, apiParams, handleFiltersChange } = useDailyOrderReportFilters();
|
||||||
const { data: reportData, isLoading } = useGetDailyOrderReport(apiParams);
|
const { data: reportData, isLoading } = useGetDailyOrderReport(apiParams);
|
||||||
const [isExporting, setIsExporting] = useState(false);
|
const [isExporting, setIsExporting] = useState(false);
|
||||||
@@ -43,6 +47,18 @@ const DailyOrderReport: FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isPermissionsLoading) {
|
||||||
|
return <PageLoading />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkPermission(PermissionEnum.VIEW_ORDER_REPORTS)) {
|
||||||
|
return (
|
||||||
|
<div className='mt-5 text-sm text-gray-500'>
|
||||||
|
شما دسترسی مشاهده این گزارش را ندارید.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-5'>
|
<div className='mt-5'>
|
||||||
<div className='flex justify-between items-center'>
|
<div className='flex justify-between items-center'>
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ import { DocumentDownload } from 'iconsax-react';
|
|||||||
import Table from '@/components/Table';
|
import Table from '@/components/Table';
|
||||||
import Filters from '@/components/Filters';
|
import Filters from '@/components/Filters';
|
||||||
import Button from '@/components/Button';
|
import Button from '@/components/Button';
|
||||||
|
import PageLoading from '@/components/PageLoading';
|
||||||
|
import { usePermissions } from '@/hooks/usePermissions';
|
||||||
|
import { PermissionEnum } from '@/pages/roles/enum/Enum';
|
||||||
import { useGetFoodOrderReport } from './hooks/useFoodOrderReportData';
|
import { useGetFoodOrderReport } from './hooks/useFoodOrderReportData';
|
||||||
import { useFoodOrderReportFilters } from './hooks/useFoodOrderReportFilters';
|
import { useFoodOrderReportFilters } from './hooks/useFoodOrderReportFilters';
|
||||||
import { getFoodOrderReportTableColumns } from './components/FoodOrderReportTableColumns';
|
import { getFoodOrderReportTableColumns } from './components/FoodOrderReportTableColumns';
|
||||||
@@ -15,6 +18,7 @@ import type { RowDataType } from '@/components/types/TableTypes';
|
|||||||
|
|
||||||
const FoodOrderReport: FC = () => {
|
const FoodOrderReport: FC = () => {
|
||||||
const { t } = useTranslation('global');
|
const { t } = useTranslation('global');
|
||||||
|
const { checkPermission, isLoading: isPermissionsLoading } = usePermissions();
|
||||||
const { filters, apiParams, handleFiltersChange } = useFoodOrderReportFilters();
|
const { filters, apiParams, handleFiltersChange } = useFoodOrderReportFilters();
|
||||||
const { data: reportData, isLoading } = useGetFoodOrderReport(apiParams);
|
const { data: reportData, isLoading } = useGetFoodOrderReport(apiParams);
|
||||||
const [isExporting, setIsExporting] = useState(false);
|
const [isExporting, setIsExporting] = useState(false);
|
||||||
@@ -43,6 +47,18 @@ const FoodOrderReport: FC = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (isPermissionsLoading) {
|
||||||
|
return <PageLoading />;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checkPermission(PermissionEnum.VIEW_ORDER_REPORTS)) {
|
||||||
|
return (
|
||||||
|
<div className='mt-5 text-sm text-gray-500'>
|
||||||
|
شما دسترسی مشاهده این گزارش را ندارید.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-5'>
|
<div className='mt-5'>
|
||||||
<div className='flex justify-between items-center'>
|
<div className='flex justify-between items-center'>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { Link } from 'react-router-dom'
|
|||||||
import { Pages } from '@/config/Pages'
|
import { Pages } from '@/config/Pages'
|
||||||
import { formatFaNumber } from '@/helpers/func'
|
import { formatFaNumber } from '@/helpers/func'
|
||||||
import type { TFunction } from 'i18next'
|
import type { TFunction } from 'i18next'
|
||||||
|
import { PaymentStatusEnum } from '../enum/Enum'
|
||||||
|
|
||||||
interface GetOrderTableColumnsParams {
|
interface GetOrderTableColumnsParams {
|
||||||
onDelete?: (id: string) => void
|
onDelete?: (id: string) => void
|
||||||
@@ -27,6 +28,30 @@ const getStatusVariant = (status: string): 'success' | 'error' | 'warning' | 'in
|
|||||||
return variantMap[status] || 'pending'
|
return variantMap[status] || 'pending'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPaymentStatusVariant = (status: string): 'success' | 'error' | 'warning' | 'info' | 'pending' => {
|
||||||
|
const variantMap: Record<string, 'success' | 'error' | 'warning' | 'info' | 'pending'> = {
|
||||||
|
[PaymentStatusEnum.Paid]: 'success',
|
||||||
|
[PaymentStatusEnum.Pending]: 'warning',
|
||||||
|
[PaymentStatusEnum.Failed]: 'error',
|
||||||
|
[PaymentStatusEnum.Refunded]: 'info',
|
||||||
|
}
|
||||||
|
return variantMap[status] || 'pending'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPaymentStatusLabel = (status: string): string => {
|
||||||
|
const labelMap: Record<string, string> = {
|
||||||
|
[PaymentStatusEnum.Paid]: 'پرداخت شده',
|
||||||
|
[PaymentStatusEnum.Pending]: 'در انتظار پرداخت',
|
||||||
|
[PaymentStatusEnum.Failed]: 'پرداخت ناموفق',
|
||||||
|
[PaymentStatusEnum.Refunded]: 'بازگشت شده',
|
||||||
|
}
|
||||||
|
return labelMap[status] || '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
const resolvePaymentStatus = (item: Order): string | undefined => {
|
||||||
|
return item.paymentStatus || item.payments?.[0]?.status
|
||||||
|
}
|
||||||
|
|
||||||
export const getOrderTableColumns = ({ t }: GetOrderTableColumnsParams): ColumnType<Order>[] => {
|
export const getOrderTableColumns = ({ t }: GetOrderTableColumnsParams): ColumnType<Order>[] => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -78,6 +103,20 @@ export const getOrderTableColumns = ({ t }: GetOrderTableColumnsParams): ColumnT
|
|||||||
return item.paymentMethod?.description || '-'
|
return item.paymentMethod?.description || '-'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'paymentStatus',
|
||||||
|
title: 'وضعیت پرداخت',
|
||||||
|
render: (item: Order) => {
|
||||||
|
const paymentStatus = resolvePaymentStatus(item)
|
||||||
|
if (!paymentStatus) return '-'
|
||||||
|
return (
|
||||||
|
<Status
|
||||||
|
variant={getPaymentStatusVariant(paymentStatus)}
|
||||||
|
label={getPaymentStatusLabel(paymentStatus)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'status',
|
key: 'status',
|
||||||
title: 'وضعیت',
|
title: 'وضعیت',
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ export const enum PermissionEnum {
|
|||||||
|
|
||||||
// Order Management
|
// Order Management
|
||||||
MANAGE_ORDERS = "manage_orders",
|
MANAGE_ORDERS = "manage_orders",
|
||||||
|
VIEW_ORDER_REPORTS = "view_order_reports",
|
||||||
|
MANAGE_SHIFTS = "manage_shifts",
|
||||||
|
VIEW_ALL_SHIFTS = "view_all_shifts",
|
||||||
|
|
||||||
// User & Admin Management
|
// User & Admin Management
|
||||||
MANAGE_ADMINS = "manage_admins",
|
MANAGE_ADMINS = "manage_admins",
|
||||||
|
|||||||
@@ -102,12 +102,12 @@ const SideBar: FC = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{checkPermission(PermissionEnum.MANAGE_ORDERS) && (
|
{(checkPermission(PermissionEnum.MANAGE_ORDERS) || checkPermission(PermissionEnum.VIEW_ORDER_REPORTS)) && (
|
||||||
<SideBarItem
|
<SideBarItem
|
||||||
icon={<DocumentText variant={isActive('orders') ? 'Bold' : 'Outline'} color={isActive('orders') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
icon={<DocumentText variant={isActive('orders') ? 'Bold' : 'Outline'} color={isActive('orders') ? 'black' : '#8C90A3'} size={iconSizeSideBar} />}
|
||||||
title={t('sidebar.orders')}
|
title={t('sidebar.orders')}
|
||||||
isActive={isActive('orders')}
|
isActive={isActive('orders')}
|
||||||
link={Pages.orders.list}
|
link={checkPermission(PermissionEnum.MANAGE_ORDERS) ? Pages.orders.list : Pages.orders.foodReport}
|
||||||
name='orders'
|
name='orders'
|
||||||
activeName='orders'
|
activeName='orders'
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import SubMenuItem from './SubMenuItem'
|
import SubMenuItem from './SubMenuItem'
|
||||||
import { useLocation } from 'react-router-dom'
|
import { useLocation } from 'react-router-dom'
|
||||||
import { Pages } from '../../config/Pages'
|
import { Pages } from '../../config/Pages'
|
||||||
|
import { usePermissions } from '@/hooks/usePermissions'
|
||||||
|
import { PermissionEnum } from '@/pages/roles/enum/Enum'
|
||||||
|
|
||||||
const OrdersSubMenu: FC = () => {
|
const OrdersSubMenu: FC = () => {
|
||||||
|
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const { t } = useTranslation('global')
|
const { t } = useTranslation('global')
|
||||||
|
const { checkPermission } = usePermissions()
|
||||||
|
|
||||||
const isActive = (name: string) => {
|
const isActive = (name: string) => {
|
||||||
return location.pathname.includes(name)
|
return location.pathname.includes(name)
|
||||||
@@ -28,31 +31,41 @@ const OrdersSubMenu: FC = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-col mt-10 gap-4'>
|
<div className='flex flex-col mt-10 gap-4'>
|
||||||
<SubMenuItem
|
{checkPermission(PermissionEnum.MANAGE_ORDERS) && (
|
||||||
title={t('submenu.orders_list')}
|
<SubMenuItem
|
||||||
isActive={isActive('list')}
|
title={t('submenu.orders_list')}
|
||||||
link={Pages.orders.list}
|
isActive={isActive('list')}
|
||||||
/>
|
link={Pages.orders.list}
|
||||||
<SubMenuItem
|
/>
|
||||||
title={t('submenu.orders_food_report')}
|
)}
|
||||||
isActive={isActive('report/by-food')}
|
{checkPermission(PermissionEnum.VIEW_ORDER_REPORTS) && (
|
||||||
link={Pages.orders.foodReport}
|
<SubMenuItem
|
||||||
/>
|
title={t('submenu.orders_food_report')}
|
||||||
<SubMenuItem
|
isActive={isActive('report/by-food')}
|
||||||
title={t('submenu.orders_daily_report')}
|
link={Pages.orders.foodReport}
|
||||||
isActive={isActive('report/by-day')}
|
/>
|
||||||
link={Pages.orders.dailyReport}
|
)}
|
||||||
/>
|
{checkPermission(PermissionEnum.VIEW_ORDER_REPORTS) && (
|
||||||
<SubMenuItem
|
<SubMenuItem
|
||||||
title={t('submenu.cash_shifts')}
|
title={t('submenu.orders_daily_report')}
|
||||||
isActive={isActive('cash-shifts')}
|
isActive={isActive('report/by-day')}
|
||||||
link={Pages.orders.cashShifts}
|
link={Pages.orders.dailyReport}
|
||||||
/>
|
/>
|
||||||
<SubMenuItem
|
)}
|
||||||
title={t('submenu.add_order')}
|
{checkPermission(PermissionEnum.MANAGE_ORDERS) && (
|
||||||
isActive={isActive('add')}
|
<SubMenuItem
|
||||||
link={Pages.orders.add}
|
title={t('submenu.cash_shifts')}
|
||||||
/>
|
isActive={isActive('cash-shifts')}
|
||||||
|
link={Pages.orders.cashShifts}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{checkPermission(PermissionEnum.MANAGE_ORDERS) && (
|
||||||
|
<SubMenuItem
|
||||||
|
title={t('submenu.add_order')}
|
||||||
|
isActive={isActive('add')}
|
||||||
|
link={Pages.orders.add}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user