feat: Add project and user cards, implement settings and list view components, and update dependencies
This commit is contained in:
162
tasker-client/src/app/home/page.tsx
Normal file
162
tasker-client/src/app/home/page.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
"use client";
|
||||
|
||||
import {
|
||||
Priority,
|
||||
Project,
|
||||
Task,
|
||||
useGetProjectsQuery,
|
||||
useGetTasksQuery,
|
||||
} from "@/state/api";
|
||||
import React from "react";
|
||||
import { useAppSelector } from "../redux";
|
||||
import { DataGrid, GridColDef } from "@mui/x-data-grid";
|
||||
import Header from "@/app/components/Header";
|
||||
import {
|
||||
Bar,
|
||||
BarChart,
|
||||
CartesianGrid,
|
||||
Cell,
|
||||
Legend,
|
||||
Pie,
|
||||
PieChart,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
YAxis,
|
||||
} from "recharts";
|
||||
import { dataGridSxStyles } from "@/lib/utils";
|
||||
|
||||
const taskColumns: GridColDef[] = [
|
||||
{ field: "title", headerName: "Title", width: 200 },
|
||||
{ field: "status", headerName: "Status", width: 150 },
|
||||
{ field: "priority", headerName: "Priority", width: 150 },
|
||||
{ field: "dueDate", headerName: "Due Date", width: 150 },
|
||||
];
|
||||
|
||||
const statusColors = ["#0088FE", "#00C49F", "#FFBB28", "#FF8042"];
|
||||
|
||||
const HomePage = () => {
|
||||
const {
|
||||
data: tasks,
|
||||
isLoading: tasksLoading,
|
||||
isError: tasksError,
|
||||
} = useGetTasksQuery({ projectId: parseInt("1") });
|
||||
const { data: projects, isLoading: isProjectsLoading } =
|
||||
useGetProjectsQuery();
|
||||
|
||||
const isDarkMode = useAppSelector((state) => state.global.isDarkMode);
|
||||
|
||||
if (tasksLoading || isProjectsLoading) return <div>Loading..</div>;
|
||||
if (tasksError || !tasks || !projects) return <div>Error fetching data</div>;
|
||||
|
||||
const priorityCount = tasks.reduce(
|
||||
(acc: Record<string, number>, task: Task) => {
|
||||
const { priority } = task;
|
||||
acc[priority as Priority] = (acc[priority as Priority] || 0) + 1;
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const taskDistribution = Object.keys(priorityCount).map((key) => ({
|
||||
name: key,
|
||||
count: priorityCount[key],
|
||||
}));
|
||||
|
||||
const statusCount = projects.reduce(
|
||||
(acc: Record<string, number>, project: Project) => {
|
||||
const status = project.endDate ? "Completed" : "Active";
|
||||
acc[status] = (acc[status] || 0) + 1;
|
||||
return acc;
|
||||
},
|
||||
{},
|
||||
);
|
||||
|
||||
const projectStatus = Object.keys(statusCount).map((key) => ({
|
||||
name: key,
|
||||
count: statusCount[key],
|
||||
}));
|
||||
|
||||
const chartColors = isDarkMode
|
||||
? {
|
||||
bar: "#8884d8",
|
||||
barGrid: "#303030",
|
||||
pieFill: "#4A90E2",
|
||||
text: "#FFFFFF",
|
||||
}
|
||||
: {
|
||||
bar: "#8884d8",
|
||||
barGrid: "#E0E0E0",
|
||||
pieFill: "#82ca9d",
|
||||
text: "#000000",
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container h-full w-[100%] bg-gray-100 bg-transparent p-8">
|
||||
<Header name="Project Management Dashboard" />
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div className="rounded-lg bg-white p-4 shadow dark:bg-dark-secondary">
|
||||
<h3 className="mb-4 text-lg font-semibold dark:text-white">
|
||||
Task Priority Distribution
|
||||
</h3>
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<BarChart data={taskDistribution}>
|
||||
<CartesianGrid
|
||||
strokeDasharray="3 3"
|
||||
stroke={chartColors.barGrid}
|
||||
/>
|
||||
<XAxis dataKey="name" stroke={chartColors.text} />
|
||||
<YAxis stroke={chartColors.text} />
|
||||
<Tooltip
|
||||
contentStyle={{
|
||||
width: "min-content",
|
||||
height: "min-content",
|
||||
}}
|
||||
/>
|
||||
<Legend />
|
||||
<Bar dataKey="count" fill={chartColors.bar} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
<div className="rounded-lg bg-white p-4 shadow dark:bg-dark-secondary">
|
||||
<h3 className="mb-4 text-lg font-semibold dark:text-white">
|
||||
Project Status
|
||||
</h3>
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<PieChart>
|
||||
<Pie dataKey="count" data={projectStatus} fill="#82ca9d" label>
|
||||
{projectStatus.map((entry, index) => (
|
||||
<Cell
|
||||
key={`cell-${index}`}
|
||||
fill={statusColors[index % statusColors.length]}
|
||||
/>
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
</PieChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
<div className="rounded-lg bg-white p-4 shadow dark:bg-dark-secondary md:col-span-2">
|
||||
<h3 className="mb-4 text-lg font-semibold dark:text-white">
|
||||
Your Tasks
|
||||
</h3>
|
||||
<div style={{ height: 400, width: "100%" }}>
|
||||
<DataGrid
|
||||
rows={tasks}
|
||||
columns={taskColumns}
|
||||
checkboxSelection
|
||||
loading={tasksLoading}
|
||||
getRowClassName={() => "data-grid-row"}
|
||||
getCellClassName={() => "data-grid-cell"}
|
||||
className="border border-gray-200 bg-white shadow dark:border-stroke-dark dark:bg-dark-secondary dark:text-gray-200"
|
||||
sx={dataGridSxStyles(isDarkMode)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
Reference in New Issue
Block a user