From 8c35b8b6e05235a2ce22902a2a8de8d2fc2d4c70 Mon Sep 17 00:00:00 2001 From: 230417 <230417@epvc.pt> Date: Thu, 26 Feb 2026 17:38:31 +0000 Subject: [PATCH] carregar imagem para barbearia --- web/src/context/AppContext.tsx | 21 ++++++ web/src/pages/Dashboard.tsx | 118 ++++++++++++++++++++++++++++++--- 2 files changed, 129 insertions(+), 10 deletions(-) diff --git a/web/src/context/AppContext.tsx b/web/src/context/AppContext.tsx index 9fdc5b8..2ffbcf5 100644 --- a/web/src/context/AppContext.tsx +++ b/web/src/context/AppContext.tsx @@ -44,6 +44,7 @@ type AppContextValue = State & { addBarber: (shopId: string, barber: Omit) => void; updateBarber: (shopId: string, barber: Barber) => void; deleteBarber: (shopId: string, barberId: string) => void; + updateShopDetails: (shopId: string, payload: Partial) => Promise; refreshShops: () => Promise; }; @@ -455,6 +456,25 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { })); }; + const updateShopDetails: AppContextValue['updateShopDetails'] = async (shopId, payload) => { + // DB Update + const { error } = await supabase + .from('shops') + .update(payload) + .eq('id', shopId); + + if (error) { + console.error('Failed to update shop details:', error); + return; + } + + // Local State Update + setState((s) => ({ + ...s, + shops: s.shops.map((shop) => (shop.id === shopId ? { ...shop, ...payload } : shop)), + })); + }; + const value: AppContextValue = { ...state, login, @@ -478,6 +498,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { addBarber, updateBarber, deleteBarber, + updateShopDetails, refreshShops, }; diff --git a/web/src/pages/Dashboard.tsx b/web/src/pages/Dashboard.tsx index 6f7b546..e6aca82 100644 --- a/web/src/pages/Dashboard.tsx +++ b/web/src/pages/Dashboard.tsx @@ -12,6 +12,7 @@ import { Badge } from '../components/ui/badge'; import { Tabs } from '../components/ui/tabs'; import { currency } from '../lib/format'; import { useApp } from '../context/AppContext'; +import { supabase } from '../lib/supabase'; import { Product } from '../types'; import { BarChart, Bar, CartesianGrid, ResponsiveContainer, Tooltip, XAxis } from 'recharts'; import { CalendarWeekView } from '../components/CalendarWeekView'; @@ -67,7 +68,7 @@ const periods: Record boolean> = { const parseDate = (value: string) => new Date(value.replace(' ', 'T')); -type TabId = 'overview' | 'appointments' | 'history' | 'orders' | 'services' | 'products' | 'barbers'; +type TabId = 'overview' | 'appointments' | 'history' | 'orders' | 'services' | 'products' | 'barbers' | 'settings'; export default function Dashboard() { // Importa estado global interligado com Supabase (ex: updateAppointmentStatus reflete-se na BD) @@ -86,6 +87,7 @@ export default function Dashboard() { deleteProduct, deleteService, deleteBarber, + updateShopDetails, } = useApp(); const shop = shops.find((s) => s.id === user?.shopId); @@ -276,6 +278,38 @@ export default function Dashboard() { setBarberSpecs(''); }; + const [isUploading, setIsUploading] = useState(false); + + const handleImageUpload = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file || !shop) return; + setIsUploading(true); + + try { + const fileExt = file.name.split('.').pop(); + const fileName = `${shop.id}-${Math.random()}.${fileExt}`; + const filePath = `covers/${fileName}`; + + const { error: uploadError } = await supabase.storage + .from('shops') + .upload(filePath, file); + + if (uploadError) throw uploadError; + + const { data } = supabase.storage + .from('shops') + .getPublicUrl(filePath); + + await updateShopDetails(shop.id, { imageUrl: data.publicUrl }); + alert('Foto de capa atualizada com sucesso!'); + } catch (error) { + console.error('Erro ao fazer upload da imagem:', error); + alert('Erro ao fazer upload. Verifique se criou o bucket "shops" corretamente no Supabase.'); + } finally { + setIsUploading(false); + } + }; + const tabs = [ { id: 'overview' as TabId, label: 'Visão Geral', icon: BarChart3 }, { id: 'appointments' as TabId, label: 'Agendamentos', icon: Calendar }, @@ -284,6 +318,7 @@ export default function Dashboard() { { id: 'services' as TabId, label: 'Serviços', icon: Scissors }, { id: 'products' as TabId, label: 'Produtos', icon: Package }, { id: 'barbers' as TabId, label: 'Barbeiros', icon: Users }, + { id: 'settings' as TabId, label: 'Definições', icon: Settings }, ]; return ( @@ -300,8 +335,8 @@ export default function Dashboard() { key={p} onClick={() => setPeriod(p)} className={`px-3 py-1.5 rounded-lg text-xs font-medium border transition-all ${period === p - ? 'border-amber-500 bg-amber-50 text-amber-700 shadow-sm' - : 'border-slate-200 text-slate-700 hover:border-amber-300 hover:bg-amber-50/50' + ? 'border-amber-500 bg-amber-50 text-amber-700 shadow-sm' + : 'border-slate-200 text-slate-700 hover:border-amber-300 hover:bg-amber-50/50' }`} > {p === 'mes' ? 'Mês' : p === 'hoje' ? 'Hoje' : p === 'semana' ? 'Semana' : 'Total'} @@ -488,7 +523,9 @@ export default function Dashboard() { Calendário -