diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 83707ca..f9c9546 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -57,13 +57,17 @@ async function dispatchRefocus(reason: string) { try { await refreshWithTimeout - } catch (err) { - console.warn("SIBU | Auth zombie detectado o red muerta. Reseteando sesión y app.", err) - // Fall fast & hard: Romper cualquier loop infinito o socket huérfano - document.body.style.opacity = '0' - await supabase.auth.signOut() - window.location.reload() - return // No despachar `app-refocus`, la app está muriendo + } catch (err: any) { + console.warn("SIBU | Error al verificar sesión en refocus (timeout o red).", err) + // FIX CRÍTICO: Si el error es de timeout (5s), la persona estaba eligiendo ruta o + // subiendo archivo y la red tardó. NUNCA expulsarla automáticamente en timeout. + // El caché local de Supabase ya mantiene su sesión válida bajo el capó. + if (err.message === "Auth refresh timeout") { + console.log("SIBU | Ignorando timeout, manteniendo sesión optimista.") + } else { + // Solo si hay un error real de Auth (sesión vencida rechazada por Supabase) + // se cierra sesión, pero no haremos signOut agresivo sin confirmar. + } } } diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 1f0ac59..0511f7e 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -154,6 +154,12 @@ const router = createRouter({ component: () => import('@/views/AdminShuttles.vue'), meta: { requiresAuth: true, role: 'ADMIN' } }, + { + path: '/admin/business-edit/:id?', + name: 'admin-business-editor', + component: () => import('@/views/AdminBusinessEditor.vue'), + meta: { requiresAuth: true } // available for promoters too + }, // ─── Vistas de Roles Especiales ────────────────────────────────────── { diff --git a/frontend/src/views/AdminBusinessEditor.vue b/frontend/src/views/AdminBusinessEditor.vue new file mode 100644 index 0000000..127fb5b --- /dev/null +++ b/frontend/src/views/AdminBusinessEditor.vue @@ -0,0 +1,641 @@ + + + + + diff --git a/frontend/src/views/PromoterDashboard.vue b/frontend/src/views/PromoterDashboard.vue index 26042d3..75d75cc 100644 --- a/frontend/src/views/PromoterDashboard.vue +++ b/frontend/src/views/PromoterDashboard.vue @@ -24,11 +24,7 @@ const categories = ['Todas', 'Restaurante', 'Turismo', 'Bebidas', 'Comercio'] // Modals const showModal = ref(false) -const showBusinessModal = ref(false) const isEditing = ref(false) -const isEditingBusiness = ref(false) -const businessImageFile = ref(null) -const businessImagePreview = ref(null) // Current data @@ -47,24 +43,6 @@ const currentCoupon = ref>({ is_active: true }) -const currentBusiness = ref>({ - name: '', - address: '', - phone: '', - image_url: '', - social_media: '', - category: 'Restaurante', - area: 'Boquete', - description: '', - website: '', - // Template fields - schedule: '', - whatsapp: '', - instagram: '', - facebook: '', - gallery_images: [] -}) - const userName = localStorage.getItem('user_name') || 'Promotor' onMounted(async () => { @@ -174,82 +152,15 @@ async function deleteShuttle(id: string) { } // Business Methods +import { useRouter } from 'vue-router' +const localRouter = useRouter() + function openCreateBusinessModal() { - isEditingBusiness.value = false - currentBusiness.value = { - name: '', - address: '', - phone: '', - image_url: '', - social_media: '', - category: 'Restaurante', - area: 'Boquete', - description: '', - website: '', - schedule: '', - whatsapp: '', - instagram: '', - facebook: '', - gallery_images: [] - } - showBusinessModal.value = true - businessImageFile.value = null - businessImagePreview.value = null -} - - -function handleBusinessImage(event: any) { - const file = event.target.files[0] - if (file) { - businessImageFile.value = file - businessImagePreview.value = URL.createObjectURL(file) - } + localRouter.push('/admin/business-edit/new') } function openEditBusinessModal(biz: Business) { - isEditingBusiness.value = true - currentBusiness.value = { ...biz } - showBusinessModal.value = true - businessImageFile.value = null - businessImagePreview.value = getImageUrl(biz.image_url) -} - -async function saveBusiness() { - try { - const formData = new FormData() - formData.append('name', currentBusiness.value.name || '') - formData.append('category', currentBusiness.value.category || 'Restaurante') - formData.append('address', currentBusiness.value.address || '') - formData.append('phone', currentBusiness.value.phone || '') - formData.append('social_media', currentBusiness.value.social_media || '') - formData.append('area', currentBusiness.value.area || 'Boquete') - formData.append('description', currentBusiness.value.description || '') - formData.append('website', currentBusiness.value.website || '') - // Template fields - formData.append('schedule', currentBusiness.value.schedule || '') - formData.append('whatsapp', currentBusiness.value.whatsapp || '') - formData.append('instagram', currentBusiness.value.instagram || '') - formData.append('facebook', currentBusiness.value.facebook || '') - // gallery_images handled separately via JSON - if (currentBusiness.value.gallery_images?.length) { - formData.append('gallery_images', JSON.stringify(currentBusiness.value.gallery_images)) - } - - if (businessImageFile.value) { - formData.append('image', businessImageFile.value) - } - - if (isEditingBusiness.value && currentBusiness.value.id) { - await businessService.updateBusiness(currentBusiness.value.id, formData) - } else { - await businessService.createBusiness(formData) - } - showBusinessModal.value = false - await loadBusinesses() - } catch (e) { - console.error('Error saving business:', e) - alert('Error al guardar el negocio') - } + localRouter.push(`/admin/business-edit/${biz.id}`) } async function deleteBusiness(id: string) { @@ -704,125 +615,6 @@ async function toggleCouponStatus(coupon: Coupon) { - -