alterações design

This commit is contained in:
2026-03-17 10:44:37 +00:00
parent c9306f2dcb
commit bdc4b56d49
2 changed files with 207 additions and 100 deletions

View File

@@ -141,6 +141,7 @@ function DashboardInner({ shop }: { shop: BarberShop }) {
const [barberName, setBarberName] = useState('');
const [barberSpecs, setBarberSpecs] = useState('');
const [barberSearchQuery, setBarberSearchQuery] = useState('');
// Settings states
const [editShopName, setEditShopName] = useState(shop.name);
@@ -249,12 +250,11 @@ function DashboardInner({ shop }: { shop: BarberShop }) {
if (!barberName.trim()) return;
addBarber(shop.id, {
name: barberName,
imageUrl: '', // Foto será adicionada depois
specialties: barberSpecs.split(',').map((s) => s.trim()).filter(Boolean),
imageUrl: '',
specialties: [],
schedule: [],
});
setBarberName('');
setBarberSpecs('');
};
const [uploadingBarberId, setUploadingBarberId] = useState<string | null>(null);
@@ -349,7 +349,7 @@ function DashboardInner({ shop }: { shop: BarberShop }) {
{ id: 'orders', label: 'Pedidos', icon: ShoppingBag, badge: pendingOrders > 0 ? pendingOrders : undefined },
{ id: 'services', label: 'Serviços', icon: Scissors },
{ id: 'products', label: 'Produtos', icon: Package },
{ id: 'barbers', label: 'Barbeiros', icon: Users },
{ id: 'barbers', label: 'Profissionais', icon: Users },
{ id: 'settings', label: 'Definições', icon: Settings },
];
@@ -897,82 +897,104 @@ function DashboardInner({ shop }: { shop: BarberShop }) {
{activeTab === 'barbers' && (
<div className="space-y-6">
<Card className="p-6">
<div className="flex items-center justify-between mb-4">
<h2 className="text-lg font-bold text-slate-900">Barbeiros</h2>
<Badge color="slate" variant="soft">{shop.barbers.length} barbeiros</Badge>
<div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
<h2 className="text-2xl font-bold text-slate-900">Profissionais</h2>
</div>
{/* Barra de Pesquisa Estilo Screenshot */}
<div className="relative group">
<div className="absolute left-4 top-1/2 -translate-y-1/2 text-slate-400 group-focus-within:text-indigo-500 transition-colors">
<Search size={20} />
</div>
<div className="space-y-3 mb-6">
{shop.barbers.map((b) => (
<div key={b.id} className="p-4 border border-slate-200 rounded-lg">
<div className="flex items-center justify-between mb-4">
<div className="flex items-center gap-4">
<div className="relative group/avatar">
<div className="w-16 h-16 rounded-2xl overflow-hidden border-2 border-slate-100 bg-slate-50 flex items-center justify-center">
{b.imageUrl ? (
<img src={b.imageUrl} alt={b.name} className="w-full h-full object-cover" />
) : (
<Users size={24} className="text-slate-400" />
)}
</div>
<input
type="file"
id={`barber-img-${b.id}`}
className="hidden"
accept="image/*"
onChange={(e) => handleBarberImageUpload(b.id, e)}
/>
<label
htmlFor={`barber-img-${b.id}`}
className="absolute inset-0 bg-black/40 text-white flex items-center justify-center rounded-2xl opacity-0 group-hover/avatar:opacity-100 cursor-pointer transition-opacity"
>
{uploadingBarberId === b.id ? <RefreshCw size={14} className="animate-spin" /> : <Plus size={14} />}
</label>
</div>
<div>
<p className="font-bold text-slate-900 text-lg">{b.name}</p>
<p className="text-sm text-slate-600">
{b.specialties.length > 0 ? b.specialties.join(', ') : 'Sem especialidades'}
</p>
</div>
<input
type="text"
placeholder="Pesquisar"
value={barberSearchQuery}
onChange={(e) => setBarberSearchQuery(e.target.value)}
className="w-full h-14 pl-12 pr-4 bg-[#0d0d0d] border border-white/5 rounded-xl text-white placeholder:text-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/20 transition-all font-medium"
/>
</div>
{/* Grelha de Profissionais */}
<div className="grid md:grid-cols-2 gap-4">
{shop.barbers
.filter(b => b.name.toLowerCase().includes(barberSearchQuery.toLowerCase()))
.map((b) => (
<div key={b.id} className="group relative flex items-center gap-4 p-4 bg-[#0d0d0d] border border-white/5 rounded-[2rem] hover:border-indigo-500/30 transition-all duration-300 shadow-xl">
{/* Avatar squircle robusto */}
<div className="relative">
<div className="w-24 h-24 rounded-[1.5rem] overflow-hidden border-2 border-white/5 bg-slate-900 flex items-center justify-center transition-transform group-hover:scale-105 duration-500">
{b.imageUrl ? (
<img src={b.imageUrl} alt={b.name} className="w-full h-full object-cover" />
) : (
<Users size={32} className="text-slate-700" />
)}
</div>
<Button variant="danger" size="sm" onClick={() => deleteBarber(shop.id, b.id)}>
{/* Botão de Upload Escondido */}
<input
type="file"
id={`barber-img-${b.id}`}
className="hidden"
accept="image/*"
onChange={(e) => handleBarberImageUpload(b.id, e)}
/>
<label
htmlFor={`barber-img-${b.id}`}
className="absolute inset-0 bg-black/40 text-white flex items-center justify-center rounded-[1.5rem] opacity-0 group-hover:opacity-100 cursor-pointer transition-opacity"
>
{uploadingBarberId === b.id ? <RefreshCw size={20} className="animate-spin" /> : <Plus size={20} />}
</label>
</div>
{/* Info Profissional */}
<div className="flex-1">
<h3 className="text-xl font-bold text-white tracking-tight leading-tight">{b.name}</h3>
{/* O utilizador pediu para ignorar observações/especialidades, removido para o look "mais limpo" do screenshot */}
</div>
{/* Ações Rápidas */}
<div className="flex flex-col gap-2 opacity-0 group-hover:opacity-100 transition-opacity">
<Button
variant="danger"
size="sm"
className="rounded-xl h-10 w-10 p-0 flex items-center justify-center bg-transparent border-white/10 hover:bg-red-500/20"
onClick={() => deleteBarber(shop.id, b.id)}
>
<Trash2 size={16} />
</Button>
</div>
</div>
))}
{shop.barbers.length === 0 && (
<div className="text-center py-12">
<Users size={48} className="mx-auto text-slate-300 mb-3" />
<p className="text-slate-600 font-medium">Nenhum barbeiro registado</p>
</div>
)}
</div>
<div className="border-t border-slate-200 pt-4">
<h3 className="text-base font-semibold text-slate-900 mb-3">Adicionar novo barbeiro</h3>
<div className="grid md:grid-cols-3 gap-3">
{shop.barbers.filter(b => b.name.toLowerCase().includes(barberSearchQuery.toLowerCase())).length === 0 && (
<div className="col-span-full py-12 text-center bg-[#0d0d0d] border border-white/5 rounded-[2rem]">
<Users size={48} className="mx-auto text-slate-800 mb-3" />
<p className="text-slate-500 font-medium italic">Nenhum profissional encontrado com esse nome.</p>
</div>
)}
</div>
{/* Formulário de Adição (Mantido mas modernizado) */}
<div className="pt-8 mt-4 border-t border-slate-200">
<h3 className="text-base font-semibold text-slate-900 mb-4">Novo Profissional</h3>
<div className="grid md:grid-cols-3 gap-3">
<div className="md:col-span-2">
<Input
label="Nome"
label="Nome do Profissional"
placeholder="Ex: João Silva"
value={barberName}
onChange={(e) => setBarberName(e.target.value)}
/>
<Input
label="Especialidades"
placeholder="Fade, Navalha, Barba"
value={barberSpecs}
onChange={(e) => setBarberSpecs(e.target.value)}
/>
<div className="flex items-end">
<Button onClick={addNewBarber} className="w-full">
<PlusIcon size={16} className="mr-2" />
Adicionar
</Button>
</div>
</div>
<div className="flex items-end">
<Button onClick={addNewBarber} className="w-full bg-indigo-600 hover:bg-indigo-700 h-11">
<PlusIcon size={16} className="mr-2" />
Adicionar
</Button>
</div>
</div>
</Card>
</div>
</div>
)}