Update ClientPortal.tsx

This commit is contained in:
fcarraUniSa
2026-02-18 09:59:04 +01:00
committed by GitHub
parent b342d5f446
commit e648e82016

View File

@@ -141,18 +141,42 @@ export const ClientPortal: React.FC<ClientPortalProps> = ({
setIsTyping(false);
};
const submitTicket = (e: React.FormEvent) => {
const submitTicket = async (e: React.FormEvent) => {
e.preventDefault();
setIsUploading(true);
const attachments: Attachment[] = [];
if (ticketFiles) {
if (ticketFiles && ticketFiles.length > 0) {
for (let i = 0; i < ticketFiles.length; i++) {
const file = ticketFiles[i];
attachments.push({
id: `att-${Date.now()}-${i}`,
name: file.name,
type: file.type,
url: URL.createObjectURL(file) // Note: This is client-side only URL for preview, real implementation would upload here too or later
});
// Validation check before upload
const maxSize = (settings.features.maxFileSizeMb || 5) * 1024 * 1024;
if (file.size > maxSize) {
showToast(`File ${file.name} troppo grande. Max ${settings.features.maxFileSizeMb}MB`, 'error');
continue;
}
const formData = new FormData();
formData.append('file', file);
try {
const res = await fetch('/api/upload', { method: 'POST', body: formData });
if(res.ok) {
const data = await res.json();
attachments.push({
id: data.id,
name: data.name,
url: data.url,
type: data.type
});
} else {
showToast(`Errore caricamento ${file.name}`, 'error');
}
} catch(err) {
console.error(err);
showToast(`Errore di rete caricamento ${file.name}`, 'error');
}
}
}
@@ -167,6 +191,7 @@ export const ClientPortal: React.FC<ClientPortalProps> = ({
setTicketForm({ subject: '', description: '', queue: queues.length > 0 ? queues[0].name : 'General' });
setTicketFiles(null);
setIsUploading(false);
setActiveView('dashboard');
};
@@ -390,6 +415,20 @@ export const ClientPortal: React.FC<ClientPortalProps> = ({
</div>
<div className="p-6 space-y-6">
<div className="bg-gray-50 p-4 rounded-lg">{selectedTicket.description}</div>
{selectedTicket.attachments && selectedTicket.attachments.length > 0 && (
<div className="bg-blue-50/50 p-4 rounded-lg border border-blue-100">
<h3 className="text-xs font-bold text-blue-800 uppercase mb-2 flex items-center"><Paperclip className="w-3 h-3 mr-1"/> Allegati Iniziali</h3>
<div className="flex flex-wrap gap-2">
{selectedTicket.attachments.map(att => (
<a key={att.id} href={att.url} target="_blank" rel="noopener noreferrer" className="flex items-center text-xs bg-white border border-blue-200 text-blue-600 px-3 py-2 rounded-lg hover:bg-blue-50 transition">
<FileText className="w-3 h-3 mr-2 text-blue-400" /> {att.name}
</a>
))}
</div>
</div>
)}
<div className="space-y-4">
<h3 className="font-bold text-gray-700">Messaggi</h3>
{selectedTicket.messages.map(m => (
@@ -440,12 +479,22 @@ export const ClientPortal: React.FC<ClientPortalProps> = ({
<form onSubmit={submitTicket} className="space-y-4">
<input type="text" placeholder="Oggetto" className="w-full border p-3 rounded-lg" value={ticketForm.subject} onChange={e => setTicketForm({...ticketForm, subject: e.target.value})} required />
<textarea placeholder="Descrizione" rows={5} className="w-full border p-3 rounded-lg" value={ticketForm.description} onChange={e => setTicketForm({...ticketForm, description: e.target.value})} required />
<select className="w-full border p-3 rounded-lg" value={ticketForm.queue} onChange={e => setTicketForm({...ticketForm, queue: e.target.value})}>
{queues.map(q => <option key={q.id} value={q.name}>{q.name}</option>)}
</select>
{/* Create Ticket attachment (mock for now as backend requires form data or separate upload) */}
{/* For simplicity in this demo, omitting file upload on creation to keep code lean, or would need same async upload logic */}
<button type="submit" className="w-full bg-brand-600 text-white py-3 rounded-lg font-bold">Crea Ticket</button>
<div className="grid grid-cols-2 gap-4">
<select className="w-full border p-3 rounded-lg bg-white" value={ticketForm.queue} onChange={e => setTicketForm({...ticketForm, queue: e.target.value})}>
{queues.map(q => <option key={q.id} value={q.name}>{q.name}</option>)}
</select>
<div className="relative">
<label className={`flex items-center justify-center w-full border p-3 rounded-lg cursor-pointer hover:bg-gray-50 ${isUploading ? 'opacity-50 pointer-events-none' : ''}`}>
{isUploading ? <Loader2 className="w-5 h-5 animate-spin text-brand-600" /> : <Paperclip className="w-5 h-5 text-gray-500 mr-2" />}
<span className="text-gray-500 text-sm">{ticketFiles && ticketFiles.length > 0 ? `${ticketFiles.length} file selezionati` : 'Allega file'}</span>
<input type="file" className="hidden" multiple onChange={(e) => setTicketFiles(e.target.files)} />
</label>
</div>
</div>
<button type="submit" disabled={isUploading} className="w-full bg-brand-600 text-white py-3 rounded-lg font-bold hover:bg-brand-700 disabled:opacity-70 flex items-center justify-center">
{isUploading ? <Loader2 className="w-5 h-5 animate-spin mr-2" /> : null}
{isUploading ? 'Caricamento in corso...' : 'Crea Ticket'}
</button>
</form>
</div>
)}