From 85870601125d2ac48212c31e5533469fde08355d Mon Sep 17 00:00:00 2001 From: Alma Date: Sat, 12 Apr 2025 15:00:55 +0200 Subject: [PATCH] working leantime widget 45 --- app/api/leantime/tasks/route.ts | 11 ++- components/flow.tsx | 145 +++++++++++++++++++++----------- 2 files changed, 107 insertions(+), 49 deletions(-) diff --git a/app/api/leantime/tasks/route.ts b/app/api/leantime/tasks/route.ts index 40b4eb9f..dc537fa4 100644 --- a/app/api/leantime/tasks/route.ts +++ b/app/api/leantime/tasks/route.ts @@ -85,10 +85,19 @@ export async function GET(request: NextRequest) { projectId: task.projectId, status: task.status, dueDate: task.dateToFinish || null, - milestone: task.milestoneName || null, + milestone: task.type || null, details: task.description || null, + editTo: task.editTo || null, + dependingTicketId: task.dependingTicketId || null })); + // Sort tasks by due date + tasks.sort((a: any, b: any) => { + if (!a.dueDate) return 1; + if (!b.dueDate) return -1; + return new Date(a.dueDate).getTime() - new Date(b.dueDate).getTime(); + }); + return NextResponse.json({ tasks }); } catch (error) { console.error('Error in tasks route:', error); diff --git a/components/flow.tsx b/components/flow.tsx index 8a46e475..5dbc7ec5 100644 --- a/components/flow.tsx +++ b/components/flow.tsx @@ -3,7 +3,7 @@ import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { RefreshCw } from "lucide-react"; +import { RefreshCw, Calendar, MoreVertical } from "lucide-react"; interface Task { id: string; @@ -99,11 +99,11 @@ export function Flow() { }, []); const formatDate = (dateString: string | null) => { - if (!dateString) return 'No due date'; + if (!dateString) return ''; const date = new Date(dateString); - return date.toLocaleDateString('fr-FR', { - day: 'numeric', - month: 'short', + return date.toLocaleDateString('en-US', { + month: '2-digit', + day: '2-digit', year: 'numeric' }); }; @@ -111,32 +111,70 @@ export function Flow() { const getStatusInfo = (status: number): { label: string; className: string } => { switch (status) { case 1: - return { label: 'NEW', className: 'bg-blue-100 text-blue-800' }; + return { label: 'New', className: 'bg-blue-600 text-white' }; case 2: - return { label: 'IN PROGRESS', className: 'bg-yellow-100 text-yellow-800' }; + return { label: 'In Progress', className: 'bg-orange-400 text-white' }; case 3: - return { label: 'DONE', className: 'bg-green-100 text-green-800' }; + return { label: 'Done', className: 'bg-green-600 text-white' }; case 4: - return { label: 'BLOCKED', className: 'bg-red-100 text-red-800' }; - case 0: + return { label: 'Blocked', className: 'bg-red-600 text-white' }; + case 5: + return { label: 'In Review', className: 'bg-purple-600 text-white' }; + case 6: + return { label: 'To Be Validated', className: 'bg-yellow-600 text-white' }; default: - return { label: 'UNKNOWN', className: 'bg-gray-100 text-gray-800' }; + return { label: 'No Status', className: 'bg-gray-400 text-white' }; } }; + const getMilestoneInfo = (milestone: string | null): { label: string; className: string } => { + if (!milestone) return { label: 'No Milestone', className: 'bg-gray-200 text-gray-700' }; + + // Map milestone/type to display names + const milestoneMap: { [key: string]: string } = { + 'Marketing': 'Marketing', + 'Publication': 'Publication', + 'Development': 'Development', + 'Design': 'Design', + 'Research': 'Research' + }; + + return { + label: milestoneMap[milestone] || milestone, + className: 'bg-gray-200 text-gray-700' + }; + }; + + const isOverdue = (dueDate: string | null): boolean => { + if (!dueDate) return false; + const today = new Date(); + today.setHours(0, 0, 0, 0); + const taskDate = new Date(dueDate); + taskDate.setHours(0, 0, 0, 0); + return taskDate < today; + }; + return ( - Tasks - + My ToDos +
+ + + +
{loading ? ( @@ -148,39 +186,50 @@ export function Flow() { ) : projectTasks.length === 0 ? (
No tasks found
) : ( -
- {projectTasks.map((project) => ( -
-

{project.projectName}

-
- {project.tasks.map((task) => { - const statusInfo = getStatusInfo(task.status); - return ( -
-
- - {task.headline} - - {task.milestone && ( - - {task.milestone} +
+
+ 🔥 Overdue + ({projectTasks.reduce((count, project) => + count + project.tasks.filter(task => isOverdue(task.dueDate)).length, 0 + )}) +
+
+ {projectTasks.map((project) => ( + project.tasks.map((task) => { + const statusInfo = getStatusInfo(task.status); + const milestoneInfo = getMilestoneInfo(task.milestone); + if (!isOverdue(task.dueDate)) return null; + + return ( +
+
+
+
{project.projectName}
+
{task.headline}
+
+ + + {formatDate(task.dueDate)} - )} +
-
- +
+ + {milestoneInfo.label} + + {statusInfo.label} - - {formatDate(task.dueDate)} - +
- ); - })} -
-
- ))} +
+ ); + }) + ))} +
)}