548 lines
23 KiB
TypeScript
548 lines
23 KiB
TypeScript
import { useState } from 'react'
|
|
import { useParams, useNavigate } from 'react-router-dom'
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
import {
|
|
ArrowLeft,
|
|
FolderOpen,
|
|
FolderCheck,
|
|
FolderArchive,
|
|
MessageSquare,
|
|
Calendar,
|
|
Pencil,
|
|
Trash2,
|
|
Plus,
|
|
X,
|
|
Search,
|
|
Inbox,
|
|
Send,
|
|
ExternalLink,
|
|
AlertTriangle,
|
|
CheckCircle2,
|
|
} from 'lucide-react'
|
|
import toast from 'react-hot-toast'
|
|
import { Button } from '@/components/ui/Button'
|
|
import { Input } from '@/components/ui/Input'
|
|
import { Label } from '@/components/ui/Label'
|
|
import {
|
|
fascicoliApi,
|
|
type FascicoloResponse,
|
|
type FascicoloMessageItem,
|
|
type FascicoloUpdate,
|
|
} from '@/api/fascicoli.api'
|
|
import { messagesApi } from '@/api/messages.api'
|
|
import { formatDate } from '@/lib/utils'
|
|
import { getErrorMessage } from '@/api/client'
|
|
import { useAuth } from '@/hooks/useAuth'
|
|
import { PecStateBadge } from '@/components/PecBadge/PecBadge'
|
|
|
|
// ─── Badge stato ──────────────────────────────────────────────────────────────
|
|
|
|
function StatoBadge({ stato }: { stato: FascicoloResponse['stato'] }) {
|
|
const config: Record<string, { label: string; className: string }> = {
|
|
aperto: { label: 'Aperto', className: 'bg-green-100 text-green-800 border border-green-200' },
|
|
chiuso: { label: 'Chiuso', className: 'bg-gray-100 text-gray-700 border border-gray-200' },
|
|
archiviato: { label: 'Archiviato', className: 'bg-amber-100 text-amber-800 border border-amber-200' },
|
|
}
|
|
const { label, className } = config[stato] ?? config.aperto
|
|
return (
|
|
<span className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${className}`}>
|
|
{label}
|
|
</span>
|
|
)
|
|
}
|
|
|
|
// ─── Dialog modifica fascicolo ────────────────────────────────────────────────
|
|
|
|
interface EditDialogProps {
|
|
fascicolo: FascicoloResponse
|
|
onClose: () => void
|
|
}
|
|
|
|
function EditDialog({ fascicolo, onClose }: EditDialogProps) {
|
|
const queryClient = useQueryClient()
|
|
const [form, setForm] = useState<FascicoloUpdate & { stato: 'aperto' | 'chiuso' | 'archiviato' }>({
|
|
titolo: fascicolo.titolo,
|
|
numero_pratica: fascicolo.numero_pratica ?? '',
|
|
stato: fascicolo.stato,
|
|
categoria: fascicolo.categoria ?? '',
|
|
scadenza: fascicolo.scadenza ? fascicolo.scadenza.substring(0, 16) : '',
|
|
note: fascicolo.note ?? '',
|
|
})
|
|
|
|
const updateMutation = useMutation({
|
|
mutationFn: (data: FascicoloUpdate) => fascicoliApi.update(fascicolo.id, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['fascicolo', fascicolo.id] })
|
|
queryClient.invalidateQueries({ queryKey: ['fascicoli'] })
|
|
toast.success('Fascicolo aggiornato')
|
|
onClose()
|
|
},
|
|
onError: (e) => toast.error(getErrorMessage(e)),
|
|
})
|
|
|
|
const handleSubmit = () => {
|
|
if (!form.titolo?.trim()) { toast.error('Il titolo e obbligatorio'); return }
|
|
updateMutation.mutate({
|
|
titolo: form.titolo?.trim(),
|
|
numero_pratica: (form.numero_pratica as string)?.trim() || null,
|
|
stato: form.stato,
|
|
categoria: (form.categoria as string)?.trim() || null,
|
|
scadenza: form.scadenza ? new Date(form.scadenza as string).toISOString() : null,
|
|
note: (form.note as string)?.trim() || null,
|
|
})
|
|
}
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
|
<div className="bg-background rounded-xl shadow-2xl w-full max-w-lg">
|
|
<div className="flex items-center justify-between px-5 py-4 border-b">
|
|
<h3 className="text-lg font-semibold">Modifica fascicolo</h3>
|
|
<button onClick={onClose} className="p-1 rounded hover:bg-muted"><X className="h-5 w-5" /></button>
|
|
</div>
|
|
<div className="px-5 py-4 space-y-4">
|
|
<div className="space-y-1">
|
|
<Label>Titolo *</Label>
|
|
<Input value={form.titolo ?? ''} onChange={(e) => setForm((f) => ({ ...f, titolo: e.target.value }))} autoFocus />
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div className="space-y-1">
|
|
<Label>Numero pratica</Label>
|
|
<Input value={form.numero_pratica as string ?? ''} onChange={(e) => setForm((f) => ({ ...f, numero_pratica: e.target.value }))} placeholder="Es. 2024/0042" />
|
|
</div>
|
|
<div className="space-y-1">
|
|
<Label>Stato</Label>
|
|
<select value={form.stato} onChange={(e) => setForm((f) => ({ ...f, stato: e.target.value as typeof form.stato }))}
|
|
className="w-full h-9 rounded-md border border-input bg-background px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-ring">
|
|
<option value="aperto">Aperto</option>
|
|
<option value="chiuso">Chiuso</option>
|
|
<option value="archiviato">Archiviato</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div className="space-y-1">
|
|
<Label>Categoria</Label>
|
|
<Input value={form.categoria as string ?? ''} onChange={(e) => setForm((f) => ({ ...f, categoria: e.target.value }))} />
|
|
</div>
|
|
<div className="space-y-1">
|
|
<Label>Scadenza</Label>
|
|
<Input type="datetime-local" value={form.scadenza as string ?? ''} onChange={(e) => setForm((f) => ({ ...f, scadenza: e.target.value }))} />
|
|
</div>
|
|
</div>
|
|
<div className="space-y-1">
|
|
<Label>Note</Label>
|
|
<textarea value={form.note as string ?? ''} onChange={(e) => setForm((f) => ({ ...f, note: e.target.value }))} rows={3}
|
|
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring resize-none" />
|
|
</div>
|
|
</div>
|
|
<div className="flex justify-end gap-3 px-5 py-4 border-t">
|
|
<Button variant="outline" onClick={onClose}>Annulla</Button>
|
|
<Button onClick={handleSubmit} isLoading={updateMutation.isPending}>Salva modifiche</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// ─── Modal selezione messaggi da aggiungere ───────────────────────────────────
|
|
|
|
interface AddMessagesModalProps {
|
|
fascicoloId: string
|
|
existingIds: Set<string>
|
|
onClose: () => void
|
|
}
|
|
|
|
function AddMessagesModal({ fascicoloId, existingIds, onClose }: AddMessagesModalProps) {
|
|
const queryClient = useQueryClient()
|
|
const [search, setSearch] = useState('')
|
|
const [selected, setSelected] = useState<Set<string>>(new Set())
|
|
|
|
const { data: messages = [] } = useQuery({
|
|
queryKey: ['messages-for-fascicolo', search],
|
|
queryFn: async () => {
|
|
// Carica messaggi recenti (non gia' nel fascicolo)
|
|
const params: Record<string, string | number> = { page: 1, page_size: 50, direction: 'all' }
|
|
if (search) params.search = search
|
|
const result = await messagesApi.list(params)
|
|
const items = (result as any).items ?? result
|
|
return items.filter((m: { id: string }) => !existingIds.has(m.id))
|
|
},
|
|
})
|
|
|
|
const addMutation = useMutation({
|
|
mutationFn: () => fascicoliApi.addMessages(fascicoloId, Array.from(selected)),
|
|
onSuccess: (data) => {
|
|
queryClient.invalidateQueries({ queryKey: ['fascicolo', fascicoloId] })
|
|
queryClient.invalidateQueries({ queryKey: ['fascicolo-messages', fascicoloId] })
|
|
queryClient.invalidateQueries({ queryKey: ['fascicoli'] })
|
|
toast.success(`${data.added} messaggi aggiunti al fascicolo`)
|
|
onClose()
|
|
},
|
|
onError: (e) => toast.error(getErrorMessage(e)),
|
|
})
|
|
|
|
const toggleSelect = (id: string) => {
|
|
setSelected((prev) => {
|
|
const next = new Set(prev)
|
|
if (next.has(id)) next.delete(id)
|
|
else next.add(id)
|
|
return next
|
|
})
|
|
}
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60">
|
|
<div className="bg-background rounded-xl shadow-2xl w-full max-w-2xl flex flex-col max-h-[80vh]">
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between px-5 py-4 border-b flex-shrink-0">
|
|
<h3 className="text-lg font-semibold flex items-center gap-2">
|
|
<Plus className="h-5 w-5 text-primary" />
|
|
Aggiungi messaggi al fascicolo
|
|
</h3>
|
|
<button onClick={onClose} className="p-1 rounded hover:bg-muted"><X className="h-5 w-5" /></button>
|
|
</div>
|
|
|
|
{/* Ricerca */}
|
|
<div className="px-5 py-3 border-b flex-shrink-0">
|
|
<div className="relative">
|
|
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
<Input className="pl-8" placeholder="Cerca messaggi..." value={search} onChange={(e) => setSearch(e.target.value)} autoFocus />
|
|
</div>
|
|
</div>
|
|
|
|
{/* Lista messaggi */}
|
|
<div className="flex-1 overflow-y-auto px-5 py-3 space-y-1.5">
|
|
{messages.length === 0 ? (
|
|
<div className="text-center py-8 text-muted-foreground">
|
|
<CheckCircle2 className="h-10 w-10 mx-auto mb-3 opacity-20" />
|
|
<p className="text-sm">Nessun messaggio disponibile</p>
|
|
</div>
|
|
) : (
|
|
messages.map((msg: FascicoloMessageItem & { id: string; subject?: string; from_address?: string; to_addresses?: string[]; direction?: string; state?: string; received_at?: string; sent_at?: string }) => (
|
|
<label
|
|
key={msg.id}
|
|
className={`flex items-center gap-3 p-3 rounded-lg border cursor-pointer transition-colors ${
|
|
selected.has(msg.id) ? 'border-primary bg-primary/5' : 'hover:bg-muted/50'
|
|
}`}
|
|
>
|
|
<input
|
|
type="checkbox"
|
|
checked={selected.has(msg.id)}
|
|
onChange={() => toggleSelect(msg.id)}
|
|
className="h-4 w-4 accent-primary flex-shrink-0"
|
|
/>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium truncate">{msg.subject || '(nessun oggetto)'}</p>
|
|
<p className="text-xs text-muted-foreground truncate">
|
|
{msg.direction === 'inbound' ? `Da: ${msg.from_address}` : `A: ${(msg.to_addresses ?? []).join(', ')}`}
|
|
{' · '}
|
|
{formatDate(msg.received_at || msg.sent_at || msg.created_at)}
|
|
</p>
|
|
</div>
|
|
<div className="flex-shrink-0">
|
|
{msg.direction === 'inbound'
|
|
? <Inbox className="h-4 w-4 text-blue-500" />
|
|
: <Send className="h-4 w-4 text-green-500" />}
|
|
</div>
|
|
</label>
|
|
))
|
|
)}
|
|
</div>
|
|
|
|
{/* Footer */}
|
|
<div className="flex items-center justify-between px-5 py-4 border-t flex-shrink-0">
|
|
<p className="text-sm text-muted-foreground">
|
|
{selected.size > 0 ? `${selected.size} messaggi selezionati` : 'Seleziona i messaggi da aggiungere'}
|
|
</p>
|
|
<div className="flex gap-3">
|
|
<Button variant="outline" onClick={onClose}>Annulla</Button>
|
|
<Button
|
|
onClick={() => addMutation.mutate()}
|
|
disabled={selected.size === 0}
|
|
isLoading={addMutation.isPending}
|
|
>
|
|
Aggiungi {selected.size > 0 ? `(${selected.size})` : ''}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// ─── Pagina dettaglio fascicolo ───────────────────────────────────────────────
|
|
|
|
export function FascicoloDetailPage() {
|
|
const { id } = useParams<{ id: string }>()
|
|
const navigate = useNavigate()
|
|
const queryClient = useQueryClient()
|
|
const { isAdmin } = useAuth()
|
|
|
|
const [showEditDialog, setShowEditDialog] = useState(false)
|
|
const [showAddMessages, setShowAddMessages] = useState(false)
|
|
const [deleteConfirm, setDeleteConfirm] = useState(false)
|
|
|
|
const { data: fascicolo, isLoading: loadingFasc } = useQuery({
|
|
queryKey: ['fascicolo', id],
|
|
queryFn: () => fascicoliApi.get(id!),
|
|
enabled: !!id,
|
|
})
|
|
|
|
const { data: messages = [], isLoading: loadingMsgs } = useQuery({
|
|
queryKey: ['fascicolo-messages', id],
|
|
queryFn: () => fascicoliApi.getMessages(id!),
|
|
enabled: !!id,
|
|
})
|
|
|
|
const removeMsgMutation = useMutation({
|
|
mutationFn: (msgId: string) => fascicoliApi.removeMessages(id!, [msgId]),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['fascicolo-messages', id] })
|
|
queryClient.invalidateQueries({ queryKey: ['fascicolo', id] })
|
|
queryClient.invalidateQueries({ queryKey: ['fascicoli'] })
|
|
toast.success('Messaggio rimosso dal fascicolo')
|
|
},
|
|
onError: (e) => toast.error(getErrorMessage(e)),
|
|
})
|
|
|
|
const deleteFascicoloMutation = useMutation({
|
|
mutationFn: () => fascicoliApi.delete(id!),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['fascicoli'] })
|
|
toast.success('Fascicolo eliminato')
|
|
navigate('/fascicoli')
|
|
},
|
|
onError: (e) => toast.error(getErrorMessage(e)),
|
|
})
|
|
|
|
if (loadingFasc) {
|
|
return (
|
|
<div className="flex items-center justify-center h-64">
|
|
<div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (!fascicolo) {
|
|
return (
|
|
<div className="flex flex-col items-center justify-center h-64 gap-4">
|
|
<AlertTriangle className="h-10 w-10 text-muted-foreground opacity-40" />
|
|
<p className="text-muted-foreground">Fascicolo non trovato</p>
|
|
<Button variant="outline" onClick={() => navigate('/fascicoli')}>
|
|
<ArrowLeft className="h-4 w-4 mr-2" />
|
|
Torna ai fascicoli
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const existingIds = new Set(messages.map((m) => m.id))
|
|
|
|
const FolderIcon = fascicolo.stato === 'aperto'
|
|
? FolderOpen
|
|
: fascicolo.stato === 'chiuso'
|
|
? FolderCheck
|
|
: FolderArchive
|
|
|
|
return (
|
|
<div className="flex flex-col h-full">
|
|
{/* Toolbar */}
|
|
<div className="border-b bg-background px-6 py-3 flex items-center justify-between">
|
|
<div className="flex items-center gap-2">
|
|
<Button variant="ghost" size="icon" onClick={() => navigate('/fascicoli')}>
|
|
<ArrowLeft className="h-5 w-5" />
|
|
</Button>
|
|
<span className="text-sm text-muted-foreground">Fascicoli</span>
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Button variant="outline" size="sm" onClick={() => setShowEditDialog(true)}>
|
|
<Pencil className="h-4 w-4 mr-1" />
|
|
Modifica
|
|
</Button>
|
|
{isAdmin && (
|
|
<Button variant="outline" size="sm" onClick={() => setDeleteConfirm(true)}
|
|
className="text-destructive border-destructive/30 hover:bg-destructive/10">
|
|
<Trash2 className="h-4 w-4 mr-1" />
|
|
Elimina
|
|
</Button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Intestazione fascicolo */}
|
|
<div className="border-b bg-muted/30 px-6 py-5">
|
|
<div className="max-w-4xl mx-auto">
|
|
<div className="flex items-start gap-4">
|
|
<FolderIcon className={`h-10 w-10 flex-shrink-0 mt-0.5 ${
|
|
fascicolo.stato === 'aperto' ? 'text-green-600'
|
|
: fascicolo.stato === 'chiuso' ? 'text-gray-500'
|
|
: 'text-amber-600'
|
|
}`} />
|
|
<div className="flex-1 min-w-0">
|
|
<div className="flex items-center gap-3 flex-wrap">
|
|
<h1 className="text-xl font-bold">{fascicolo.titolo}</h1>
|
|
<StatoBadge stato={fascicolo.stato} />
|
|
{fascicolo.numero_pratica && (
|
|
<span className="text-sm text-muted-foreground font-mono bg-background border px-2 py-0.5 rounded">
|
|
#{fascicolo.numero_pratica}
|
|
</span>
|
|
)}
|
|
</div>
|
|
<div className="flex items-center gap-6 mt-2 text-sm text-muted-foreground flex-wrap">
|
|
{fascicolo.categoria && (
|
|
<span className="flex items-center gap-1.5">
|
|
<span className="font-medium">Categoria:</span> {fascicolo.categoria}
|
|
</span>
|
|
)}
|
|
{fascicolo.scadenza && (
|
|
<span className="flex items-center gap-1.5 text-amber-700">
|
|
<Calendar className="h-4 w-4" />
|
|
<span className="font-medium">Scadenza:</span> {formatDate(fascicolo.scadenza)}
|
|
</span>
|
|
)}
|
|
<span className="flex items-center gap-1.5">
|
|
<MessageSquare className="h-4 w-4" />
|
|
{fascicolo.message_count} {fascicolo.message_count === 1 ? 'messaggio' : 'messaggi'}
|
|
</span>
|
|
<span>Aggiornato: {formatDate(fascicolo.updated_at)}</span>
|
|
</div>
|
|
{fascicolo.note && (
|
|
<p className="mt-2 text-sm text-muted-foreground italic">{fascicolo.note}</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Sezione messaggi */}
|
|
<div className="flex-1 overflow-y-auto p-6">
|
|
<div className="max-w-4xl mx-auto">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h2 className="text-base font-semibold flex items-center gap-2">
|
|
<MessageSquare className="h-4 w-4 text-primary" />
|
|
Messaggi nel fascicolo ({messages.length})
|
|
</h2>
|
|
<Button size="sm" onClick={() => setShowAddMessages(true)}>
|
|
<Plus className="h-4 w-4 mr-1" />
|
|
Aggiungi messaggi
|
|
</Button>
|
|
</div>
|
|
|
|
{loadingMsgs ? (
|
|
<div className="flex justify-center py-10">
|
|
<div className="h-6 w-6 animate-spin rounded-full border-4 border-primary border-t-transparent" />
|
|
</div>
|
|
) : messages.length === 0 ? (
|
|
<div className="text-center py-14 text-muted-foreground border-2 border-dashed rounded-xl">
|
|
<MessageSquare className="h-12 w-12 mx-auto mb-4 opacity-20" />
|
|
<p className="font-medium">Nessun messaggio nel fascicolo</p>
|
|
<p className="text-sm mt-1">Aggiungi messaggi PEC per costruire il fascicolo.</p>
|
|
<Button className="mt-4" size="sm" onClick={() => setShowAddMessages(true)}>
|
|
<Plus className="h-4 w-4 mr-1" />
|
|
Aggiungi messaggi
|
|
</Button>
|
|
</div>
|
|
) : (
|
|
<div className="space-y-2">
|
|
{messages.map((msg) => (
|
|
<div
|
|
key={msg.id}
|
|
className="flex items-center gap-4 p-4 rounded-lg border bg-card hover:shadow-sm transition-shadow group"
|
|
>
|
|
{/* Icona direzione */}
|
|
<div className="flex-shrink-0">
|
|
{msg.direction === 'inbound'
|
|
? <Inbox className="h-5 w-5 text-blue-500" />
|
|
: <Send className="h-5 w-5 text-green-500" />}
|
|
</div>
|
|
|
|
{/* Info messaggio */}
|
|
<div className="flex-1 min-w-0">
|
|
<p className="font-medium truncate">{msg.subject || '(nessun oggetto)'}</p>
|
|
<p className="text-xs text-muted-foreground mt-0.5">
|
|
{msg.direction === 'inbound'
|
|
? `Da: ${msg.from_address}`
|
|
: `A: ${(msg.to_addresses ?? []).join(', ')}`}
|
|
{' · '}
|
|
{formatDate(msg.received_at || msg.sent_at || msg.created_at)}
|
|
</p>
|
|
<p className="text-xs text-muted-foreground/70">
|
|
Aggiunto: {formatDate(msg.added_at)}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Badge stato */}
|
|
<div className="flex-shrink-0">
|
|
<PecStateBadge state={msg.state} />
|
|
</div>
|
|
|
|
{/* Azioni */}
|
|
<div className="flex items-center gap-1 flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
<button
|
|
type="button"
|
|
onClick={() => navigate(`/messages/${msg.id}`)}
|
|
className="p-1.5 rounded hover:bg-muted text-muted-foreground hover:text-primary"
|
|
title="Apri messaggio"
|
|
>
|
|
<ExternalLink className="h-4 w-4" />
|
|
</button>
|
|
<button
|
|
type="button"
|
|
onClick={() => removeMsgMutation.mutate(msg.id)}
|
|
className="p-1.5 rounded hover:bg-destructive/10 text-muted-foreground hover:text-destructive"
|
|
title="Rimuovi dal fascicolo"
|
|
>
|
|
<X className="h-4 w-4" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Modal modifica */}
|
|
{showEditDialog && (
|
|
<EditDialog fascicolo={fascicolo} onClose={() => setShowEditDialog(false)} />
|
|
)}
|
|
|
|
{/* Modal aggiungi messaggi */}
|
|
{showAddMessages && (
|
|
<AddMessagesModal
|
|
fascicoloId={id!}
|
|
existingIds={existingIds}
|
|
onClose={() => setShowAddMessages(false)}
|
|
/>
|
|
)}
|
|
|
|
{/* Conferma eliminazione */}
|
|
{deleteConfirm && (
|
|
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
|
|
<div className="bg-background rounded-xl shadow-2xl p-6 w-full max-w-md space-y-4">
|
|
<h3 className="text-lg font-semibold flex items-center gap-2 text-destructive">
|
|
<Trash2 className="h-5 w-5" />
|
|
Elimina fascicolo
|
|
</h3>
|
|
<p className="text-sm text-muted-foreground">
|
|
Stai per eliminare <strong>{fascicolo.titolo}</strong>.
|
|
I messaggi collegati non verranno eliminati.
|
|
Questa operazione non puo essere annullata.
|
|
</p>
|
|
<div className="flex justify-end gap-3 pt-2">
|
|
<Button variant="outline" onClick={() => setDeleteConfirm(false)}>Annulla</Button>
|
|
<Button
|
|
variant="destructive"
|
|
isLoading={deleteFascicoloMutation.isPending}
|
|
onClick={() => deleteFascicoloMutation.mutate()}
|
|
>
|
|
Elimina
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|