248 lines
7.9 KiB
TypeScript
248 lines
7.9 KiB
TypeScript
|
|
import React, { useState } from 'react';
|
|
import { Institution, Address } from '../types';
|
|
import { Input, Select } from './Input';
|
|
import { Button } from './Button';
|
|
import { Building2, X, Check } from 'lucide-react';
|
|
|
|
interface InstitutionFormProps {
|
|
onCancel: () => void;
|
|
onSubmit: (data: Partial<Institution>) => void;
|
|
initialData?: Institution;
|
|
userId: string;
|
|
}
|
|
|
|
const INSTITUTION_TYPES = [
|
|
'Universidade Pública',
|
|
'Universidade Privada',
|
|
'Faculdade',
|
|
'Instituto Federal',
|
|
'Centro Universitário',
|
|
'Campus Universitário'
|
|
];
|
|
|
|
export const InstitutionForm: React.FC<InstitutionFormProps> = ({
|
|
onCancel,
|
|
onSubmit,
|
|
initialData,
|
|
userId
|
|
}) => {
|
|
const [formData, setFormData] = useState<Partial<Institution>>(initialData || {
|
|
name: '',
|
|
type: '',
|
|
cnpj: '',
|
|
phone: '',
|
|
email: '',
|
|
description: '',
|
|
ownerId: userId,
|
|
address: {
|
|
street: '',
|
|
number: '',
|
|
city: '',
|
|
state: '',
|
|
zip: ''
|
|
}
|
|
});
|
|
|
|
const [showToast, setShowToast] = useState(false);
|
|
const [stateError, setStateError] = useState('');
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
setShowToast(true);
|
|
setTimeout(() => {
|
|
onSubmit(formData);
|
|
}, 1000);
|
|
};
|
|
|
|
const handleChange = (field: keyof Institution, value: any) => {
|
|
setFormData(prev => ({ ...prev, [field]: value }));
|
|
};
|
|
|
|
const handleAddressChange = (field: keyof Address, value: string) => {
|
|
setFormData(prev => ({
|
|
...prev,
|
|
address: {
|
|
...prev.address!,
|
|
[field]: value
|
|
}
|
|
}));
|
|
};
|
|
|
|
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">Universidade cadastrada 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">
|
|
<Building2 className="text-brand-gold h-8 w-8" />
|
|
<div>
|
|
<h2 className="text-2xl font-serif text-brand-black">
|
|
{initialData ? 'Editar Universidade' : 'Cadastrar Universidade'}
|
|
</h2>
|
|
<p className="text-sm text-gray-500 mt-1">
|
|
Registre a universidade onde os eventos fotográficos serão realizados
|
|
</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">
|
|
|
|
{/* Informações Básicas */}
|
|
<div className="space-y-4">
|
|
<h3 className="text-sm font-semibold text-gray-700 tracking-wide uppercase">
|
|
Informações Básicas
|
|
</h3>
|
|
|
|
<Input
|
|
label="Nome da Universidade*"
|
|
placeholder="Ex: Universidade Federal do Rio Grande do Sul"
|
|
value={formData.name || ''}
|
|
onChange={(e) => handleChange('name', e.target.value)}
|
|
required
|
|
/>
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<Select
|
|
label="Tipo de Universidade*"
|
|
options={INSTITUTION_TYPES.map(t => ({ value: t, label: t }))}
|
|
value={formData.type || ''}
|
|
onChange={(e) => handleChange('type', e.target.value)}
|
|
required
|
|
/>
|
|
|
|
<Input
|
|
label="CNPJ (Opcional)"
|
|
placeholder="00.000.000/0000-00"
|
|
value={formData.cnpj || ''}
|
|
onChange={(e) => handleChange('cnpj', e.target.value)}
|
|
mask="cnpj"
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-2 gap-4">
|
|
<Input
|
|
label="Telefone*"
|
|
type="tel"
|
|
placeholder="(00) 00000-0000"
|
|
value={formData.phone || ''}
|
|
onChange={(e) => handleChange('phone', e.target.value)}
|
|
mask="phone"
|
|
required
|
|
/>
|
|
|
|
<Input
|
|
label="E-mail*"
|
|
type="email"
|
|
placeholder="contato@instituicao.com"
|
|
value={formData.email || ''}
|
|
onChange={(e) => handleChange('email', e.target.value)}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label className="block text-sm font-medium text-gray-700 mb-1 tracking-wide uppercase text-xs">
|
|
Descrição (Opcional)
|
|
</label>
|
|
<textarea
|
|
className="w-full border border-gray-300 rounded-sm p-3 focus:outline-none focus:border-brand-gold h-24 text-sm"
|
|
placeholder="Ex: Campus principal, informações sobre o campus, áreas para eventos..."
|
|
value={formData.description || ''}
|
|
onChange={(e) => handleChange('description', e.target.value)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Endereço */}
|
|
<div className="space-y-4 border-t pt-6">
|
|
<h3 className="text-sm font-semibold text-gray-700 tracking-wide uppercase">
|
|
Endereço (Opcional)
|
|
</h3>
|
|
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<div className="col-span-2">
|
|
<Input
|
|
label="Rua"
|
|
placeholder="Nome da rua"
|
|
value={formData.address?.street || ''}
|
|
onChange={(e) => handleAddressChange('street', e.target.value)}
|
|
/>
|
|
</div>
|
|
<Input
|
|
label="Número"
|
|
placeholder="123"
|
|
value={formData.address?.number || ''}
|
|
onChange={(e) => {
|
|
const value = e.target.value.replace(/\D/g, '');
|
|
handleAddressChange('number', value);
|
|
}}
|
|
type="text"
|
|
inputMode="numeric"
|
|
/>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-3 gap-4">
|
|
<Input
|
|
label="Cidade"
|
|
placeholder="Cidade"
|
|
value={formData.address?.city || ''}
|
|
onChange={(e) => handleAddressChange('city', e.target.value)}
|
|
/>
|
|
<Input
|
|
label="Estado"
|
|
placeholder="UF"
|
|
value={formData.address?.state || ''}
|
|
onChange={(e) => {
|
|
const hasNumbers = /[0-9]/.test(e.target.value);
|
|
if (hasNumbers) {
|
|
setStateError('O campo Estado aceita apenas letras');
|
|
setTimeout(() => setStateError(''), 3000);
|
|
}
|
|
const value = e.target.value.replace(/[0-9]/g, '').toUpperCase();
|
|
handleAddressChange('state', value);
|
|
}}
|
|
maxLength={2}
|
|
error={stateError}
|
|
/>
|
|
<Input
|
|
label="CEP"
|
|
placeholder="00000-000"
|
|
value={formData.address?.zip || ''}
|
|
onChange={(e) => handleAddressChange('zip', e.target.value)}
|
|
mask="cep"
|
|
/>
|
|
</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 Universidade'}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
);
|
|
};
|