testes/src/features/prafrot/components/AttendanceFormModal.jsx

175 lines
7.6 KiB
JavaScript

import React, { useState, useEffect } from 'react';
import { X, Send, Clock, Calendar, MessageSquare, ShieldCheck, AlertCircle } from 'lucide-react';
import { motion, AnimatePresence } from 'framer-motion';
import { approveTripRequest } from '../services/prafrotService';
import { getCurrentModuleUser } from '@/utils/tokenManager';
import { toast } from 'sonner';
export const AttendanceFormModal = ({ trip, onClose, onRefresh }) => {
const [loading, setLoading] = useState(false);
const user = getCurrentModuleUser();
const [formData, setFormData] = useState({
atendimento: user?.nome || user?.name || '',
situacao_liberacao: 'LIBERADO',
data_liberacao: new Date().toISOString().split('T')[0],
hora_liberacao: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }),
observacao: ''
});
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
await approveTripRequest({
idsolicitacoes: trip.idsolicitacoes,
status: formData.situacao_liberacao,
atendimento: formData.atendimento,
data_liberacao: formData.data_liberacao,
hora_liberacao: formData.hora_liberacao,
obs_liberacao: formData.observacao
});
toast.success('Atendimento realizado com sucesso!');
onRefresh();
onClose();
} catch (error) {
toast.error('Erro ao realizar atendimento');
} finally {
setLoading(false);
}
};
const inputStyle = "w-full bg-black/40 border border-white/10 rounded-xl px-4 py-3 text-sm text-white focus:outline-none focus:border-emerald-500/50 transition-all placeholder:text-zinc-600";
const labelStyle = "text-[10px] font-bold text-zinc-500 uppercase tracking-widest mb-2 block";
return (
<div className="fixed inset-0 z-[110] flex items-center justify-center p-4 overflow-hidden">
<motion.div
initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
onClick={onClose}
className="absolute inset-0 bg-black/80 backdrop-blur-sm"
/>
<motion.div
initial={{ opacity: 0, scale: 0.95, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: 20 }}
className="relative w-full max-w-lg bg-[#141416] border border-white/10 rounded-[32px] shadow-2xl overflow-hidden"
>
<div className="p-6 border-b border-white/5 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-xl bg-emerald-500/10 flex items-center justify-center text-emerald-500">
<ShieldCheck size={20} />
</div>
<div>
<h2 className="text-lg font-bold text-white leading-none">Formulário de Atendimento</h2>
<p className="text-[10px] text-zinc-500 uppercase tracking-widest mt-1">Solicitação #{trip.idsolicitacoes}</p>
</div>
</div>
<button onClick={onClose} className="w-8 h-8 rounded-full bg-white/5 flex items-center justify-center text-zinc-500 hover:text-white transition-colors">
<X size={18} />
</button>
</div>
<form onSubmit={handleSubmit} className="p-6 space-y-6">
<div className="space-y-2">
<label className={labelStyle}>Atendimento (Usuário)</label>
<div className="relative">
<ShieldCheck className="absolute left-4 top-1/2 -translate-y-1/2 text-zinc-600" size={16} />
<input
type="text"
className={`${inputStyle} pl-12`}
value={formData.atendimento}
onChange={e => setFormData({...formData, atendimento: e.target.value})}
required
/>
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<label className={labelStyle}>Data da Liberação</label>
<div className="relative">
<Calendar className="absolute left-4 top-1/2 -translate-y-1/2 text-zinc-600" size={16} />
<input
type="date"
className={`${inputStyle} pl-12`}
value={formData.data_liberacao}
onChange={e => setFormData({...formData, data_liberacao: e.target.value})}
required
/>
</div>
</div>
<div className="space-y-2">
<label className={labelStyle}>Hora da Liberação</label>
<div className="relative">
<Clock className="absolute left-4 top-1/2 -translate-y-1/2 text-zinc-600" size={16} />
<input
type="time"
className={`${inputStyle} pl-12`}
value={formData.hora_liberacao}
onChange={e => setFormData({...formData, hora_liberacao: e.target.value})}
required
/>
</div>
</div>
</div>
<div className="space-y-2">
<label className={labelStyle}>Situação da Liberação</label>
<div className="flex gap-2">
{[
{ id: 'LIBERADO', label: 'Liberado', color: 'bg-emerald-500', icon: ShieldCheck },
{ id: 'PARALIZADO', label: 'Paralizado', color: 'bg-amber-500', icon: AlertCircle }
].map(opt => (
<button
key={opt.id}
type="button"
onClick={() => setFormData({...formData, situacao_liberacao: opt.id})}
className={`flex-1 py-3 px-4 rounded-xl border flex items-center justify-center gap-2 transition-all ${
formData.situacao_liberacao === opt.id
? `border-${opt.id === 'LIBERADO' ? 'emerald' : 'amber'}-500/50 bg-${opt.id === 'LIBERADO' ? 'emerald' : 'amber'}-500/10 text-${opt.id === 'LIBERADO' ? 'emerald' : 'amber'}-500`
: 'border-white/5 bg-white/5 text-zinc-500 hover:border-white/10'
}`}
>
<opt.icon size={14} />
<span className="text-[10px] font-bold uppercase tracking-widest">{opt.label}</span>
</button>
))}
</div>
</div>
<div className="space-y-2">
<label className={labelStyle}>Observações</label>
<div className="relative">
<MessageSquare className="absolute left-4 top-4 text-zinc-600" size={16} />
<textarea
className={`${inputStyle} pl-12 min-h-[100px] resize-none`}
placeholder="Descreva observações adicionais..."
value={formData.observacao}
onChange={e => setFormData({...formData, observacao: e.target.value})}
/>
</div>
</div>
<div className="pt-4">
<button
type="submit"
disabled={loading}
className="w-full py-4 bg-emerald-600 hover:bg-emerald-500 text-white rounded-2xl font-bold text-xs uppercase tracking-[0.2em] transition-all shadow-lg shadow-emerald-500/20 flex items-center justify-center gap-2 disabled:opacity-50"
>
{loading ? (
<motion.div animate={{ rotate: 360 }} transition={{ repeat: Infinity, duration: 1 }} className="w-5 h-5 border-2 border-white/20 border-t-white rounded-full" />
) : (
<>
<Send size={16} /> Confirmar Atendimento
</>
)}
</button>
</div>
</form>
</motion.div>
</div>
);
};