photum/frontend/components/CourseForm.tsx
João Vitor de5ceea1f3 feat: reestruturar página de equipe com sistema de profissionais multi-função
- Renomear 'Equipe & Fotógrafos' para 'Equipe' no título e navbar
- Adicionar suporte para 3 tipos de profissionais: Fotógrafo, Cinegrafista, Recepcionista
- Implementar cards estatísticos separados por função profissional
- Adicionar filtros por função (Fotógrafos, Cinegrafistas, Recepcionistas)
- Adicionar filtros por status (Disponível, Em Evento, Inativo)
- Transformar cards em tabela responsiva com colunas: Nome, Função Profissional, Disponibilidade
- Expandir interface Professional com campos completos do Excel:
  * Endereço completo (rua, número, complemento, bairro, cidade, UF)
  * Dados bancários (banco, agência, conta/pix, tipo cartão, titular)
  * Recursos (carro disponível, possui estúdio, quantidade)
  * Sistema de avaliações detalhado (6 critérios + média)
  * Valores (tabela free, extra no cachê)
  * Observações
- Redesenhar modal 'Adicionar Profissional' com formulário extenso organizado em seções
- Atualizar modal de detalhes com todas as novas informações
- Adicionar ícones específicos por função (Camera, Video, UserCheck)
- Remover fotos da tabela mantendo apenas informações essenciais
2025-12-08 03:12:45 -03:00

211 lines
6.5 KiB
TypeScript

import React, { useState } from "react";
import { Course, Institution } from "../types";
import { Input, Select } from "./Input";
import { Button } from "./Button";
import { GraduationCap, X, Check, AlertCircle } from "lucide-react";
interface CourseFormProps {
onCancel: () => void;
onSubmit: (data: Partial<Course>) => void;
initialData?: Course;
userId: string;
institutions: Institution[];
}
const GRADUATION_TYPES = [
"Bacharelado",
"Licenciatura",
"Tecnológico",
"Especialização",
"Mestrado",
"Doutorado",
];
export const CourseForm: React.FC<CourseFormProps> = ({
onCancel,
onSubmit,
initialData,
userId,
institutions,
}) => {
const currentYear = new Date().getFullYear();
const [formData, setFormData] = useState<Partial<Course>>(
initialData || {
name: "",
institutionId: "",
year: currentYear,
semester: 1,
graduationType: "",
createdAt: new Date().toISOString(),
createdBy: userId,
isActive: true,
}
);
const [showToast, setShowToast] = useState(false);
const [error, setError] = useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Validações
if (!formData.name || formData.name.trim().length < 3) {
setError("Nome do curso deve ter pelo menos 3 caracteres");
return;
}
if (!formData.institutionId) {
setError("Selecione uma universidade");
return;
}
if (!formData.graduationType) {
setError("Selecione o tipo de graduação");
return;
}
setShowToast(true);
setTimeout(() => {
onSubmit(formData);
}, 1000);
};
const handleChange = (field: keyof Course, value: any) => {
setFormData((prev) => ({ ...prev, [field]: value }));
setError(""); // Limpa erro ao editar
};
return (
<div className="bg-white rounded-lg shadow-xl overflow-hidden max-w-2xl mx-auto border border-gray-100 slide-up relative">
{/* Success Toast */}
{showToast && (
<div className="absolute top-4 right-4 z-50 bg-brand-black text-white px-6 py-4 rounded shadow-2xl flex items-center space-x-3 fade-in">
<Check className="text-brand-gold h-6 w-6" />
<div>
<h4 className="font-bold text-sm">Sucesso!</h4>
<p className="text-xs text-gray-300">
Curso cadastrado com sucesso.
</p>
</div>
</div>
)}
{/* Form Header */}
<div className="bg-gray-50 border-b px-8 py-6 flex justify-between items-center">
<div className="flex items-center space-x-3">
<GraduationCap className="text-brand-gold h-8 w-8" />
<div>
<h2 className="text-2xl font-serif text-brand-black">
{initialData ? "Editar Curso/Turma" : "Cadastrar Curso/Turma"}
</h2>
<p className="text-sm text-gray-500 mt-1">
Registre as turmas disponíveis para eventos fotográficos
</p>
</div>
</div>
<button
onClick={onCancel}
className="p-2 hover:bg-gray-200 rounded-full transition-colors"
>
<X size={20} className="text-gray-600" />
</button>
</div>
<form onSubmit={handleSubmit} className="p-8 space-y-6">
{/* Erro global */}
{error && (
<div className="bg-red-50 border border-red-200 rounded-lg p-3 flex items-start">
<AlertCircle
size={18}
className="text-red-500 mr-2 flex-shrink-0 mt-0.5"
/>
<p className="text-sm text-red-700">{error}</p>
</div>
)}
{/* Informações do Curso */}
<div className="space-y-4">
<h3 className="text-sm font-semibold text-gray-700 tracking-wide uppercase">
Informações do Curso
</h3>
<Select
label="Universidade*"
options={institutions.map((inst) => ({
value: inst.id,
label: `${inst.name} - ${inst.type}`,
}))}
value={formData.institutionId || ""}
onChange={(e) => handleChange("institutionId", e.target.value)}
required
/>
<Input
label="Nome do Curso/Turma*"
placeholder="Ex: Engenharia Civil 2025, Medicina - Turma A"
value={formData.name || ""}
onChange={(e) => handleChange("name", e.target.value)}
required
/>
<div className="grid grid-cols-3 gap-4">
<Input
label="Ano*"
type="number"
placeholder={currentYear.toString()}
value={formData.year || currentYear}
onChange={(e) => handleChange("year", parseInt(e.target.value))}
min={currentYear - 1}
max={currentYear + 5}
required
/>
<Select
label="Semestre"
options={[
{ value: "1", label: "1º Semestre" },
{ value: "2", label: "2º Semestre" },
]}
value={formData.semester?.toString() || "1"}
onChange={(e) =>
handleChange("semester", parseInt(e.target.value))
}
/>
<Select
label="Tipo*"
options={GRADUATION_TYPES.map((t) => ({ value: t, label: t }))}
value={formData.graduationType || ""}
onChange={(e) => handleChange("graduationType", e.target.value)}
required
/>
</div>
{/* Status Ativo/Inativo */}
<div className="flex items-center space-x-3 pt-2">
<input
type="checkbox"
id="isActive"
checked={formData.isActive !== false}
onChange={(e) => handleChange("isActive", e.target.checked)}
className="w-4 h-4 text-brand-gold border-gray-300 rounded focus:ring-brand-gold"
/>
<label htmlFor="isActive" className="text-sm text-gray-700">
Curso ativo (disponível para seleção em eventos)
</label>
</div>
</div>
{/* Actions */}
<div className="flex justify-end space-x-3 pt-6 border-t">
<Button variant="outline" onClick={onCancel} type="button">
Cancelar
</Button>
<Button type="submit" variant="secondary">
{initialData ? "Salvar Alterações" : "Cadastrar Curso"}
</Button>
</div>
</form>
</div>
);
};