espace-paie-odentas/components/staff/StaffTicketActions.tsx

138 lines
5.4 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { TicketReplyConfirmationModal } from "./TicketReplyConfirmationModal";
export default function StaffTicketActions({ ticketId, status, mode = "both" }: { ticketId: string; status: string; mode?: "status" | "message" | "both" }) {
const [updating, setUpdating] = useState(false);
const [sending, setSending] = useState(false);
const [showModal, setShowModal] = useState(false);
const [pendingMessage, setPendingMessage] = useState({ body: "", internal: false });
const [recipientInfo, setRecipientInfo] = useState<{ email: string; name: string } | null>(null);
// Récupérer les informations du destinataire
useEffect(() => {
async function fetchRecipientInfo() {
try {
console.log('🔍 [StaffTicketActions] Fetching recipient info for ticket:', ticketId);
const url = `/api/tickets/${ticketId}/recipient-info`;
console.log('🔍 [StaffTicketActions] URL:', url);
const res = await fetch(url, { credentials: 'include' });
console.log('🔍 [StaffTicketActions] Response status:', res.status);
if (res.ok) {
const data = await res.json();
console.log('✅ [StaffTicketActions] Recipient info:', data);
setRecipientInfo(data);
} else {
const errorText = await res.text();
console.error('❌ [StaffTicketActions] Error response:', res.status, errorText);
}
} catch (e) {
console.error('❌ [StaffTicketActions] Erreur lors de la récupération des infos destinataire:', e);
}
}
fetchRecipientInfo();
}, [ticketId]);
async function onStatusSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const fd = new FormData(e.currentTarget);
const next = String(fd.get('status') || 'open');
setUpdating(true);
try {
const res = await fetch(`/api/tickets/${ticketId}`, { method: 'PATCH', credentials: 'include', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status: next }) });
if (!res.ok) throw new Error(await res.text());
location.reload();
} catch (e: any) {
alert('Erreur: ' + (e?.message || 'inconnue'));
} finally {
setUpdating(false);
}
}
async function onMessageSubmit(e: React.FormEvent<HTMLFormElement>) {
e.preventDefault();
const form = e.currentTarget;
const fd = new FormData(form);
const body = String(fd.get('body') || '').trim();
const internal = fd.get('internal') === 'on';
if (!body) return;
// Si c'est une note interne, envoyer directement
if (internal) {
await sendMessage(body, internal, form);
} else {
// Sinon, afficher le modal de confirmation
setPendingMessage({ body, internal });
setShowModal(true);
}
}
async function sendMessage(body: string, internal: boolean, formToReset?: HTMLFormElement) {
setSending(true);
try {
const res = await fetch(`/api/tickets/${ticketId}/messages`, {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body, internal })
});
if (!res.ok) throw new Error(await res.text());
if (formToReset) formToReset.reset();
location.reload();
} catch (e: any) {
alert('Erreur: ' + (e?.message || 'inconnue'));
} finally {
setSending(false);
setShowModal(false);
}
}
function handleConfirmSend() {
// Récupérer le formulaire pour le reset
const form = document.querySelector('form[data-ticket-form]') as HTMLFormElement;
sendMessage(pendingMessage.body, pendingMessage.internal, form);
}
return (
<>
{(mode === 'status' || mode === 'both') && (
<form className="flex items-center gap-2" onSubmit={onStatusSubmit}>
<select name="status" defaultValue={status} className="px-2 py-1 rounded-md border text-sm bg-transparent">
<option value="open">Ouvert</option>
<option value="waiting_client">En attente client</option>
<option value="waiting_staff">En attente support</option>
<option value="closed">Fermé</option>
</select>
<button disabled={updating} className="inline-flex items-center px-3 py-2 rounded-lg bg-slate-200 text-sm disabled:opacity-50">Mettre à jour</button>
</form>
)}
{(mode === 'message' || mode === 'both') && (
<form className="space-y-2" onSubmit={onMessageSubmit} data-ticket-form>
<textarea name="body" className="w-full px-3 py-2 rounded-lg border bg-transparent text-sm min-h-[120px]" placeholder="Réponse…" />
<div className="flex items-center gap-3">
<label className="inline-flex items-center gap-2 text-sm"><input type="checkbox" name="internal" /> Note interne</label>
<button disabled={sending} className="ml-auto inline-flex items-center px-3 py-2 rounded-lg bg-emerald-600 text-white text-sm hover:bg-emerald-700 disabled:opacity-50">Envoyer</button>
</div>
</form>
)}
{/* Modal de confirmation */}
{recipientInfo && (
<TicketReplyConfirmationModal
isOpen={showModal}
recipientEmail={recipientInfo.email}
recipientName={recipientInfo.name}
messageBody={pendingMessage.body}
onConfirm={handleConfirmSend}
onCancel={() => setShowModal(false)}
isLoading={sending}
/>
)}
</>
);
}