Add POI feature and imporve the overall backend implementation
This commit is contained in:
@@ -13,26 +13,26 @@ export const getDemoTourSteps = (): DriveStep[] => [
|
||||
{
|
||||
element: '[data-tour="dashboard-stats"]',
|
||||
popover: {
|
||||
title: 'Tu Panel de Control',
|
||||
description: 'Todo lo importante en un vistazo: ventas del día, pedidos pendientes, productos vendidos y alertas de stock crítico. Empieza tu día aquí en 30 segundos.',
|
||||
title: 'Estado de Salud de Tu Panadería',
|
||||
description: 'Aquí ves el estado general de tu negocio en tiempo real: órdenes pendientes, alertas de stock crítico, reducción de desperdicio y ahorro mensual. Todo lo importante en un vistazo para empezar el día en 30 segundos.',
|
||||
side: 'bottom',
|
||||
align: 'start',
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '[data-tour="real-time-alerts"]',
|
||||
popover: {
|
||||
title: 'El Sistema Te Avisa de Todo',
|
||||
description: 'Olvídate de vigilar el stock constantemente. El sistema te alerta automáticamente de ingredientes bajos, pedidos urgentes, predicciones de demanda y oportunidades de producción. Tu asistente 24/7.',
|
||||
side: 'top',
|
||||
align: 'start',
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '[data-tour="pending-po-approvals"]',
|
||||
popover: {
|
||||
title: 'Qué Comprar Hoy (Ya Calculado)',
|
||||
description: 'Cada mañana el sistema analiza automáticamente tus ventas, pronósticos y stock, y te dice exactamente qué ingredientes comprar. Solo tienes que revisar y aprobar con un clic. Adiós a Excel y cálculos manuales.',
|
||||
title: '¿Qué Requiere Tu Atención?',
|
||||
description: 'Aquí aparecen las acciones que necesitan tu aprobación: órdenes de compra generadas automáticamente, lotes de producción sugeridos, y otras decisiones importantes. Revisa, aprueba o modifica con un clic.',
|
||||
side: 'top',
|
||||
align: 'start',
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '[data-tour="real-time-alerts"]',
|
||||
popover: {
|
||||
title: 'Lo Que el Sistema Hizo Por Ti',
|
||||
description: 'El sistema trabaja 24/7 analizando datos, generando pronósticos y creando planes. Aquí ves un resumen de las decisiones automáticas que tomó: órdenes generadas, producción planificada y optimizaciones realizadas.',
|
||||
side: 'top',
|
||||
align: 'start',
|
||||
},
|
||||
@@ -114,26 +114,26 @@ export const getMobileTourSteps = (): DriveStep[] => [
|
||||
{
|
||||
element: '[data-tour="dashboard-stats"]',
|
||||
popover: {
|
||||
title: 'Tu Panel de Control',
|
||||
description: 'Todo lo importante en un vistazo. Empieza tu día aquí en 30 segundos.',
|
||||
title: 'Estado de Tu Panadería',
|
||||
description: 'Estado de salud del negocio en tiempo real. Todo lo importante en un vistazo para empezar el día en 30 segundos.',
|
||||
side: 'bottom',
|
||||
align: 'start',
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '[data-tour="real-time-alerts"]',
|
||||
popover: {
|
||||
title: 'El Sistema Te Avisa',
|
||||
description: 'Olvídate de vigilar el stock. Alertas automáticas de todo lo importante. Tu asistente 24/7.',
|
||||
side: 'top',
|
||||
align: 'start',
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '[data-tour="pending-po-approvals"]',
|
||||
popover: {
|
||||
title: 'Qué Comprar (Ya Calculado)',
|
||||
description: 'Cada mañana el sistema calcula qué ingredientes comprar. Solo aprueba con un clic. Adiós Excel.',
|
||||
title: '¿Qué Requiere Atención?',
|
||||
description: 'Acciones que necesitan tu aprobación: compras, producción y decisiones. Revisa y aprueba con un clic.',
|
||||
side: 'top',
|
||||
align: 'start',
|
||||
},
|
||||
},
|
||||
{
|
||||
element: '[data-tour="real-time-alerts"]',
|
||||
popover: {
|
||||
title: 'Lo Que el Sistema Hizo',
|
||||
description: 'Resumen de decisiones automáticas: órdenes generadas, producción planificada, optimizaciones. Tu asistente 24/7.',
|
||||
side: 'top',
|
||||
align: 'start',
|
||||
},
|
||||
|
||||
@@ -71,8 +71,8 @@ export const useDemoTour = () => {
|
||||
}, 500);
|
||||
}, [navigate]);
|
||||
|
||||
const startTour = useCallback((fromStep: number = 0) => {
|
||||
console.log('[useDemoTour] startTour called with fromStep:', fromStep);
|
||||
const startTour = useCallback((fromStep: number = 0, retryCount: number = 0) => {
|
||||
console.log('[useDemoTour] startTour called with fromStep:', fromStep, 'retry:', retryCount);
|
||||
|
||||
// Check if we're already on the dashboard
|
||||
const currentPath = window.location.pathname;
|
||||
@@ -81,7 +81,7 @@ export const useDemoTour = () => {
|
||||
// Store tour intent in sessionStorage before navigation
|
||||
sessionStorage.setItem('demo_tour_should_start', 'true');
|
||||
sessionStorage.setItem('demo_tour_start_step', fromStep.toString());
|
||||
|
||||
|
||||
// Navigate to dashboard
|
||||
navigate(ROUTES.DASHBOARD);
|
||||
return;
|
||||
@@ -90,20 +90,41 @@ export const useDemoTour = () => {
|
||||
const steps = isMobile ? getMobileTourSteps() : getDemoTourSteps();
|
||||
console.log('[useDemoTour] Using', isMobile ? 'mobile' : 'desktop', 'steps, total:', steps.length);
|
||||
|
||||
// Check if first element exists (only if we're on the dashboard)
|
||||
// Check if critical tour elements exist (only if we're on the dashboard)
|
||||
if (currentPath === ROUTES.DASHBOARD) {
|
||||
const firstElement = steps[0]?.element;
|
||||
if (firstElement) {
|
||||
const selector = typeof firstElement === 'string' ? firstElement : String(firstElement);
|
||||
// Validate critical dashboard elements
|
||||
const criticalSelectors = [
|
||||
'[data-tour="demo-banner"]',
|
||||
'[data-tour="dashboard-stats"]'
|
||||
];
|
||||
|
||||
let missingElement = null;
|
||||
for (const selector of criticalSelectors) {
|
||||
const el = document.querySelector(selector);
|
||||
console.log('[useDemoTour] First element exists:', !!el, 'selector:', selector);
|
||||
if (!el) {
|
||||
console.warn('[useDemoTour] First tour element not found in DOM! Delaying tour start...');
|
||||
// Retry after DOM is ready
|
||||
setTimeout(() => startTour(fromStep), 500);
|
||||
missingElement = selector;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (missingElement) {
|
||||
// Retry up to 5 times with exponential backoff
|
||||
if (retryCount < 5) {
|
||||
const delay = Math.min(500 * Math.pow(1.5, retryCount), 3000);
|
||||
console.warn(`[useDemoTour] Critical tour element "${missingElement}" not found! Retrying in ${delay}ms (attempt ${retryCount + 1}/5)...`);
|
||||
setTimeout(() => startTour(fromStep, retryCount + 1), delay);
|
||||
return;
|
||||
} else {
|
||||
console.error(`[useDemoTour] Failed to find critical element "${missingElement}" after 5 retries. Tour cannot start.`);
|
||||
// Clear the tour start flag to prevent infinite retry loops
|
||||
sessionStorage.removeItem('demo_tour_should_start');
|
||||
sessionStorage.removeItem('demo_tour_start_step');
|
||||
clearTourStartPending();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[useDemoTour] All critical tour elements found, starting tour...');
|
||||
}
|
||||
|
||||
const config = getDriverConfig(handleStepComplete);
|
||||
|
||||
Reference in New Issue
Block a user