diff --git a/src/app/dashboard/trust/disputes/page.tsx b/src/app/dashboard/trust/disputes/page.tsx new file mode 100644 index 0000000..bfa5e59 --- /dev/null +++ b/src/app/dashboard/trust/disputes/page.tsx @@ -0,0 +1,176 @@ +'use client'; + +import { useMemo, useState } from 'react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import Link from 'next/link'; +import { apiFetch } from '../../../lib/api'; +import { useSession } from '../../../components/session-provider'; + +interface Task { id: string; title: string; description: string | null; status: string; priority: string | null; tags: string[]; createdAt: string; } + +const DISPUTE_TAGS = ['dispute', 'disputa', 'conflict', 'litigiu', 'litigation', 'incident', 'complaint', 'reclamatie', 'reclamație']; +const RESOLUTION_STATUS: Record = { + todo: { label: 'Deschis', cls: 'bg-signal-danger/10 text-signal-danger' }, + in_progress: { label: 'În negociere', cls: 'bg-warn/10 text-warn' }, + review: { label: 'În revizie', cls: 'bg-primary/10 text-primary' }, + completed: { label: 'Rezolvat', cls: 'bg-signal-ok/10 text-signal-ok' }, + cancelled: { label: 'Abandonat', cls: 'bg-muted text-ink-faint' }, +}; + +export default function TrustDisputesPage() { + const { activeTenant } = useSession(); + const tenantId = activeTenant?.tenantId ?? ''; + const qc = useQueryClient(); + const [showAdd, setShowAdd] = useState(false); + const [form, setForm] = useState({ title: '', description: '', type: 'dispute', priority: 'normal' }); + + const { data: tasks = [], isLoading } = useQuery({ + queryKey: ['disputes', tenantId], + queryFn: () => apiFetch('/v1/tasks?limit=500', { tenantId }), + enabled: Boolean(tenantId), staleTime: 60_000, + }); + + const disputes = useMemo(() => + tasks.filter((t) => t.tags.some((tag) => DISPUTE_TAGS.includes(tag.toLowerCase()))) + .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()), + [tasks]); + + const open = disputes.filter((d) => !['completed', 'cancelled'].includes(d.status)); + + const createMut = useMutation({ + mutationFn: () => apiFetch('/v1/tasks', { tenantId, method: 'POST', body: { + title: form.title, description: form.description || undefined, + priority: form.priority, tags: [form.type, 'dispute'], status: 'todo', + }}), + onSuccess: () => { qc.invalidateQueries({ queryKey: ['disputes', tenantId] }); setShowAdd(false); setForm({ title: '', description: '', type: 'dispute', priority: 'normal' }); }, + }); + + const patchMut = useMutation({ + mutationFn: ({ id, status }: { id: string; status: string }) => + apiFetch(`/v1/tasks/${id}`, { tenantId, method: 'PATCH', body: { status } }), + onSuccess: () => qc.invalidateQueries({ queryKey: ['disputes', tenantId] }), + }); + + return ( +
+
+
+ +

Dispute & Incidente

+

+ {disputes.length} înregistrate · {open.length} deschise +

+
+ +
+ +
+

+ Confidențialitate: Înregistrările sunt stocate local în CEO OS și nu sunt partajate automat. + Documentează pentru uz propriu — consultă un jurist pentru situații cu implicații legale. +

+
+ + {open.length > 0 && ( +
+ ⚠️ +

{open.length} dispute/incidente deschise necesită atenție.

+
+ )} + + {showAdd && ( +
+

Incident / Dispută nouă

+
+ setForm((p) => ({ ...p, title: e.target.value }))} + className="rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring sm:col-span-2" /> + + +