working leantime widget 7

This commit is contained in:
Alma 2025-04-12 12:45:07 +02:00
parent aabe557fad
commit 928de78b13
2 changed files with 66 additions and 47 deletions

View File

@ -8,7 +8,7 @@ const userCache = new Map<string, number>();
export async function GET() { export async function GET() {
const session = await getServerSession(authOptions); const session = await getServerSession(authOptions);
if (!session) { if (!session || !session.user?.email) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
} }
@ -51,10 +51,12 @@ export async function GET() {
throw new Error('Could not find Leantime user ID'); throw new Error('Could not find Leantime user ID');
} }
leantimeUserId = userData.result.id; leantimeUserId = userData.result.id as number;
// Cache the user ID for 5 minutes // Cache the user ID for 5 minutes
userCache.set(session.user.email, leantimeUserId); if (session.user.email) {
setTimeout(() => userCache.delete(session.user.email), 5 * 60 * 1000); userCache.set(session.user.email, leantimeUserId);
setTimeout(() => userCache.delete(session.user.email!), 5 * 60 * 1000);
}
} }
// Now fetch the status labels // Now fetch the status labels
@ -108,19 +110,34 @@ export async function GET() {
return NextResponse.json({ statusLabels: [] }); return NextResponse.json({ statusLabels: [] });
} }
// Transform the nested status labels into a flat array // Create a map to store unique status labels
const transformedLabels = Object.entries(data.result).flatMap(([projectId, labels]) => { const uniqueLabels = new Map();
return Object.entries(labels).map(([id, label]: [string, any]) => ({
id, // Transform and deduplicate status labels
name: label.name, Object.entries(data.result as Record<string, Record<string, any>>).forEach(([projectId, labels]) => {
projectId, Object.entries(labels).forEach(([id, label]) => {
projectName: projectId, // You might want to fetch project names separately const key = label.name;
statusType: label.statusType, if (!uniqueLabels.has(key)) {
class: label.class, uniqueLabels.set(key, {
sortKey: label.sortKey id,
})); name: label.name,
statusType: label.statusType,
class: label.class,
sortKey: label.sortKey,
projects: []
});
}
uniqueLabels.get(key).projects.push({
id: projectId,
name: projectId // You might want to fetch project names separately
});
});
}); });
// Convert the map to an array and sort by sortKey
const transformedLabels = Array.from(uniqueLabels.values())
.sort((a, b) => (a.sortKey || '').localeCompare(b.sortKey || ''));
return NextResponse.json({ statusLabels: transformedLabels }); return NextResponse.json({ statusLabels: transformedLabels });
} catch (error) { } catch (error) {
console.error('Detailed error in status labels fetch:', error); console.error('Detailed error in status labels fetch:', error);

View File

@ -7,14 +7,18 @@ import { RefreshCw } from "lucide-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
interface Project {
id: string;
name: string;
}
interface StatusLabel { interface StatusLabel {
id: string; id: string;
name: string; name: string;
projectId: string;
projectName: string;
statusType: string; statusType: string;
class: string; class: string;
sortKey: string; sortKey: string;
projects: Project[];
} }
export function Flow() { export function Flow() {
@ -67,15 +71,6 @@ export function Flow() {
} }
}, [session]); }, [session]);
// Group status labels by project
const groupedLabels = statusLabels.reduce((acc, label) => {
if (!acc[label.projectId]) {
acc[label.projectId] = [];
}
acc[label.projectId].push(label);
return acc;
}, {} as Record<string, StatusLabel[]>);
return ( return (
<Card <Card
className="transition-transform duration-500 ease-in-out transform hover:scale-105 cursor-pointer bg-white/50 backdrop-blur-sm h-full" className="transition-transform duration-500 ease-in-out transform hover:scale-105 cursor-pointer bg-white/50 backdrop-blur-sm h-full"
@ -115,31 +110,38 @@ export function Flow() {
)} )}
{!loading && !error && ( {!loading && !error && (
<div className="space-y-4 max-h-[300px] overflow-y-auto"> <div className="space-y-4 max-h-[300px] overflow-y-auto">
{Object.entries(groupedLabels).length === 0 ? ( {statusLabels.length === 0 ? (
<p className="text-center text-muted-foreground">No status labels found</p> <p className="text-center text-muted-foreground">No status labels found</p>
) : ( ) : (
Object.entries(groupedLabels).map(([projectId, labels]) => ( <div className="space-y-2">
<div key={projectId} className="space-y-2"> {statusLabels.map((label) => (
<h3 className="text-sm font-medium text-gray-500">{projectId}</h3> <div
<div className="space-y-1"> key={label.id}
{labels.map((label) => ( className="flex items-start space-x-2 hover:bg-gray-50 p-2 rounded-lg transition-colors"
<div >
key={`${label.projectId}-${label.id}`} <div className="flex-1 min-w-0">
className="flex items-start space-x-2 hover:bg-gray-50 p-2 rounded-lg transition-colors" <div className="flex items-baseline justify-between">
> <p className="text-sm font-medium truncate">{label.name}</p>
<div className="flex-1 min-w-0"> <span className={`text-xs px-2 py-1 rounded ${label.class}`}>
<div className="flex items-baseline justify-between"> {label.statusType}
<p className="text-sm font-medium truncate">{label.name}</p> </span>
<span className={`text-xs px-2 py-1 rounded ${label.class}`}>
{label.statusType}
</span>
</div>
</div>
</div> </div>
))} {label.projects.length > 0 && (
<div className="mt-1 flex flex-wrap gap-1">
{label.projects.map((project) => (
<span
key={project.id}
className="text-xs bg-gray-100 text-gray-600 px-1.5 py-0.5 rounded"
>
{project.name}
</span>
))}
</div>
)}
</div>
</div> </div>
</div> ))}
)) </div>
)} )}
</div> </div>
)} )}