This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user