feat: redesign superadmin agencies list, implement flat design, add date filters, and fix UI bugs
This commit is contained in:
364
front-end-dash.aggios.app/app/superadmin/agencies/new/page.tsx
Normal file
364
front-end-dash.aggios.app/app/superadmin/agencies/new/page.tsx
Normal file
@@ -0,0 +1,364 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function NewAgencyPage() {
|
||||
const router = useRouter();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState('');
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
// Agência
|
||||
agencyName: '',
|
||||
subdomain: '',
|
||||
cnpj: '',
|
||||
razaoSocial: '',
|
||||
description: '',
|
||||
website: '',
|
||||
industry: '',
|
||||
phone: '',
|
||||
teamSize: '',
|
||||
|
||||
// Endereço
|
||||
cep: '',
|
||||
state: '',
|
||||
city: '',
|
||||
neighborhood: '',
|
||||
street: '',
|
||||
number: '',
|
||||
complement: '',
|
||||
|
||||
// Admin
|
||||
adminEmail: '',
|
||||
adminPassword: '',
|
||||
adminName: '',
|
||||
});
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
setLoading(true);
|
||||
setError('');
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/admin/agencies/register', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${localStorage.getItem('token')}`,
|
||||
},
|
||||
body: JSON.stringify(formData),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.text();
|
||||
throw new Error(errorData || 'Erro ao criar agência');
|
||||
}
|
||||
|
||||
router.push('/superadmin/agencies');
|
||||
} catch (err: any) {
|
||||
setError(err.message);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[e.target.name]: e.target.value
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-8 h-full overflow-auto">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-2xl font-bold text-gray-900">Nova Agência</h1>
|
||||
<p className="text-gray-600 mt-2">Cadastre uma nova agência no sistema Aggios</p>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-800">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-8">
|
||||
{/* Informações da Agência */}
|
||||
<section className="bg-white p-6 rounded-lg border border-gray-200">
|
||||
<h2 className="text-lg font-semibold mb-4 text-gray-900">Informações da Agência</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Nome da Agência *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="agencyName"
|
||||
required
|
||||
value={formData.agencyName}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Subdomínio *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="subdomain"
|
||||
required
|
||||
value={formData.subdomain}
|
||||
onChange={handleChange}
|
||||
placeholder="exemplo"
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Será usado como: exemplo.aggios.app</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">CNPJ</label>
|
||||
<input
|
||||
type="text"
|
||||
name="cnpj"
|
||||
value={formData.cnpj}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Razão Social</label>
|
||||
<input
|
||||
type="text"
|
||||
name="razaoSocial"
|
||||
value={formData.razaoSocial}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Website</label>
|
||||
<input
|
||||
type="url"
|
||||
name="website"
|
||||
value={formData.website}
|
||||
onChange={handleChange}
|
||||
placeholder="https://"
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Telefone</label>
|
||||
<input
|
||||
type="tel"
|
||||
name="phone"
|
||||
value={formData.phone}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Setor</label>
|
||||
<input
|
||||
type="text"
|
||||
name="industry"
|
||||
value={formData.industry}
|
||||
onChange={handleChange}
|
||||
placeholder="Ex: Tecnologia, Marketing"
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Tamanho do Time</label>
|
||||
<select
|
||||
name="teamSize"
|
||||
value={formData.teamSize}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
>
|
||||
<option value="">Selecione</option>
|
||||
<option value="1-10">1-10 pessoas</option>
|
||||
<option value="11-50">11-50 pessoas</option>
|
||||
<option value="51-200">51-200 pessoas</option>
|
||||
<option value="201+">201+ pessoas</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Descrição</label>
|
||||
<textarea
|
||||
name="description"
|
||||
value={formData.description}
|
||||
onChange={handleChange}
|
||||
rows={3}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Endereço */}
|
||||
<section className="bg-white p-6 rounded-lg border border-gray-200">
|
||||
<h2 className="text-lg font-semibold mb-4 text-gray-900">Endereço</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">CEP</label>
|
||||
<input
|
||||
type="text"
|
||||
name="cep"
|
||||
value={formData.cep}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Estado</label>
|
||||
<input
|
||||
type="text"
|
||||
name="state"
|
||||
value={formData.state}
|
||||
onChange={handleChange}
|
||||
maxLength={2}
|
||||
placeholder="SP"
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Cidade</label>
|
||||
<input
|
||||
type="text"
|
||||
name="city"
|
||||
value={formData.city}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Bairro</label>
|
||||
<input
|
||||
type="text"
|
||||
name="neighborhood"
|
||||
value={formData.neighborhood}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Número</label>
|
||||
<input
|
||||
type="text"
|
||||
name="number"
|
||||
value={formData.number}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Rua</label>
|
||||
<input
|
||||
type="text"
|
||||
name="street"
|
||||
value={formData.street}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Complemento</label>
|
||||
<input
|
||||
type="text"
|
||||
name="complement"
|
||||
value={formData.complement}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Administrador */}
|
||||
<section className="bg-white p-6 rounded-lg border border-gray-200">
|
||||
<h2 className="text-lg font-semibold mb-4 text-gray-900">Administrador da Agência</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Nome do Admin *
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="adminName"
|
||||
required
|
||||
value={formData.adminName}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Email do Admin *
|
||||
</label>
|
||||
<input
|
||||
type="email"
|
||||
name="adminEmail"
|
||||
required
|
||||
value={formData.adminEmail}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Senha do Admin *
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="adminPassword"
|
||||
required
|
||||
minLength={8}
|
||||
value={formData.adminPassword}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">Mínimo 8 caracteres</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Botões */}
|
||||
<div className="flex gap-3 justify-end">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => router.back()}
|
||||
className="px-6 py-2 border border-gray-300 rounded-md hover:bg-gray-50 transition-colors"
|
||||
>
|
||||
Cancelar
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={loading}
|
||||
className="px-6 py-2 bg-purple-600 text-white rounded-md hover:bg-purple-700 transition-colors disabled:opacity-50"
|
||||
>
|
||||
{loading ? 'Criando...' : 'Criar Agência'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user