import { CheckCircle, XCircle, Clock, MessageSquare, Mic, Square, Play, Trash2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Textarea } from '@/components/ui/textarea'; import { useModelStore, type ChecklistItem } from '@/stores/useModelStore'; import { useState, useRef, useCallback } from 'react'; import { toast } from 'sonner'; function VoiceRecorder({ itemId, audioUrl }: { itemId: string; audioUrl: string | null }) { const { setChecklistItemAudio } = useModelStore(); const [recording, setRecording] = useState(false); const [playing, setPlaying] = useState(false); const mediaRecorderRef = useRef(null); const chunksRef = useRef([]); const audioRef = useRef(null); const startRecording = useCallback(async () => { try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm' }); mediaRecorderRef.current = mediaRecorder; chunksRef.current = []; mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) chunksRef.current.push(e.data); }; mediaRecorder.onstop = () => { const blob = new Blob(chunksRef.current, { type: 'audio/webm' }); const url = URL.createObjectURL(blob); setChecklistItemAudio(itemId, url); stream.getTracks().forEach(t => t.stop()); toast.success('Anotação de voz gravada'); }; mediaRecorder.start(); setRecording(true); } catch { toast.error('Não foi possível acessar o microfone'); } }, [itemId, setChecklistItemAudio]); const stopRecording = useCallback(() => { mediaRecorderRef.current?.stop(); setRecording(false); }, []); const playAudio = useCallback(() => { if (!audioUrl) return; const audio = new Audio(audioUrl); audioRef.current = audio; setPlaying(true); audio.onended = () => setPlaying(false); audio.play(); }, [audioUrl]); const deleteAudio = useCallback(() => { if (audioUrl) URL.revokeObjectURL(audioUrl); setChecklistItemAudio(itemId, null); setPlaying(false); }, [itemId, audioUrl, setChecklistItemAudio]); return (
{!recording && !audioUrl && ( )} {recording && ( )} {audioUrl && !recording && ( <> {playing ? '▶ Reproduzindo…' : '● Gravação salva'} )}
); } function ChecklistRow({ item }: { item: ChecklistItem }) { const { setChecklistItemStatus, setChecklistItemNote } = useModelStore(); const [showNote, setShowNote] = useState(item.status === 'rejected'); const handleApprove = () => { setChecklistItemStatus(item.id, 'approved'); setShowNote(false); toast.success(`"${item.label}" aprovado`); }; const handleReject = () => { setChecklistItemStatus(item.id, 'rejected'); setShowNote(true); toast.error(`"${item.label}" reprovado — adicione uma anotação`); }; const statusColor = item.status === 'approved' ? 'text-success' : item.status === 'rejected' ? 'text-destructive' : 'text-muted-foreground'; const StatusIcon = item.status === 'approved' ? CheckCircle : item.status === 'rejected' ? XCircle : Clock; return (
{item.label}
{(showNote || item.status === 'rejected') && (
Anotação