'use client' import { useState, useMemo } from 'react' import { Deadline, DeadlineType } from '@/types' import { Button } from '@/components/ui/button' import { DeadlineCard } from './DeadlineCard' import { DeadlineGroupCard, isSkattekontoDeadline } from './DeadlineGroupCard' import { DeadlineFilters } from './DeadlineFilters' import { DeadlineForm } from './DeadlineForm' import { isDeadlineOverdue } from '@/lib/calendar/utils' import { Plus, Lock } from 'lucide-react' import { useCanWrite } from '@/lib/hooks/use-can-write' interface DeadlineListProps { deadlines: Deadline[] customers: { id: string; name: string }[] onDeadlineCreate: (data: Omit) => Promise onDeadlineToggle: (deadline: Deadline) => Promise onDeadlineEdit: (deadline: Deadline) => Promise onDeadlineDelete: (deadline: Deadline) => Promise } export function DeadlineList({ deadlines, customers, onDeadlineCreate, onDeadlineToggle, onDeadlineEdit, onDeadlineDelete, }: DeadlineListProps) { const { canWrite } = useCanWrite() const [statusFilter, setStatusFilter] = useState<'all' | 'pending' | 'completed'>('pending') const [typeFilter, setTypeFilter] = useState('all') const [showForm, setShowForm] = useState(false) const [editingDeadline, setEditingDeadline] = useState(null) const filteredDeadlines = useMemo(() => { return deadlines.filter((d) => { if (statusFilter === 'pending' && d.is_completed) return false if (statusFilter === 'completed' && !d.is_completed) return false if (typeFilter !== 'all' && d.deadline_type !== typeFilter) return false return true }) }, [deadlines, statusFilter, typeFilter]) const groupedDeadlines = useMemo(() => { const today = new Date().toISOString().split('T')[0] const overdue: Deadline[] = [] const todayDeadlines: Deadline[] = [] const upcoming: Deadline[] = [] const completed: Deadline[] = [] for (const d of filteredDeadlines) { if (d.is_completed) { completed.push(d) } else if (isDeadlineOverdue(d)) { overdue.push(d) } else if (d.due_date === today) { todayDeadlines.push(d) } else { upcoming.push(d) } } return { overdue, today: todayDeadlines, upcoming, completed } }, [filteredDeadlines]) const handleResetFilters = () => { setStatusFilter('all') setTypeFilter('all') } const handleFormSubmit = async (data: Omit) => { if (editingDeadline) { await onDeadlineEdit({ ...editingDeadline, ...data }) } else { await onDeadlineCreate(data) } setShowForm(false) setEditingDeadline(null) } const handleEdit = (deadline: Deadline) => { setEditingDeadline(deadline) setShowForm(true) } const handleFormClose = () => { setShowForm(false) setEditingDeadline(null) } const sections = [ { key: 'overdue', label: 'Förfallna', items: groupedDeadlines.overdue }, { key: 'today', label: 'Idag', items: groupedDeadlines.today }, { key: 'upcoming', label: 'Kommande', items: groupedDeadlines.upcoming }, { key: 'completed', label: 'Klara', items: groupedDeadlines.completed }, ].filter(s => s.items.length > 0) // Skattekonto obligations legally share the same due date (moms + AGI + // preliminärskatt all fall on "den 12:e"): collapse 2+ such rows into one // grouped card per date instead of near-identical rows. Other deadlines // render as before, in their original order. type ListEntry = | { kind: 'single'; deadline: Deadline } | { kind: 'group'; date: string; items: Deadline[] } const toEntries = (items: Deadline[]): ListEntry[] => { const byDate = new Map() for (const d of items) { if (!isSkattekontoDeadline(d)) continue const group = byDate.get(d.due_date) ?? [] group.push(d) byDate.set(d.due_date, group) } const emittedDates = new Set() const entries: ListEntry[] = [] for (const d of items) { const group = byDate.get(d.due_date) if (isSkattekontoDeadline(d) && group && group.length >= 2) { if (!emittedDates.has(d.due_date)) { emittedDates.add(d.due_date) entries.push({ kind: 'group', date: d.due_date, items: group }) } continue } entries.push({ kind: 'single', deadline: d }) } return entries } return (
{/* Toolbar */}
{/* Content */} {filteredDeadlines.length === 0 ? (

{statusFilter !== 'all' || typeFilter !== 'all' ? 'Inga deadlines matchar filtret.' : 'Inga deadlines ännu.'}

) : (
{sections.map(({ key, label, items }) => (

{label}

{items.length}
{toEntries(items).map((entry) => entry.kind === 'group' ? ( ) : ( ), )}
))}
)} { if (deadline.id) { const full = deadlines.find(d => d.id === deadline.id) if (full) onDeadlineDelete(full) } }} initialData={editingDeadline || undefined} customers={customers} />
) }