Przeglądaj źródła

Add table view for user workspace

tags/Baseline_30082024_FRONTEND_UAT
Wayne 1 rok temu
rodzic
commit
be5b0f0778
2 zmienionych plików z 206 dodań i 82 usunięć
  1. +100
    -82
      src/components/UserWorkspacePage/ProjectGrid.tsx
  2. +106
    -0
      src/components/UserWorkspacePage/ProjectTable.tsx

+ 100
- 82
src/components/UserWorkspacePage/ProjectGrid.tsx Wyświetl plik

@@ -13,9 +13,10 @@ import {
import { useTranslation } from "react-i18next";
import { manhourFormatter } from "@/app/utils/formatUtil";
import { AssignedProject } from "@/app/api/projects";
import { ViewList, ViewModule } from "@mui/icons-material";
import { TableRows, ViewModule, TableChart } from "@mui/icons-material";
import ProjectTable from "./ProjectTable";

interface Props {
export interface Props {
projects: AssignedProject[];
maintainNormalStaffWorkspaceAbility?: boolean;
maintainManagementStaffWorkspaceAbility?: boolean;
@@ -27,7 +28,7 @@ const ProjectGrid: React.FC<Props> = ({
maintainManagementStaffWorkspaceAbility,
}) => {
const { t } = useTranslation("home");
const [view, setView] = useState<"grid" | "list">("grid");
const [view, setView] = useState<"grid" | "list" | "table">("grid");

const handleViewChange = useCallback<
NonNullable<ToggleButtonProps["onChange"]>
@@ -53,44 +54,94 @@ const ProjectGrid: React.FC<Props> = ({
</ToggleButton>
<ToggleButton value="list">
<Tooltip title={t("List view")}>
<ViewList />
<TableRows />
</Tooltip>
</ToggleButton>
<ToggleButton value="table">
<Tooltip title={t("Table view")}>
<TableChart />
</Tooltip>
</ToggleButton>
</ToggleButtonGroup>
<Grid
container
columns={view === "list" ? 4 : { xs: 4, sm: 8, md: 12, lg: 16 }}
spacing={2}
alignItems="stretch"
>
{projects.map((project, idx) => (
<Grid key={`${project.code}${idx}`} item xs={4}>
<Card sx={{ height: "100%" }}>
<CardContent
sx={{
display: "flex",
flexDirection: "column",
height: "100%",
}}
>
<Typography variant="overline">{project.code}</Typography>
<Typography
variant="h6"
{view === "table" ? (
<ProjectTable
projects={projects}
maintainManagementStaffWorkspaceAbility={
maintainManagementStaffWorkspaceAbility
}
maintainNormalStaffWorkspaceAbility={
maintainNormalStaffWorkspaceAbility
}
/>
) : (
<Grid
container
columns={view === "list" ? 4 : { xs: 4, sm: 8, md: 12, lg: 16 }}
spacing={2}
alignItems="stretch"
>
{projects.map((project, idx) => (
<Grid key={`${project.code}${idx}`} item xs={4}>
<Card sx={{ height: "100%" }}>
<CardContent
sx={{
marginBlockEnd: 3,
display: "flex",
flexDirection: "column",
height: "100%",
}}
>
{project.name}
</Typography>
{/* Spacer */}
<Box sx={{ flex: 1 }} />
{/* Hours Spent */}
{(Boolean(maintainNormalStaffWorkspaceAbility) ||
Boolean(maintainManagementStaffWorkspaceAbility)) && (
<>
<Typography variant="subtitle2">
{t("Hours Spent:")}
</Typography>
<Typography variant="overline">{project.code}</Typography>
<Typography
variant="h6"
sx={{
marginBlockEnd: 3,
}}
>
{project.name}
</Typography>
{/* Spacer */}
<Box sx={{ flex: 1 }} />
{/* Hours Spent */}
{(Boolean(maintainNormalStaffWorkspaceAbility) ||
Boolean(maintainManagementStaffWorkspaceAbility)) && (
<>
<Typography variant="subtitle2">
{t("Hours Spent:")}
</Typography>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<Typography variant="caption">{t("Normal")}</Typography>
<Typography>
{manhourFormatter.format(
Boolean(maintainManagementStaffWorkspaceAbility)
? project.hoursSpent
: project.currentStaffHoursSpent,
)}
</Typography>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<Typography variant="caption">{t("Others")}</Typography>
<Typography>{`${manhourFormatter.format(
Boolean(maintainManagementStaffWorkspaceAbility)
? project.hoursSpentOther
: project.currentStaffHoursSpentOther,
)}`}</Typography>
</Box>
</>
)}
{/* Hours Allocated */}
{Boolean(maintainManagementStaffWorkspaceAbility) && (
<Box
sx={{
display: "flex",
@@ -98,56 +149,23 @@ const ProjectGrid: React.FC<Props> = ({
alignItems: "baseline",
}}
>
<Typography variant="caption">{t("Normal")}</Typography>
<Typography
variant="subtitle2"
sx={{ marginBlockStart: 2 }}
>
{t("Hours Allocated:")}
</Typography>
<Typography>
{manhourFormatter.format(
Boolean(maintainManagementStaffWorkspaceAbility)
? project.hoursSpent
: project.currentStaffHoursSpent,
)}
{manhourFormatter.format(project.hoursAllocated)}
</Typography>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<Typography variant="caption">{t("Others")}</Typography>
<Typography>{`${manhourFormatter.format(
Boolean(maintainManagementStaffWorkspaceAbility)
? project.hoursSpentOther
: project.currentStaffHoursSpentOther,
)}`}</Typography>
</Box>
</>
)}
{/* Hours Allocated */}
{Boolean(maintainManagementStaffWorkspaceAbility) && (
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "baseline",
}}
>
<Typography
variant="subtitle2"
sx={{ marginBlockStart: 2 }}
>
{t("Hours Allocated:")}
</Typography>
<Typography>
{manhourFormatter.format(project.hoursAllocated)}
</Typography>
</Box>
)}
</CardContent>
</Card>
</Grid>
))}
</Grid>
)}
</CardContent>
</Card>
</Grid>
))}
</Grid>
)}
</Box>
);
};


+ 106
- 0
src/components/UserWorkspacePage/ProjectTable.tsx Wyświetl plik

@@ -0,0 +1,106 @@
import { useTranslation } from "react-i18next";
import { Props } from "./ProjectGrid";
import {
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
} from "@mui/material";
import { useMemo } from "react";
import { AssignedProject } from "@/app/api/projects";
import { manhourFormatter } from "@/app/utils/formatUtil";

interface Column {
name: keyof AssignedProject;
label: string;
}

const hourColumns: Array<keyof AssignedProject> = [
"currentStaffHoursSpent",
"currentStaffHoursSpentOther",
"hoursAllocated",
"hoursSpent",
"hoursSpentOther",
];

const ProjectTable: React.FC<Props> = ({
projects,
maintainManagementStaffWorkspaceAbility,
maintainNormalStaffWorkspaceAbility,
}) => {
const { t } = useTranslation("home");
const columns = useMemo<Column[]>(() => {
return [
{ name: "code", label: t("Project Code") },
{ name: "name", label: t("Project Name") },
...(maintainManagementStaffWorkspaceAbility ||
maintainNormalStaffWorkspaceAbility
? maintainManagementStaffWorkspaceAbility
? ([
{ name: "hoursSpent", label: t("Total Normal Hours Spent") },
{ name: "hoursSpentOther", label: t("Total Other Hours Spent") },
{ name: "hoursAllocated", label: t("Hours Allocated") },
] satisfies Column[])
: ([
{
name: "currentStaffHoursSpent",
label: t("Normal Hours Spent"),
},
{
name: "currentStaffHoursSpentOther",
label: t("Other Hours Spent"),
},
] satisfies Column[])
: []),
];
}, [
maintainManagementStaffWorkspaceAbility,
maintainNormalStaffWorkspaceAbility,
t,
]);

return (
<Paper sx={{ overflow: "hidden" }}>
<TableContainer>
<Table>
<TableHead>
<TableRow>
{columns.map((column, idx) => (
<TableCell key={`${column.name.toString()}-${idx}`}>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{projects.map((project) => {
return (
<TableRow hover tabIndex={-1} key={project.id}>
{columns.map((column, idx) => {
const columnName = column.name;
const needsFormatting = hourColumns.includes(columnName);

return (
<TableCell key={`${columnName.toString()}-${idx}`}>
{needsFormatting
? manhourFormatter.format(
project[columnName] as number,
)
: project[columnName]?.toString()}
</TableCell>
);
})}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
</Paper>
);
};

export default ProjectTable;

Ładowanie…
Anuluj
Zapisz