FPSMS-frontend
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 

184 líneas
5.5 KiB

  1. "use client";
  2. import { Box, Tab, Tabs, Snackbar, Alert, CircularProgress, Typography } from "@mui/material";
  3. import { useState, useCallback, useEffect } from "react";
  4. import { useTranslation } from "react-i18next";
  5. import { AllPickedStockTakeListReponse, getApproverStockTakeRecords } from "@/app/api/stockTake/actions";
  6. import PickerCardList from "./PickerCardList";
  7. import PickerStockTake from "./PickerStockTake";
  8. import PickerReStockTake from "./PickerReStockTake";
  9. import ApproverStockTakeAll from "./ApproverStockTakeAll";
  10. type ViewScope = "picker" | "approver-all";
  11. const StockTakeTab: React.FC = () => {
  12. const { t } = useTranslation(["inventory", "common"]);
  13. const [tabValue, setTabValue] = useState(0);
  14. const [selectedSession, setSelectedSession] = useState<AllPickedStockTakeListReponse | null>(null);
  15. const [viewMode, setViewMode] = useState<"details" | "reStockTake">("details");
  16. const [viewScope, setViewScope] = useState<ViewScope>("picker");
  17. const [approverSession, setApproverSession] = useState<AllPickedStockTakeListReponse | null>(null);
  18. const [approverLoading, setApproverLoading] = useState(false);
  19. const [snackbar, setSnackbar] = useState<{
  20. open: boolean;
  21. message: string;
  22. severity: "success" | "error" | "warning"
  23. }>({
  24. open: false,
  25. message: "",
  26. severity: "success",
  27. });
  28. const handleCardClick = useCallback((session: AllPickedStockTakeListReponse) => {
  29. setSelectedSession(session);
  30. setViewMode("details");
  31. }, []);
  32. const handleReStockTakeClick = useCallback((session: AllPickedStockTakeListReponse) => {
  33. setSelectedSession(session);
  34. setViewMode("reStockTake");
  35. setViewScope("picker");
  36. }, []);
  37. const handleBackToList = useCallback(() => {
  38. setSelectedSession(null);
  39. setViewMode("details");
  40. }, []);
  41. const handleSnackbar = useCallback((message: string, severity: "success" | "error" | "warning") => {
  42. setSnackbar({
  43. open: true,
  44. message,
  45. severity,
  46. });
  47. }, []);
  48. useEffect(() => {
  49. if (tabValue !== 1) return;
  50. setApproverLoading(true);
  51. getApproverStockTakeRecords()
  52. .then((records) => {
  53. const list = Array.isArray(records) ? records : [];
  54. setApproverSession(list[0] ?? null);
  55. })
  56. .catch((e) => {
  57. console.error(e);
  58. setApproverSession(null);
  59. })
  60. .finally(() => setApproverLoading(false));
  61. }, [tabValue]);
  62. if (selectedSession && viewScope === "picker") {
  63. return (
  64. <Box>
  65. {viewScope === "picker" && (
  66. tabValue === 0 ? (
  67. viewMode === "reStockTake" ? (
  68. <PickerReStockTake
  69. selectedSession={selectedSession}
  70. onBack={handleBackToList}
  71. onSnackbar={handleSnackbar}
  72. />
  73. ) : (
  74. <PickerStockTake
  75. selectedSession={selectedSession}
  76. onBack={handleBackToList}
  77. onSnackbar={handleSnackbar}
  78. />
  79. )
  80. ) : null
  81. )}
  82. <Snackbar
  83. open={snackbar.open}
  84. autoHideDuration={6000}
  85. onClose={() => setSnackbar({ ...snackbar, open: false })}
  86. >
  87. <Alert onClose={() => setSnackbar({ ...snackbar, open: false })} severity={snackbar.severity}>
  88. {snackbar.message}
  89. </Alert>
  90. </Snackbar>
  91. </Box>
  92. );
  93. }
  94. return (
  95. <Box>
  96. <Tabs
  97. value={tabValue}
  98. onChange={(e, newValue) => {
  99. setTabValue(newValue);
  100. if (newValue === 0) {
  101. setViewScope("picker");
  102. } else {
  103. setViewScope("approver-all");
  104. }
  105. }}
  106. sx={{ mb: 2 }}
  107. >
  108. <Tab label={t("Picker")} />
  109. <Tab label={t("Approver Pending")} />
  110. <Tab label={t("Approver Approved")} />
  111. </Tabs>
  112. {tabValue === 0 && (
  113. <PickerCardList
  114. onCardClick={(session) => {
  115. setViewScope("picker");
  116. handleCardClick(session);
  117. }}
  118. onReStockTakeClick={handleReStockTakeClick}
  119. />
  120. )}
  121. {tabValue === 1 && (
  122. <Box>
  123. {approverLoading ? (
  124. <Box sx={{ display: "flex", justifyContent: "center", p: 3 }}>
  125. <CircularProgress />
  126. </Box>
  127. ) : approverSession ? (
  128. <ApproverStockTakeAll
  129. selectedSession={approverSession}
  130. mode="pending"
  131. onSnackbar={handleSnackbar}
  132. />
  133. ) : (
  134. <Typography variant="body2" color="text.secondary">
  135. {t("No data")}
  136. </Typography>
  137. )}
  138. </Box>
  139. )}
  140. {tabValue === 2 && (
  141. <Box>
  142. {approverLoading ? (
  143. <Box sx={{ display: "flex", justifyContent: "center", p: 3 }}>
  144. <CircularProgress />
  145. </Box>
  146. ) : approverSession ? (
  147. <ApproverStockTakeAll
  148. selectedSession={approverSession}
  149. mode="approved"
  150. onSnackbar={handleSnackbar}
  151. />
  152. ) : (
  153. <Typography variant="body2" color="text.secondary">
  154. {t("No data")}
  155. </Typography>
  156. )}
  157. </Box>
  158. )}
  159. <Snackbar
  160. open={snackbar.open}
  161. autoHideDuration={6000}
  162. onClose={() => setSnackbar({ ...snackbar, open: false })}
  163. >
  164. <Alert onClose={() => setSnackbar({ ...snackbar, open: false })} severity={snackbar.severity}>
  165. {snackbar.message}
  166. </Alert>
  167. </Snackbar>
  168. </Box>
  169. );
  170. };
  171. export default StockTakeTab;