inspannings-monitor/components/planning/activity-suggestion-list.tsx

107 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { useMemo } from "react";
import type { ActivityCategory, ActivitySuggestion } from "@/lib/planning/types";
import { cn } from "@/lib/utils";
type ActivitySuggestionListProps = {
categories: ActivityCategory[];
suggestions: ActivitySuggestion[];
query: string;
disabled?: boolean;
showPriority?: boolean;
onSelect: (suggestion: ActivitySuggestion) => void;
};
function normalizeQuery(value: string) {
return value.trim().replace(/\s+/g, " ").toLocaleLowerCase("nl-NL");
}
function getCategoryLabel(categories: ActivityCategory[], categoryId: string) {
return categories.find((category) => category.id === categoryId)?.labelNl ?? "Onbekende categorie";
}
function formatImpactLabel(value: ActivitySuggestion["impactLevel"]) {
if (value === "laag") {
return "Lage impact";
}
if (value === "hoog") {
return "Hoge impact";
}
return "Middenimpact";
}
function formatPriorityLabel(value: ActivitySuggestion["priorityLevel"]) {
if (value === "laag") {
return "Lage prioriteit";
}
if (value === "hoog") {
return "Hoge prioriteit";
}
return "Normale prioriteit";
}
export function ActivitySuggestionList({
categories,
suggestions,
query,
disabled = false,
showPriority = true,
onSelect,
}: ActivitySuggestionListProps) {
const normalizedQuery = normalizeQuery(query);
const visibleSuggestions = useMemo(() => {
const filtered = normalizedQuery
? suggestions.filter((suggestion) =>
normalizeQuery(suggestion.name).includes(normalizedQuery),
)
: suggestions;
return filtered.slice(0, normalizedQuery ? 5 : 4);
}, [normalizedQuery, suggestions]);
if (visibleSuggestions.length === 0) {
if (!normalizedQuery) {
return null;
}
return (
<p className="text-sm leading-7 text-muted-foreground">
Geen eerdere match gevonden. Je kunt deze activiteit gewoon nieuw opslaan.
</p>
);
}
return (
<div className="space-y-2">
<p className="text-sm font-medium text-foreground">
{normalizedQuery ? "Vergelijkbare eerdere activiteiten" : "Snel hergebruiken"}
</p>
<div className="grid gap-2">
{visibleSuggestions.map((suggestion) => (
<button
key={suggestion.id}
type="button"
disabled={disabled}
onClick={() => onSelect(suggestion)}
className={cn(
"rounded-[1.1rem] border border-border/65 bg-background/78 px-4 py-3 text-left transition hover:border-primary/35 hover:bg-card disabled:pointer-events-none disabled:opacity-60",
)}
>
<span className="block text-sm font-semibold text-foreground">{suggestion.name}</span>
<span className="mt-1 block text-sm leading-6 text-muted-foreground">
{getCategoryLabel(categories, suggestion.categoryId)} · {suggestion.durationMinutes} min ·{" "}
{formatImpactLabel(suggestion.impactLevel)}
{showPriority ? ` · ${formatPriorityLabel(suggestion.priorityLevel)}` : ""}
{suggestion.useCount > 1 ? ` · ${suggestion.useCount}× gebruikt` : ""}
</span>
</button>
))}
</div>
</div>
);
}