working leantime widget 9

This commit is contained in:
Alma 2025-04-12 12:57:08 +02:00
parent d9208b489d
commit af09f37458
2 changed files with 48 additions and 62 deletions

View File

@ -107,38 +107,31 @@ export async function GET() {
if (!data.result) { if (!data.result) {
console.log('No result in Leantime response'); console.log('No result in Leantime response');
return NextResponse.json({ statusLabels: [] }); return NextResponse.json({ projects: [] });
} }
// Create a map to store unique status labels // Transform the response into a more structured format while maintaining project grouping
const uniqueLabels = new Map(); const transformedProjects = Object.entries(data.result as Record<string, Record<string, any>>).map(([projectId, labels]) => {
// Convert the labels object to an array and sort by sortKey
const sortedLabels = Object.entries(labels).map(([id, label]) => ({
id,
name: label.name,
statusType: label.statusType,
class: label.class,
sortKey: Number(label.sortKey) || 0,
kanbanCol: label.kanbanCol
})).sort((a, b) => a.sortKey - b.sortKey);
// Transform and deduplicate status labels return {
Object.entries(data.result as Record<string, Record<string, any>>).forEach(([projectId, labels]) => { projectId,
Object.entries(labels).forEach(([id, label]) => { labels: sortedLabels
const key = label.name; };
if (!uniqueLabels.has(key)) {
uniqueLabels.set(key, {
id,
name: label.name,
statusType: label.statusType,
class: label.class,
sortKey: Number(label.sortKey) || 0, // Convert to number, default to 0 if invalid
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 numerically // Sort projects by ID for consistency
const transformedLabels = Array.from(uniqueLabels.values()) transformedProjects.sort((a, b) => a.projectId.localeCompare(b.projectId));
.sort((a, b) => a.sortKey - b.sortKey);
return NextResponse.json({ statusLabels: transformedLabels }); return NextResponse.json({ projects: transformedProjects });
} catch (error) { } catch (error) {
console.error('Detailed error in status labels fetch:', error); console.error('Detailed error in status labels fetch:', error);
return NextResponse.json( return NextResponse.json(

View File

@ -7,22 +7,22 @@ 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;
statusType: string; statusType: string;
class: string; class: string;
sortKey: string; sortKey: number;
projects: Project[]; kanbanCol: boolean;
}
interface Project {
projectId: string;
labels: StatusLabel[];
} }
export function Flow() { export function Flow() {
const [statusLabels, setStatusLabels] = useState<StatusLabel[]>([]); const [projects, setProjects] = useState<Project[]>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
@ -50,7 +50,7 @@ export function Flow() {
} }
const data = await response.json(); const data = await response.json();
setStatusLabels(data.statusLabels); setProjects(data.projects);
setError(null); setError(null);
} catch (err) { } catch (err) {
console.error('Error fetching status labels:', err); console.error('Error fetching status labels:', err);
@ -110,38 +110,31 @@ 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">
{statusLabels.length === 0 ? ( {projects.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>
) : ( ) : (
<div className="space-y-2"> projects.map((project) => (
{statusLabels.map((label) => ( <div key={project.projectId} className="space-y-2">
<div <h3 className="text-sm font-medium text-gray-500">Project {project.projectId}</h3>
key={label.id} <div className="space-y-1">
className="flex items-start space-x-2 hover:bg-gray-50 p-2 rounded-lg transition-colors" {project.labels.map((label) => (
> <div
<div className="flex-1 min-w-0"> key={`${project.projectId}-${label.id}`}
<div className="flex items-baseline justify-between"> className="flex items-start space-x-2 hover:bg-gray-50 p-2 rounded-lg transition-colors"
<p className="text-sm font-medium truncate">{label.name}</p> >
<span className={`text-xs px-2 py-1 rounded ${label.class}`}> <div className="flex-1 min-w-0">
{label.statusType} <div className="flex items-baseline justify-between">
</span> <p className="text-sm font-medium truncate">{label.name}</p>
</div> <span className={`text-xs px-2 py-1 rounded ${label.class}`}>
{label.projects.length > 0 && ( {label.statusType}
<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> </span>
))} </div>
</div> </div>
)} </div>
</div> ))}
</div> </div>
))} </div>
</div> ))
)} )}
</div> </div>
)} )}