first commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"use client";
|
||||
|
||||
import { getAllSchedulesApi } from "@/app/utils/api/projectApi";
|
||||
import { Card } from "ikoncomponents";
|
||||
import { useEffect, useState, useMemo } from "react";
|
||||
|
||||
interface Task {
|
||||
id: number;
|
||||
taskName: string;
|
||||
taskDescription: string;
|
||||
taskStart: string;
|
||||
taskEnd: string;
|
||||
milestoneTask: boolean;
|
||||
}
|
||||
|
||||
export default function CurrentMonthMilestones() {
|
||||
const [apiTasks, setApiTasks] = useState<Task[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchScheduleData = async () => {
|
||||
try {
|
||||
const response = await getAllSchedulesApi();
|
||||
// Flatten all nested task arrays across every project in the response
|
||||
const allTasks = response.flatMap((project: any) => project.task || []);
|
||||
setApiTasks(allTasks);
|
||||
} catch (error) {
|
||||
console.error("Error fetching schedule data:", error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchScheduleData();
|
||||
}, []);
|
||||
|
||||
const visibleMilestones = useMemo(() => {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
|
||||
return (
|
||||
apiTasks
|
||||
.filter((task) => {
|
||||
// 1. Must be a milestone task
|
||||
const isMilestone = task.milestoneTask === true;
|
||||
|
||||
// 2. Must be today or a future date
|
||||
const taskStartDate = new Date(task.taskStart);
|
||||
taskStartDate.setHours(0, 0, 0, 0);
|
||||
const isTodayOrFuture = taskStartDate >= today;
|
||||
|
||||
return isMilestone && isTodayOrFuture;
|
||||
})
|
||||
// 3. Keep exactly the top 3 items
|
||||
.slice(0, 3)
|
||||
);
|
||||
}, [apiTasks]);
|
||||
|
||||
return (
|
||||
<Card className="p-4 h-127">
|
||||
<div className="max-w-3xl rounded-2xl p-3 shadow-sm h-full flex flex-col">
|
||||
<h1 className="mb-4 text-xl font-bold flex-shrink-0">
|
||||
Current Month Milestones
|
||||
</h1>
|
||||
|
||||
<div className="space-y-4 flex-grow flex flex-col justify-center items-center">
|
||||
{visibleMilestones.length === 0 ? (
|
||||
<p className="text-sm text-muted-foreground italic p-4 text-center">
|
||||
No milestone tasks scheduled for this period.
|
||||
</p>
|
||||
) : (
|
||||
<div className="w-full space-y-4 flex-grow justify-start">
|
||||
{visibleMilestones.map((task, index) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="rounded-xl border border-border bg-card p-4 shadow-sm"
|
||||
>
|
||||
{/* Index and Task Name */}
|
||||
<h2 className="text-lg font-semibold flex items-center gap-2">
|
||||
<span className="text-muted-foreground">{index + 1}.</span>
|
||||
{task.taskName}
|
||||
</h2>
|
||||
|
||||
{/* Description Block */}
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
{task.taskDescription || "No description provided."}
|
||||
</p>
|
||||
|
||||
{/* Dates in a Separate Line Below */}
|
||||
<div className="mt-3 pt-3 border-t border-border/50 flex items-center gap-6 text-xs text-muted-foreground">
|
||||
<div>
|
||||
<span className="font-medium text-foreground">
|
||||
Start:
|
||||
</span>{" "}
|
||||
{task.taskStart}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span className="font-medium text-foreground">End:</span>{" "}
|
||||
{task.taskEnd}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user