|
- "use client";
-
- import {
- Box,
- Card,
- CardContent,
- CardActions,
- Typography,
- CircularProgress,
- Grid,
- Chip,
- Button,
- TablePagination,
- } from "@mui/material";
- import { useCallback, useEffect, useMemo, useState } from "react";
- import { useTranslation } from "react-i18next";
- import {
- AllPickedStockTakeListReponse,
- getApproverStockTakeRecords,
- } from "@/app/api/stockTake/actions";
- import dayjs from "dayjs";
- import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
-
- const PER_PAGE = 6;
-
- interface ApproverAllCardListProps {
- onCardClick: (session: AllPickedStockTakeListReponse) => void;
- }
-
- const ApproverAllCardList: React.FC<ApproverAllCardListProps> = ({
- onCardClick,
- }) => {
- const { t } = useTranslation(["inventory", "common"]);
- const [loading, setLoading] = useState(false);
- const [sessions, setSessions] = useState<AllPickedStockTakeListReponse[]>([]);
- const [page, setPage] = useState(0);
-
- const fetchSessions = useCallback(async () => {
- setLoading(true);
- try {
- const data = await getApproverStockTakeRecords();
- const list = Array.isArray(data) ? data : [];
-
- // 找出最新一轮的 planStartDate
- const withPlanStart = list.filter((s) => s.planStartDate);
- if (withPlanStart.length === 0) {
- setSessions([]);
- setPage(0);
- return;
- }
-
- const latestPlanStart = withPlanStart
- .map((s) => s.planStartDate as string)
- .sort((a, b) => dayjs(b).valueOf() - dayjs(a).valueOf())[0];
-
- // 这一轮下所有 section 的卡片
- const roundSessions = list.filter((s) => s.planStartDate === latestPlanStart);
-
- // 汇总这一轮的总 item / lot 数
- const totalItems = roundSessions.reduce(
- (sum, s) => sum + (s.totalItemNumber || 0),
- 0
- );
- const totalLots = roundSessions.reduce(
- (sum, s) => sum + (s.totalInventoryLotNumber || 0),
- 0
- );
-
- // 用这一轮里的第一条作为代表,覆盖汇总数字
- const representative = roundSessions[0];
- const mergedRound: AllPickedStockTakeListReponse = {
- ...representative,
- totalItemNumber: totalItems,
- totalInventoryLotNumber: totalLots,
- };
-
- // UI 上只展示这一轮一张卡
- setSessions([mergedRound]);
- setPage(0);
- } catch (e) {
- console.error(e);
- setSessions([]);
- } finally {
- setLoading(false);
- }
- }, []);
-
- useEffect(() => {
- fetchSessions();
- }, [fetchSessions]);
-
- const getStatusColor = (status: string | null) => {
- if (!status) return "default";
- const statusLower = status.toLowerCase();
- if (statusLower === "completed") return "success";
- if (statusLower === "approving") return "info";
- return "warning";
- };
-
- const paged = useMemo(() => {
- const startIdx = page * PER_PAGE;
- return sessions.slice(startIdx, startIdx + PER_PAGE);
- }, [page, sessions]);
-
- if (loading) {
- return (
- <Box sx={{ display: "flex", justifyContent: "center", p: 3 }}>
- <CircularProgress />
- </Box>
- );
- }
-
- return (
- <Box>
-
-
- <Grid container spacing={2}>
- {paged.map((session) => {
- const statusColor = getStatusColor(session.status);
- const planStart = session.planStartDate
- ? dayjs(session.planStartDate).format(OUTPUT_DATE_FORMAT)
- : "-";
-
- return (
- <Grid key={session.stockTakeId} item xs={12} sm={6} md={4}>
- <Card
- sx={{
- minHeight: 180,
- display: "flex",
- flexDirection: "column",
- border: "1px solid",
- borderColor:
- statusColor === "success" ? "success.main" : "primary.main",
- cursor: "pointer",
- "&:hover": {
- boxShadow: 4,
- },
- }}
- onClick={() => onCardClick(session)}
- >
- <CardContent sx={{ pb: 1, flexGrow: 1 }}>
- <Typography variant="subtitle1" fontWeight={600} sx={{ mb: 0.5 }}>
- {t("Stock Take Round")}: {planStart}
- </Typography>
- <Typography variant="body2" color="text.secondary">
- {t("Plan Start Date")}: {planStart}
- </Typography>
- <Typography variant="body2" color="text.secondary">
- {t("Total Items")}: {session.totalItemNumber}
- </Typography>
- <Typography variant="body2" color="text.secondary">
- {t("Total Lots")}: {session.totalInventoryLotNumber}
- </Typography>
- </CardContent>
- <CardActions sx={{ pt: 0.5, justifyContent: "space-between" }}>
- <Button
- size="small"
- variant="contained"
- onClick={(e) => {
- e.stopPropagation();
- onCardClick(session);
- }}
- >
- {t("View Details")}
- </Button>
- {session.status ? (
- <Chip
- size="small"
- label={t(session.status)}
- color={statusColor as any}
- />
- ) : (
- <Chip size="small" label={t(" ")} color="default" />
- )}
- </CardActions>
- </Card>
- </Grid>
- );
- })}
- </Grid>
-
- {sessions.length > 0 && (
- <TablePagination
- component="div"
- count={sessions.length}
- page={page}
- rowsPerPage={PER_PAGE}
- onPageChange={(_, p) => setPage(p)}
- rowsPerPageOptions={[PER_PAGE]}
- />
- )}
- </Box>
- );
- };
-
- export default ApproverAllCardList;
|