From af1f79ec7bc7a4415dda2a874a7b84136e398d78 Mon Sep 17 00:00:00 2001 From: 230417 <230417@epvc.pt> Date: Tue, 12 May 2026 17:15:05 +0100 Subject: [PATCH] feat: implement automatic shop creation for barbers and add error handling to data mutation methods --- src/context/AppContext.tsx | 58 +++++++++++++++++++++++++++++++------- src/pages/Dashboard.tsx | 38 ++++++++++++++++--------- 2 files changed, 73 insertions(+), 23 deletions(-) diff --git a/src/context/AppContext.tsx b/src/context/AppContext.tsx index b50982a..8715a37 100644 --- a/src/context/AppContext.tsx +++ b/src/context/AppContext.tsx @@ -91,22 +91,39 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { const applySupabaseUser = async (authUser: any): Promise => { if (!authUser) return undefined; - const { data: prof } = await supabase + const { data: prof, error: profErr } = await supabase .from('profiles') - .select('shop_id, role, name, fcm_token') + .select('shop_id, role, name, fcm_token, shop_name') .eq('id', authUser.id) .single(); + const role = (prof?.role as any) || authUser.user_metadata?.role || 'cliente'; + const shopId = prof?.shop_id || (role === 'barbearia' ? authUser.id : undefined); + const nextUser: User = { id: authUser.id, name: prof?.name || authUser.user_metadata?.name || authUser.email?.split('@')[0] || 'Utilizador', email: authUser.email || '', password: '', - role: (prof?.role as any) || authUser.user_metadata?.role || 'cliente', - shopId: prof?.shop_id || undefined, + role, + shopId, fcmToken: prof?.fcm_token || undefined, }; + // If it's a barber and the shop record doesn't exist, create it (matching web logic) + if (role === 'barbearia' && shopId) { + const { data: existingShop } = await supabase.from('shops').select('id').eq('id', shopId).single(); + if (!existingShop) { + const shopName = prof?.shop_name || authUser.user_metadata?.shopName || `Barbearia de ${nextUser.name}`; + await supabase.from('shops').insert([{ + id: shopId, + name: shopName, + address: 'Endereço a definir', + rating: 0, + }]); + } + } + setUser(nextUser); registerForPushNotificationsAsync().then((token) => { @@ -366,13 +383,17 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { const clearCart = () => setCart([]); const addService = async (shopId: string, service: Omit) => { - await supabase.from('services').insert([{ + const { error } = await supabase.from('services').insert([{ shop_id: shopId, name: service.name, price: service.price, duration: service.duration, barber_ids: service.barberIds || [], }]); + if (error) { + console.error('Erro addService:', error); + throw error; + } await refreshShops(); }; @@ -392,7 +413,16 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { }; const addProduct = async (shopId: string, product: Omit) => { - await supabase.from('products').insert([{ shop_id: shopId, ...product }]); + const { error } = await supabase.from('products').insert([{ + shop_id: shopId, + name: product.name, + price: product.price, + stock: product.stock + }]); + if (error) { + console.error('Erro addProduct:', error); + throw error; + } await refreshShops(); }; @@ -408,13 +438,17 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { }; const addBarber = async (shopId: string, barber: Omit) => { - await supabase.from('barbers').insert([{ + const { error } = await supabase.from('barbers').insert([{ shop_id: shopId, name: barber.name, specialties: barber.specialties, - schedule: barber.schedule, + schedule: barber.schedule || [], image_url: barber.imageUrl, }]); + if (error) { + console.error('Erro addBarber:', error); + throw error; + } await refreshShops(); }; @@ -436,6 +470,7 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { const updateShopDetails = async (shopId: string, payload: Partial) => { const { services, products, barbers, id, imageUrl, paymentMethods, socialNetworks, contacts, schedule, ...rest } = payload; const updateData: Record = { ...rest }; + if (imageUrl !== undefined) updateData.image_url = imageUrl; if (paymentMethods !== undefined) updateData.payment_methods = paymentMethods; if (socialNetworks !== undefined) updateData.social_networks = socialNetworks; @@ -443,13 +478,16 @@ export const AppProvider = ({ children }: { children: React.ReactNode }) => { if (schedule !== undefined) updateData.schedule = schedule; const { error } = await supabase.from('shops').update(updateData).eq('id', shopId); - if (error) throw error; + if (error) { + console.error('Erro updateShopDetails:', error); + throw error; + } if (payload.name) { await supabase.from('profiles').update({ shop_name: payload.name }).eq('shop_id', shopId); } - setShops((prev) => prev.map((shop) => (shop.id === shopId ? { ...shop, ...payload } : shop))); + await refreshShops(); }; const submitReview = async (shopId: string, appointmentId: string, rating: number, comment: string) => { diff --git a/src/pages/Dashboard.tsx b/src/pages/Dashboard.tsx index ff18003..14cb836 100644 --- a/src/pages/Dashboard.tsx +++ b/src/pages/Dashboard.tsx @@ -262,9 +262,13 @@ export default function Dashboard() { setFormSvc({...formSvc, duration: t})} /> @@ -293,9 +297,13 @@ export default function Dashboard() { setFormProd({...formProd, stock: t})} /> @@ -324,13 +332,17 @@ export default function Dashboard() { setFormBarb({...formBarb, name: t})} /> setFormBarb({...formBarb, specialties: t})} />