You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

174 line
5.6 KiB

  1. import React, { useCallback, useState } from "react";
  2. import {
  3. Box,
  4. Card,
  5. CardContent,
  6. Grid,
  7. ToggleButton,
  8. ToggleButtonGroup,
  9. ToggleButtonProps,
  10. Tooltip,
  11. Typography,
  12. } from "@mui/material";
  13. import { useTranslation } from "react-i18next";
  14. import { manhourFormatter } from "@/app/utils/formatUtil";
  15. import { AssignedProject } from "@/app/api/projects";
  16. import { TableRows, ViewModule, TableChart } from "@mui/icons-material";
  17. import ProjectTable from "./ProjectTable";
  18. export interface Props {
  19. projects: AssignedProject[];
  20. maintainNormalStaffWorkspaceAbility?: boolean;
  21. maintainManagementStaffWorkspaceAbility?: boolean;
  22. }
  23. const ProjectGrid: React.FC<Props> = ({
  24. projects,
  25. maintainNormalStaffWorkspaceAbility,
  26. maintainManagementStaffWorkspaceAbility,
  27. }) => {
  28. const { t } = useTranslation("home");
  29. const [view, setView] = useState<"grid" | "list" | "table">("grid");
  30. const handleViewChange = useCallback<
  31. NonNullable<ToggleButtonProps["onChange"]>
  32. >((e, value) => {
  33. if (value) {
  34. setView(value);
  35. }
  36. }, []);
  37. return (
  38. <Box>
  39. <ToggleButtonGroup
  40. color="primary"
  41. value={view}
  42. exclusive
  43. onChange={handleViewChange}
  44. sx={{ marginBlockEnd: 2 }}
  45. >
  46. <ToggleButton value="grid">
  47. <Tooltip title={t("Grid view")}>
  48. <ViewModule />
  49. </Tooltip>
  50. </ToggleButton>
  51. <ToggleButton value="list">
  52. <Tooltip title={t("List view")}>
  53. <TableRows />
  54. </Tooltip>
  55. </ToggleButton>
  56. <ToggleButton value="table">
  57. <Tooltip title={t("Table view")}>
  58. <TableChart />
  59. </Tooltip>
  60. </ToggleButton>
  61. </ToggleButtonGroup>
  62. {view === "table" ? (
  63. <ProjectTable
  64. projects={projects}
  65. maintainManagementStaffWorkspaceAbility={
  66. maintainManagementStaffWorkspaceAbility
  67. }
  68. maintainNormalStaffWorkspaceAbility={
  69. maintainNormalStaffWorkspaceAbility
  70. }
  71. />
  72. ) : (
  73. <Grid
  74. container
  75. columns={view === "list" ? 4 : { xs: 4, sm: 8, md: 12, lg: 16 }}
  76. spacing={2}
  77. alignItems="stretch"
  78. >
  79. {projects.map((project, idx) => (
  80. <Grid key={`${project.code}${idx}`} item xs={4}>
  81. <Card sx={{ height: "100%" }}>
  82. <CardContent
  83. sx={{
  84. display: "flex",
  85. flexDirection: "column",
  86. height: "100%",
  87. }}
  88. >
  89. <Typography variant="overline">{project.code}</Typography>
  90. <Typography
  91. variant="h6"
  92. sx={{
  93. marginBlockEnd: 3,
  94. }}
  95. >
  96. {project.name}
  97. </Typography>
  98. {/* Spacer */}
  99. <Box sx={{ flex: 1 }} />
  100. {/* Hours Spent */}
  101. {(Boolean(maintainNormalStaffWorkspaceAbility) ||
  102. Boolean(maintainManagementStaffWorkspaceAbility)) && (
  103. <>
  104. <Typography variant="subtitle2">
  105. {t("Hours Spent:")}
  106. </Typography>
  107. <Box
  108. sx={{
  109. display: "flex",
  110. justifyContent: "space-between",
  111. alignItems: "baseline",
  112. }}
  113. >
  114. <Typography variant="caption">{t("Normal")}</Typography>
  115. <Typography>
  116. {manhourFormatter.format(
  117. Boolean(maintainManagementStaffWorkspaceAbility)
  118. ? project.hoursSpent
  119. : project.currentStaffHoursSpent,
  120. )}
  121. </Typography>
  122. </Box>
  123. <Box
  124. sx={{
  125. display: "flex",
  126. justifyContent: "space-between",
  127. alignItems: "baseline",
  128. }}
  129. >
  130. <Typography variant="caption">{t("Others")}</Typography>
  131. <Typography>{`${manhourFormatter.format(
  132. Boolean(maintainManagementStaffWorkspaceAbility)
  133. ? project.hoursSpentOther
  134. : project.currentStaffHoursSpentOther,
  135. )}`}</Typography>
  136. </Box>
  137. </>
  138. )}
  139. {/* Hours Allocated */}
  140. {Boolean(maintainManagementStaffWorkspaceAbility) && (
  141. <Box
  142. sx={{
  143. display: "flex",
  144. justifyContent: "space-between",
  145. alignItems: "baseline",
  146. }}
  147. >
  148. <Typography
  149. variant="subtitle2"
  150. sx={{ marginBlockStart: 2 }}
  151. >
  152. {t("Hours Allocated:")}
  153. </Typography>
  154. <Typography>
  155. {manhourFormatter.format(project.hoursAllocated)}
  156. </Typography>
  157. </Box>
  158. )}
  159. </CardContent>
  160. </Card>
  161. </Grid>
  162. ))}
  163. </Grid>
  164. )}
  165. </Box>
  166. );
  167. };
  168. export default ProjectGrid;