224 lines
7.3 KiB
TypeScript
224 lines
7.3 KiB
TypeScript
import { type FC, useMemo, useState } from "react";
|
|
import { useTranslation } from "react-i18next";
|
|
import { Add, Edit, Lock1 } from "iconsax-react";
|
|
import Table from "@/components/Table";
|
|
import Filters from "@/components/Filters";
|
|
import Button from "@/components/Button";
|
|
import type { RowDataType } from "@/components/types/TableTypes";
|
|
import {
|
|
useGetCashShifts,
|
|
useGetCurrentCashShift,
|
|
useGetCurrentCashShiftSummary,
|
|
} from "./hooks/useCashShiftData";
|
|
import { useCashShiftFilters } from "./hooks/useCashShiftFilters";
|
|
import { getCashShiftTableColumns } from "./components/CashShiftTableColumns";
|
|
import { useCashShiftFiltersFields } from "./components/CashShiftFiltersFields";
|
|
import CashShiftSummaryCard from "./components/CashShiftSummaryCard";
|
|
import OpenCashShiftModal from "./components/OpenCashShiftModal";
|
|
import CloseCashShiftModal from "./components/CloseCashShiftModal";
|
|
import EditCashShiftModal from "./components/EditCashShiftModal";
|
|
import CashShiftDetailModal from "./components/CashShiftDetailModal";
|
|
import type { CashShift } from "./types/Types";
|
|
import { CashShiftStatus } from "./enum/Enum";
|
|
import { formatOptionalDate } from "@/helpers/func";
|
|
import Status from "@/components/Status";
|
|
import MoonLoader from "react-spinners/MoonLoader";
|
|
|
|
const CashShiftsList: FC = () => {
|
|
const { t } = useTranslation("global");
|
|
const [isOpenModalVisible, setIsOpenModalVisible] = useState(false);
|
|
const [isCloseModalVisible, setIsCloseModalVisible] = useState(false);
|
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
|
const [isDetailModalVisible, setIsDetailModalVisible] = useState(false);
|
|
const [selectedShift, setSelectedShift] = useState<CashShift | null>(null);
|
|
|
|
const {
|
|
filters,
|
|
currentPage,
|
|
apiParams,
|
|
handleFiltersChange,
|
|
handlePageChange,
|
|
} = useCashShiftFilters();
|
|
|
|
const { data: shiftsData, isLoading } = useGetCashShifts(apiParams);
|
|
const { data: currentShiftData, isLoading: isCurrentShiftLoading } =
|
|
useGetCurrentCashShift();
|
|
|
|
const currentShift = currentShiftData?.data ?? null;
|
|
const hasOpenShift = currentShift?.status === CashShiftStatus.OPEN;
|
|
|
|
const { data: currentSummaryData, isLoading: isCurrentSummaryLoading } =
|
|
useGetCurrentCashShiftSummary(hasOpenShift);
|
|
|
|
const shifts = shiftsData?.data || [];
|
|
const totalPages = shiftsData?.meta?.totalPages || 1;
|
|
|
|
const columns = useMemo(
|
|
() =>
|
|
getCashShiftTableColumns({
|
|
t,
|
|
onView: (shift) => {
|
|
setSelectedShift(shift);
|
|
setIsDetailModalVisible(true);
|
|
},
|
|
onEdit: (shift) => {
|
|
setSelectedShift(shift);
|
|
setIsEditModalVisible(true);
|
|
},
|
|
onClose: (shift) => {
|
|
setSelectedShift(shift);
|
|
setIsCloseModalVisible(true);
|
|
},
|
|
}),
|
|
[t]
|
|
);
|
|
|
|
const filterFields = useCashShiftFiltersFields();
|
|
|
|
const getAdminName = (shift: CashShift) => {
|
|
const name = [shift.admin?.firstName, shift.admin?.lastName]
|
|
.filter(Boolean)
|
|
.join(" ");
|
|
return name || shift.admin?.phone || "-";
|
|
};
|
|
|
|
return (
|
|
<div className="mt-5">
|
|
<div className="flex justify-between items-center">
|
|
<h1 className="text-lg font-light">{t("cash_shift.list_title")}</h1>
|
|
{!hasOpenShift && (
|
|
<Button className="w-fit px-6" onClick={() => setIsOpenModalVisible(true)}>
|
|
<div className="flex gap-2 items-center">
|
|
<Add color="#fff" size={20} />
|
|
<span>{t("cash_shift.open_shift")}</span>
|
|
</div>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
{isCurrentShiftLoading ? (
|
|
<div className="mt-6 flex items-center gap-2">
|
|
<MoonLoader size={16} color="#000" />
|
|
</div>
|
|
) : (
|
|
hasOpenShift &&
|
|
currentShift && (
|
|
<div className="mt-6 bg-[#F5F5F5] rounded-2xl p-5 space-y-4">
|
|
<div className="flex flex-wrap justify-between items-start gap-4">
|
|
<div>
|
|
<div className="text-sm font-medium">
|
|
{t("cash_shift.current_shift")}
|
|
</div>
|
|
<div className="text-xs text-description mt-1">
|
|
{t("cash_shift.operator")}: {getAdminName(currentShift)}
|
|
</div>
|
|
<div className="text-xs text-description mt-1">
|
|
{t("cash_shift.opened_at")}:{" "}
|
|
{formatOptionalDate(currentShift.openedAt, {
|
|
year: "numeric",
|
|
month: "2-digit",
|
|
day: "2-digit",
|
|
hour: "2-digit",
|
|
minute: "2-digit",
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-3">
|
|
<Status
|
|
variant="warning"
|
|
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
|
|
className="w-fit px-5"
|
|
onClick={() => {
|
|
setSelectedShift(currentShift);
|
|
setIsCloseModalVisible(true);
|
|
}}
|
|
>
|
|
<div className="flex gap-2 items-center">
|
|
<Lock1 color="#fff" size={18} />
|
|
<span>{t("cash_shift.close_shift")}</span>
|
|
</div>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
|
|
<CashShiftSummaryCard
|
|
summary={currentSummaryData?.data}
|
|
openingAmount={currentShift.openingAmount}
|
|
isLoading={isCurrentSummaryLoading}
|
|
/>
|
|
</div>
|
|
)
|
|
)}
|
|
|
|
<div className="mt-8">
|
|
<Filters
|
|
fields={filterFields}
|
|
onChange={handleFiltersChange}
|
|
initialValues={filters}
|
|
showClearButton
|
|
/>
|
|
</div>
|
|
|
|
<Table<CashShift & RowDataType>
|
|
columns={columns}
|
|
data={shifts as (CashShift & RowDataType)[]}
|
|
isloading={isLoading}
|
|
pagination={{
|
|
currentPage,
|
|
totalPages,
|
|
onPageChange: handlePageChange,
|
|
}}
|
|
/>
|
|
|
|
<OpenCashShiftModal
|
|
open={isOpenModalVisible}
|
|
onClose={() => setIsOpenModalVisible(false)}
|
|
/>
|
|
|
|
<CloseCashShiftModal
|
|
open={isCloseModalVisible}
|
|
onClose={() => {
|
|
setIsCloseModalVisible(false);
|
|
setSelectedShift(null);
|
|
}}
|
|
shift={selectedShift}
|
|
/>
|
|
|
|
<EditCashShiftModal
|
|
open={isEditModalVisible}
|
|
onClose={() => {
|
|
setIsEditModalVisible(false);
|
|
setSelectedShift(null);
|
|
}}
|
|
shift={selectedShift}
|
|
/>
|
|
|
|
<CashShiftDetailModal
|
|
open={isDetailModalVisible}
|
|
onClose={() => {
|
|
setIsDetailModalVisible(false);
|
|
setSelectedShift(null);
|
|
}}
|
|
shift={selectedShift}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CashShiftsList;
|