Files
tracksteel_app/src/pages/Sugestoes.tsx
T

235 lines
9.5 KiB
TypeScript

import React, { useState } from 'react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Textarea } from '@/components/ui/textarea';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { MessageSquare, Send, Clock, CheckCircle, XCircle, User, Calendar, History } from 'lucide-react';
import { useSugestoes } from '@/hooks/useSugestoes';
import { useUserRole } from '@/hooks/useUserRole';
import { format, parseISO } from 'date-fns';
import { ptBR } from 'date-fns/locale';
import HistoricoSugestoes from '@/components/sugestoes/HistoricoSugestoes';
const Sugestoes = () => {
const {
sugestoes,
sugestoesArquivadas,
loading,
loadingArchived,
createSugestao,
updateSugestao,
isCreating
} = useSugestoes();
const { isAdmin } = useUserRole();
const [novaSugestao, setNovaSugestao] = useState('');
const [editingNotes, setEditingNotes] = useState<{ [key: string]: string }>({});
const [showHistorico, setShowHistorico] = useState(false);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (novaSugestao.trim()) {
createSugestao(novaSugestao.trim());
setNovaSugestao('');
}
};
const handleStatusChange = (id: string, newStatus: string) => {
const notes = editingNotes[id] || '';
updateSugestao(id, newStatus, notes);
};
const handleNotesChange = (id: string, notes: string) => {
setEditingNotes(prev => ({ ...prev, [id]: notes }));
};
const getStatusIcon = (status: string) => {
switch (status) {
case 'Implementada':
return <CheckCircle className="h-4 w-4 text-green-600" />;
case 'Rejeitada':
return <XCircle className="h-4 w-4 text-red-600" />;
default:
return <Clock className="h-4 w-4 text-yellow-600" />;
}
};
const getStatusColor = (status: string) => {
switch (status) {
case 'Implementada':
return 'bg-green-50 text-green-700 border-green-200';
case 'Rejeitada':
return 'bg-red-50 text-red-700 border-red-200';
default:
return 'bg-yellow-50 text-yellow-700 border-yellow-200';
}
};
if (loading) {
return (
<div className="container mx-auto p-4 bg-background min-h-screen">
<div className="flex items-center justify-center h-64">
<div className="text-foreground">Carregando sugestões...</div>
</div>
</div>
);
}
return (
<div className="container mx-auto p-2 sm:p-4 space-y-3 sm:space-y-4 bg-background min-h-screen">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3">
<div>
<h1 className="text-lg sm:text-2xl lg:text-3xl font-bold text-foreground mb-1">Sugestões de Melhoria</h1>
<p className="text-muted-foreground text-xs sm:text-sm">Compartilhe suas ideias para melhorar o sistema</p>
</div>
<div className="flex items-center gap-2">
<Button
variant="outline"
onClick={() => setShowHistorico(true)}
className="border-border text-muted-foreground hover:bg-accent h-8 text-xs"
size="sm"
>
<History className="h-3 w-3 mr-1 sm:mr-2" />
<span className="hidden sm:inline">Histórico</span>
<span className="sm:hidden">Hist.</span>
</Button>
<Badge variant="outline" className="text-xs">
{sugestoes.length} {sugestoes.length === 1 ? 'sugestão' : 'sugestões'}
</Badge>
</div>
</div>
{/* Formulário para nova sugestão */}
<Card className="bg-card border-border">
<CardHeader className="pb-2 sm:pb-3">
<CardTitle className="text-card-foreground flex items-center gap-2 text-sm sm:text-lg">
<MessageSquare className="h-4 w-4 sm:h-5 sm:w-5" />
Nova Sugestão
</CardTitle>
</CardHeader>
<CardContent className="pt-0">
<form onSubmit={handleSubmit} className="space-y-3">
<div>
<Label htmlFor="sugestao" className="text-muted-foreground text-xs sm:text-sm">
Descreva sua sugestão
</Label>
<Textarea
id="sugestao"
value={novaSugestao}
onChange={(e) => setNovaSugestao(e.target.value)}
placeholder="Descreva sua ideia para melhorar o sistema..."
className="mt-1 bg-background border-border text-foreground placeholder-muted-foreground text-xs sm:text-sm"
rows={3}
required
/>
</div>
<Button
type="submit"
disabled={isCreating || !novaSugestao.trim()}
className="bg-primary hover:bg-primary/90 text-primary-foreground h-8 text-xs"
size="sm"
>
<Send className="h-3 w-3 mr-1 sm:mr-2" />
{isCreating ? 'Enviando...' : 'Enviar Sugestão'}
</Button>
</form>
</CardContent>
</Card>
{/* Lista de sugestões */}
<div className="space-y-2 sm:space-y-3">
{sugestoes.map((sugestao) => (
<Card key={sugestao.id} className="bg-card border-border">
<CardHeader className="pb-2 sm:pb-3">
<div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-2">
<div className="flex flex-col sm:flex-row sm:items-center gap-2">
<div className="flex items-center gap-1 text-muted-foreground text-xs">
<User className="h-3 w-3" />
{sugestao.user_name}
</div>
<div className="flex items-center gap-1 text-muted-foreground text-xs">
<Calendar className="h-3 w-3" />
{format(parseISO(sugestao.created_at), 'dd/MM/yyyy HH:mm', { locale: ptBR })}
</div>
</div>
<Badge variant="outline" className={`${getStatusColor(sugestao.status)} text-xs`}>
{getStatusIcon(sugestao.status)}
<span className="ml-1">{sugestao.status}</span>
</Badge>
</div>
</CardHeader>
<CardContent className="pt-0">
<p className="text-card-foreground mb-3 text-xs sm:text-sm">{sugestao.sugestao}</p>
{/* Painel administrativo */}
{isAdmin && (
<div className="border-t border-border pt-3 space-y-3">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
<div>
<Label className="text-muted-foreground text-xs">Status</Label>
<Select
value={sugestao.status}
onValueChange={(value) => handleStatusChange(sugestao.id, value)}
>
<SelectTrigger className="bg-background border-border text-foreground h-8 text-xs">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="Pendente">Pendente</SelectItem>
<SelectItem value="Implementada">Implementada</SelectItem>
<SelectItem value="Rejeitada">Rejeitada</SelectItem>
</SelectContent>
</Select>
</div>
<div>
<Label className="text-muted-foreground text-xs">Observações do Desenvolvedor</Label>
<Input
value={editingNotes[sugestao.id] || sugestao.developer_notes || ''}
onChange={(e) => handleNotesChange(sugestao.id, e.target.value)}
placeholder="Adicionar observações..."
className="bg-background border-border text-foreground placeholder-muted-foreground h-8 text-xs"
/>
</div>
</div>
{sugestao.developer_notes && (
<div className="bg-muted/50 p-2 rounded-lg">
<Label className="text-muted-foreground text-xs font-medium">Observações:</Label>
<p className="text-muted-foreground mt-1 text-xs">{sugestao.developer_notes}</p>
</div>
)}
</div>
)}
</CardContent>
</Card>
))}
</div>
{sugestoes.length === 0 && (
<Card className="bg-card border-border">
<CardContent className="flex flex-col items-center justify-center py-12">
<MessageSquare className="h-12 w-12 text-muted-foreground mb-4" />
<p className="text-muted-foreground text-center">
Nenhuma sugestão foi enviada ainda.{' '}
<br />
Seja o primeiro a compartilhar uma ideia!
</p>
</CardContent>
</Card>
)}
{/* Modal de Histórico */}
<HistoricoSugestoes
isOpen={showHistorico}
onClose={() => setShowHistorico(false)}
sugestoesArquivadas={sugestoesArquivadas}
loading={loadingArchived}
/>
</div>
);
};
export default Sugestoes;