From 7c8f64a716186249e925e2237fe1656485c63b84 Mon Sep 17 00:00:00 2001 From: Alma Date: Sat, 12 Apr 2025 12:29:34 +0200 Subject: [PATCH] working leantime widget --- app/api/leantime/status-labels/route.ts | 47 ++++++++++++++ components/flow.tsx | 85 ++++++++----------------- 2 files changed, 72 insertions(+), 60 deletions(-) create mode 100644 app/api/leantime/status-labels/route.ts diff --git a/app/api/leantime/status-labels/route.ts b/app/api/leantime/status-labels/route.ts new file mode 100644 index 00000000..4129daac --- /dev/null +++ b/app/api/leantime/status-labels/route.ts @@ -0,0 +1,47 @@ +import { getServerSession } from "next-auth/next"; +import { authOptions } from "@/app/api/auth/[...nextauth]/route"; +import { NextResponse } from "next/server"; + +export async function GET() { + const session = await getServerSession(authOptions); + + if (!session) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } + + try { + const response = await fetch('https://agilite.slm-lab.net/api/jsonrpc', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': process.env.LEANTIME_TOKEN || '', + }, + body: JSON.stringify({ + method: 'leantime.rpc.Tickets.Tickets.getAllStatusLabelsByUserId', + jsonrpc: '2.0', + id: 1, + params: { + userId: session.user.id, + } + }) + }); + + if (!response.ok) { + throw new Error('Failed to fetch status labels from Leantime'); + } + + const data = await response.json(); + + if (!data.result) { + return NextResponse.json({ statusLabels: [] }); + } + + return NextResponse.json({ statusLabels: data.result }); + } catch (error) { + console.error('Error fetching status labels:', error); + return NextResponse.json( + { error: "Failed to fetch status labels" }, + { status: 500 } + ); + } +} \ No newline at end of file diff --git a/components/flow.tsx b/components/flow.tsx index 573e6eef..3abb8184 100644 --- a/components/flow.tsx +++ b/components/flow.tsx @@ -3,33 +3,31 @@ import { useEffect, useState } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { RefreshCw, Calendar, CheckCircle2, Clock } from "lucide-react"; +import { RefreshCw } from "lucide-react"; import { useRouter } from "next/navigation"; import { useSession } from "next-auth/react"; -interface Task { +interface StatusLabel { id: string; - headline: string; - description: string; - status: string; - dueDate: string; - priority: number; + name: string; + projectId: string; + projectName: string; } export function Flow() { - const [tasks, setTasks] = useState([]); + const [statusLabels, setStatusLabels] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [refreshing, setRefreshing] = useState(false); const router = useRouter(); const { data: session } = useSession(); - const fetchTasks = async (isRefresh = false) => { + const fetchStatusLabels = async (isRefresh = false) => { try { if (isRefresh) { setRefreshing(true); } - const response = await fetch('/api/leantime/tasks', { + const response = await fetch('/api/leantime/status-labels', { cache: 'no-store', next: { revalidate: 0 }, }); @@ -41,15 +39,15 @@ export function Flow() { if (!response.ok) { const errorData = await response.json(); - throw new Error(errorData.error || 'Failed to fetch tasks'); + throw new Error(errorData.error || 'Failed to fetch status labels'); } const data = await response.json(); - setTasks(data.tasks); + setStatusLabels(data.statusLabels); setError(null); } catch (err) { - console.error('Error fetching tasks:', err); - const errorMessage = err instanceof Error ? err.message : 'Failed to fetch tasks'; + console.error('Error fetching status labels:', err); + const errorMessage = err instanceof Error ? err.message : 'Failed to fetch status labels'; setError(errorMessage); } finally { setLoading(false); @@ -59,50 +57,26 @@ export function Flow() { useEffect(() => { if (session) { - fetchTasks(); + fetchStatusLabels(); // Set up polling every 5 minutes - const interval = setInterval(() => fetchTasks(), 300000); + const interval = setInterval(() => fetchStatusLabels(), 300000); return () => clearInterval(interval); } }, [session]); - const getPriorityColor = (priority: number) => { - switch (priority) { - case 1: - return 'text-red-500'; - case 2: - return 'text-yellow-500'; - case 3: - return 'text-green-500'; - default: - return 'text-gray-500'; - } - }; - - const getStatusIcon = (status: string) => { - switch (status.toLowerCase()) { - case 'done': - return ; - case 'in progress': - return ; - default: - return ; - } - }; - return ( router.push('/flow')} > - My Tasks + Flow - {loading &&

Loading tasks...

} + {loading &&

Loading status labels...

} {error && (

Error: {error}

@@ -119,7 +93,7 @@ export function Flow() { variant="outline" onClick={(e) => { e.stopPropagation(); - fetchTasks(true); + fetchStatusLabels(true); }} className="mt-2" > @@ -129,30 +103,21 @@ export function Flow() { )} {!loading && !error && (
- {tasks.length === 0 ? ( -

No tasks found

+ {statusLabels.length === 0 ? ( +

No status labels found

) : ( - tasks.map((task) => ( + statusLabels.map((label) => (
-
- {getStatusIcon(task.status)} -
-

{task.headline}

- - {task.priority === 1 ? 'High' : task.priority === 2 ? 'Medium' : 'Low'} +

{label.name}

+ + {label.projectName}
-

{task.description}

- {task.dueDate && ( -

- Due: {new Date(task.dueDate).toLocaleDateString()} -

- )}
))