Improve the dahboard with the weather info
This commit is contained in:
@@ -9,9 +9,14 @@ import { useTenantId } from './useTenantId';
|
||||
|
||||
interface DashboardData {
|
||||
weather: {
|
||||
temperature: number;
|
||||
description: string;
|
||||
precipitation: number;
|
||||
temperature?: number;
|
||||
description?: string;
|
||||
precipitation?: number;
|
||||
humidity?: number;
|
||||
wind_speed?: number;
|
||||
pressure?: number;
|
||||
source: string;
|
||||
date: string;
|
||||
} | null;
|
||||
todayForecasts: Array<{
|
||||
product: string;
|
||||
@@ -91,18 +96,16 @@ export const useDashboard = () => {
|
||||
try {
|
||||
// 1. Get available products from inventory service
|
||||
const products = await getProductsList(tenantId);
|
||||
// 2. Get weather data (Madrid coordinates)
|
||||
// 2. Get complete weather data from AEMET (Madrid coordinates)
|
||||
let weather = null;
|
||||
try {
|
||||
weather = await getCurrentWeather(tenantId, 40.4168, -3.7038);
|
||||
const weatherResponse = await getCurrentWeather(tenantId, 40.4168, -3.7038);
|
||||
// Use the full WeatherData interface instead of limited subset
|
||||
weather = weatherResponse;
|
||||
} catch (error) {
|
||||
console.warn('Failed to fetch weather:', error);
|
||||
// Fallback weather
|
||||
weather = {
|
||||
temperature: 18,
|
||||
description: 'Parcialmente nublado',
|
||||
precipitation: 0
|
||||
};
|
||||
console.error('AEMET weather data unavailable for dashboard:', error);
|
||||
// No fallback - weather remains null if AEMET API fails
|
||||
weather = null;
|
||||
}
|
||||
|
||||
// 3. Generate forecasts for each product
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// Real API hook for Order Suggestions using backend data
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import { useSales, useExternal, useForecast, useInventoryProducts } from '../api';
|
||||
import { useExternal, useForecast, useInventoryProducts } from '../api';
|
||||
import { useTenantId } from './useTenantId';
|
||||
import type { DailyOrderItem, WeeklyOrderItem } from '../components/simple/OrderSuggestions';
|
||||
|
||||
@@ -44,10 +44,6 @@ export const useOrderSuggestions = (providedTenantId?: string | null) => {
|
||||
const tenantId = providedTenantId !== undefined ? providedTenantId : hookTenantId;
|
||||
|
||||
console.log('🏢 OrderSuggestions: Tenant info:', { tenantId, tenantLoading, tenantError });
|
||||
const {
|
||||
getSalesAnalytics,
|
||||
getDashboardStats
|
||||
} = useSales();
|
||||
const {
|
||||
getProductsList
|
||||
} = useInventoryProducts();
|
||||
@@ -55,159 +51,213 @@ export const useOrderSuggestions = (providedTenantId?: string | null) => {
|
||||
getCurrentWeather
|
||||
} = useExternal();
|
||||
const {
|
||||
createSingleForecast,
|
||||
getQuickForecasts,
|
||||
getForecastAlerts
|
||||
createSingleForecast
|
||||
} = useForecast();
|
||||
|
||||
// Generate daily order suggestions based on real forecast data
|
||||
// Generate daily order suggestions - creates next day forecasts for all products
|
||||
const generateDailyOrderSuggestions = useCallback(async (): Promise<DailyOrderItem[]> => {
|
||||
if (!tenantId) return [];
|
||||
|
||||
try {
|
||||
console.log('📊 OrderSuggestions: Generating daily suggestions for tenant:', tenantId);
|
||||
|
||||
// Get products list from backend
|
||||
// Get all products from backend
|
||||
const productsList = await getProductsList(tenantId);
|
||||
const products = productsList.map(p => p.name);
|
||||
console.log('📋 OrderSuggestions: Products list:', products);
|
||||
console.log('📋 OrderSuggestions: Products list:', productsList);
|
||||
|
||||
// Filter for daily bakery products (case insensitive)
|
||||
const dailyProductKeywords = ['pan', 'baguette', 'croissant', 'magdalena'];
|
||||
const dailyProducts = products.filter(p =>
|
||||
// Filter for daily products (bakery items that need daily forecasting)
|
||||
const dailyProductKeywords = ['pan', 'baguette', 'croissant', 'magdalena', 'tarta', 'bollo', 'empanada'];
|
||||
const dailyProducts = productsList.filter(p =>
|
||||
dailyProductKeywords.some(keyword =>
|
||||
p.toLowerCase().includes(keyword.toLowerCase())
|
||||
p.name.toLowerCase().includes(keyword.toLowerCase())
|
||||
)
|
||||
);
|
||||
console.log('🥖 OrderSuggestions: Daily products:', dailyProducts);
|
||||
|
||||
// Get quick forecasts for these products
|
||||
const quickForecasts = await getQuickForecasts(tenantId);
|
||||
console.log('🔮 OrderSuggestions: Quick forecasts:', quickForecasts);
|
||||
|
||||
// Get weather data to determine urgency
|
||||
const weather = await getCurrentWeather(tenantId, 40.4168, -3.7038);
|
||||
console.log('🌤️ OrderSuggestions: Weather data:', weather);
|
||||
|
||||
// Create individual forecasts for each daily product for next day
|
||||
const suggestions: DailyOrderItem[] = [];
|
||||
console.log('🔄 OrderSuggestions: Processing daily products:', dailyProducts);
|
||||
const tomorrow = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString().split('T')[0];
|
||||
|
||||
// Get weather data to determine urgency factors
|
||||
let weather = null;
|
||||
try {
|
||||
weather = await getCurrentWeather(tenantId, 40.4168, -3.7038);
|
||||
console.log('🌤️ OrderSuggestions: Weather data:', weather);
|
||||
} catch (error) {
|
||||
console.warn('⚠️ OrderSuggestions: AEMET weather data unavailable, continuing without weather factors:', error);
|
||||
weather = null;
|
||||
}
|
||||
|
||||
for (const product of dailyProducts) {
|
||||
console.log('🔄 OrderSuggestions: Processing product:', product);
|
||||
// Find forecast for this product
|
||||
const forecast = quickForecasts.find(f =>
|
||||
f.product_name === product || f.inventory_product_id === product
|
||||
);
|
||||
console.log('🔄 OrderSuggestions: Creating forecast for product:', product.name);
|
||||
|
||||
if (forecast) {
|
||||
// Calculate suggested quantity based on prediction
|
||||
const suggestedQuantity = Math.max(forecast.next_day_prediction, 10);
|
||||
|
||||
// Determine urgency based on confidence and trend
|
||||
let urgency: 'high' | 'medium' | 'low' = 'medium';
|
||||
if (forecast.confidence_score > 0.9 && forecast.trend_direction === 'up') {
|
||||
urgency = 'high';
|
||||
} else if (forecast.confidence_score < 0.7) {
|
||||
urgency = 'low';
|
||||
}
|
||||
|
||||
// Generate reason based on forecast data
|
||||
let reason = `Predicción: ${forecast.next_day_prediction} unidades`;
|
||||
if (forecast.trend_direction === 'up') {
|
||||
reason += ' (tendencia al alza)';
|
||||
}
|
||||
if (weather && weather.precipitation > 0) {
|
||||
reason += ', lluvia prevista';
|
||||
urgency = urgency === 'low' ? 'medium' : 'high';
|
||||
}
|
||||
|
||||
const orderItem: DailyOrderItem = {
|
||||
id: `daily-${product.toLowerCase().replace(/\s+/g, '-')}`,
|
||||
product,
|
||||
emoji: getProductEmoji(product),
|
||||
suggestedQuantity: Math.round(suggestedQuantity),
|
||||
currentQuantity: Math.round(suggestedQuantity * 0.2), // Assume 20% current stock
|
||||
unit: 'unidades',
|
||||
urgency,
|
||||
reason,
|
||||
confidence: Math.round(forecast.confidence_score * 100),
|
||||
supplier: SUPPLIERS[product] || 'Proveedor General',
|
||||
estimatedCost: Math.round(suggestedQuantity * (PRODUCT_PRICES[product] || 2.5) * 100) / 100,
|
||||
lastOrderDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0]
|
||||
try {
|
||||
// Create single forecast for next day for this specific product
|
||||
const forecastRequest = {
|
||||
inventory_product_id: product.inventory_product_id,
|
||||
forecast_date: tomorrow,
|
||||
forecast_days: 1,
|
||||
location: 'Madrid',
|
||||
include_external_factors: true,
|
||||
confidence_intervals: true
|
||||
};
|
||||
|
||||
const forecasts = await createSingleForecast(tenantId, forecastRequest);
|
||||
|
||||
if (forecasts.length > 0) {
|
||||
const forecast = forecasts[0];
|
||||
const suggestedQuantity = Math.max(Math.round(forecast.predicted_demand), 5);
|
||||
|
||||
// Determine urgency based on confidence and external factors
|
||||
let urgency: 'high' | 'medium' | 'low' = 'medium';
|
||||
const confidence = forecast.confidence_level || 0.8;
|
||||
|
||||
if (confidence > 0.9) {
|
||||
urgency = 'low'; // High confidence = low urgency
|
||||
} else if (confidence < 0.6) {
|
||||
urgency = 'high'; // Low confidence = high urgency, need more buffer
|
||||
}
|
||||
|
||||
// Adjust based on weather
|
||||
if (weather && weather.precipitation > 0) {
|
||||
urgency = urgency === 'low' ? 'medium' : 'high';
|
||||
}
|
||||
|
||||
suggestions.push(orderItem);
|
||||
console.log('➕ OrderSuggestions: Added daily suggestion:', orderItem);
|
||||
// Generate reason based on forecast data
|
||||
let reason = `Predicción: ${suggestedQuantity} unidades (demanda para mañana)`;
|
||||
if (weather && weather.precipitation > 0) {
|
||||
reason += ', lluvia prevista';
|
||||
}
|
||||
|
||||
const orderItem: DailyOrderItem = {
|
||||
id: `daily-${product.name.toLowerCase().replace(/\s+/g, '-')}`,
|
||||
product: product.name,
|
||||
emoji: getProductEmoji(product.name),
|
||||
suggestedQuantity,
|
||||
currentQuantity: Math.round(suggestedQuantity * (0.1 + Math.random() * 0.3)), // Random current stock 10-40%
|
||||
unit: getProductUnit(product.name),
|
||||
urgency,
|
||||
reason,
|
||||
confidence: Math.round(confidence * 100),
|
||||
supplier: SUPPLIERS[product.name] || 'Proveedor General',
|
||||
estimatedCost: Math.round(suggestedQuantity * (PRODUCT_PRICES[product.name] || 2.5) * 100) / 100,
|
||||
lastOrderDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0]
|
||||
};
|
||||
|
||||
suggestions.push(orderItem);
|
||||
console.log('➕ OrderSuggestions: Added daily suggestion:', orderItem);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ OrderSuggestions: Failed to create forecast for ${product.name}:`, error);
|
||||
// Continue with other products even if one fails
|
||||
}
|
||||
}
|
||||
|
||||
console.log('🎯 OrderSuggestions: Final daily suggestions:', suggestions);
|
||||
return suggestions;
|
||||
return suggestions.sort((a, b) => {
|
||||
// Sort by urgency (high first) then by suggested quantity
|
||||
const urgencyOrder = { high: 3, medium: 2, low: 1 };
|
||||
if (urgencyOrder[a.urgency] !== urgencyOrder[b.urgency]) {
|
||||
return urgencyOrder[b.urgency] - urgencyOrder[a.urgency];
|
||||
}
|
||||
return b.suggestedQuantity - a.suggestedQuantity;
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ OrderSuggestions: Error in generateDailyOrderSuggestions:', error);
|
||||
return [];
|
||||
}
|
||||
}, [tenantId, getProductsList, getQuickForecasts, getCurrentWeather]);
|
||||
}, [tenantId, getProductsList, createSingleForecast, getCurrentWeather]);
|
||||
|
||||
// Generate weekly order suggestions based on sales analytics
|
||||
// Generate weekly order suggestions - creates 7-day forecasts for weekly order products
|
||||
const generateWeeklyOrderSuggestions = useCallback(async (): Promise<WeeklyOrderItem[]> => {
|
||||
if (!tenantId) return [];
|
||||
|
||||
console.log('📊 OrderSuggestions: Generating weekly suggestions for tenant:', tenantId);
|
||||
try {
|
||||
console.log('📊 OrderSuggestions: Generating weekly suggestions for tenant:', tenantId);
|
||||
|
||||
// Get sales analytics for the past month
|
||||
const endDate = new Date().toISOString();
|
||||
const startDate = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
|
||||
// Get all products from backend
|
||||
const productsList = await getProductsList(tenantId);
|
||||
console.log('📋 OrderSuggestions: Products list for weekly:', productsList);
|
||||
|
||||
const analytics = await getSalesAnalytics(tenantId, startDate, endDate);
|
||||
console.log('📈 OrderSuggestions: Sales analytics:', analytics);
|
||||
|
||||
// Weekly products (ingredients and supplies)
|
||||
const weeklyProducts = [
|
||||
'Café en Grano',
|
||||
'Leche Entera',
|
||||
'Mantequilla',
|
||||
'Vasos de Café',
|
||||
'Servilletas',
|
||||
'Bolsas papel'
|
||||
];
|
||||
// Filter for weekly products (ingredients, supplies, drinks that need weekly forecasting)
|
||||
const weeklyProductKeywords = ['café', 'leche', 'mantequilla', 'vaso', 'servilleta', 'bolsa', 'bebida', 'refresco', 'agua'];
|
||||
const weeklyProducts = productsList.filter(p =>
|
||||
weeklyProductKeywords.some(keyword =>
|
||||
p.name.toLowerCase().includes(keyword.toLowerCase())
|
||||
)
|
||||
);
|
||||
console.log('📦 OrderSuggestions: Weekly products:', weeklyProducts);
|
||||
|
||||
const suggestions: WeeklyOrderItem[] = [];
|
||||
|
||||
const startDate = new Date().toISOString().split('T')[0];
|
||||
|
||||
for (const product of weeklyProducts) {
|
||||
// Calculate weekly consumption based on analytics
|
||||
const weeklyConsumption = calculateWeeklyConsumption(product, analytics);
|
||||
const currentStock = Math.round(weeklyConsumption * (0.3 + Math.random() * 0.4)); // Random stock between 30-70% of weekly need
|
||||
const stockDays = Math.max(1, Math.round((currentStock / weeklyConsumption) * 7));
|
||||
console.log('🔄 OrderSuggestions: Creating 7-day forecast for product:', product.name);
|
||||
|
||||
try {
|
||||
// Create single forecast for 7 days for this specific product
|
||||
const forecastRequest = {
|
||||
inventory_product_id: product.inventory_product_id,
|
||||
forecast_date: startDate,
|
||||
forecast_days: 7,
|
||||
location: 'Madrid',
|
||||
include_external_factors: true,
|
||||
confidence_intervals: true
|
||||
};
|
||||
|
||||
const forecasts = await createSingleForecast(tenantId, forecastRequest);
|
||||
|
||||
if (forecasts.length > 0) {
|
||||
// Calculate total weekly demand from all forecast days
|
||||
const totalWeeklyDemand = forecasts.reduce((sum, forecast) => sum + forecast.predicted_demand, 0);
|
||||
const averageConfidence = forecasts.reduce((sum, forecast) => sum + (forecast.confidence_level || 0.8), 0) / forecasts.length;
|
||||
|
||||
// Determine frequency based on product type
|
||||
const highFrequencyKeywords = ['café', 'leche', 'mantequilla', 'bebida'];
|
||||
const frequency: 'weekly' | 'biweekly' =
|
||||
highFrequencyKeywords.some(keyword => product.name.toLowerCase().includes(keyword)) ? 'weekly' : 'biweekly';
|
||||
|
||||
// Calculate suggested quantity with buffer
|
||||
const suggestedQuantity = frequency === 'weekly' ?
|
||||
Math.round(totalWeeklyDemand * 1.15) : // 15% buffer for weekly
|
||||
Math.round(totalWeeklyDemand * 2.3); // 2 weeks + 15% buffer
|
||||
|
||||
// Simulate current stock and calculate stock days
|
||||
const dailyConsumption = totalWeeklyDemand / 7;
|
||||
const currentStock = Math.round(dailyConsumption * (2 + Math.random() * 8)); // 2-10 days worth
|
||||
const stockDays = Math.max(1, Math.round(currentStock / dailyConsumption));
|
||||
|
||||
// Determine frequency
|
||||
const frequency: 'weekly' | 'biweekly' =
|
||||
['Café en Grano', 'Leche Entera', 'Mantequilla'].includes(product) ? 'weekly' : 'biweekly';
|
||||
const orderItem: WeeklyOrderItem = {
|
||||
id: `weekly-${product.name.toLowerCase().replace(/\s+/g, '-')}`,
|
||||
product: product.name,
|
||||
emoji: getProductEmoji(product.name),
|
||||
suggestedQuantity,
|
||||
currentStock,
|
||||
unit: getProductUnit(product.name),
|
||||
frequency,
|
||||
nextOrderDate: getNextOrderDate(frequency, stockDays),
|
||||
supplier: SUPPLIERS[product.name] || 'Proveedor General',
|
||||
estimatedCost: Math.round(suggestedQuantity * (PRODUCT_PRICES[product.name] || 1.0) * 100) / 100,
|
||||
stockDays,
|
||||
confidence: Math.round(averageConfidence * 100)
|
||||
};
|
||||
|
||||
const suggestedQuantity = frequency === 'weekly' ?
|
||||
Math.round(weeklyConsumption * 1.1) : // 10% buffer for weekly
|
||||
Math.round(weeklyConsumption * 2.2); // 2 weeks + 10% buffer
|
||||
|
||||
const orderItem: WeeklyOrderItem = {
|
||||
id: `weekly-${product.toLowerCase().replace(/\s+/g, '-')}`,
|
||||
product,
|
||||
emoji: getProductEmoji(product),
|
||||
suggestedQuantity,
|
||||
currentStock,
|
||||
unit: getProductUnit(product),
|
||||
frequency,
|
||||
nextOrderDate: getNextOrderDate(frequency, stockDays),
|
||||
supplier: SUPPLIERS[product] || 'Proveedor General',
|
||||
estimatedCost: Math.round(suggestedQuantity * (PRODUCT_PRICES[product] || 1.0) * 100) / 100,
|
||||
stockDays,
|
||||
confidence: stockDays <= 2 ? 95 : stockDays <= 5 ? 85 : 75
|
||||
};
|
||||
|
||||
suggestions.push(orderItem);
|
||||
suggestions.push(orderItem);
|
||||
console.log('➕ OrderSuggestions: Added weekly suggestion:', orderItem);
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn(`⚠️ OrderSuggestions: Failed to create weekly forecast for ${product.name}:`, error);
|
||||
// Continue with other products even if one fails
|
||||
}
|
||||
}
|
||||
|
||||
return suggestions.sort((a, b) => a.stockDays - b.stockDays); // Sort by urgency
|
||||
}, [tenantId, getSalesAnalytics]);
|
||||
console.log('🎯 OrderSuggestions: Final weekly suggestions:', suggestions);
|
||||
return suggestions.sort((a, b) => a.stockDays - b.stockDays); // Sort by urgency (lowest stock days first)
|
||||
} catch (error) {
|
||||
console.error('❌ OrderSuggestions: Error in generateWeeklyOrderSuggestions:', error);
|
||||
return [];
|
||||
}
|
||||
}, [tenantId, getProductsList, createSingleForecast]);
|
||||
|
||||
// Load order suggestions
|
||||
const loadOrderSuggestions = useCallback(async () => {
|
||||
@@ -282,7 +332,13 @@ function getProductEmoji(product: string): string {
|
||||
'Mantequilla': '🧈',
|
||||
'Vasos de Café': '🥤',
|
||||
'Servilletas': '🧻',
|
||||
'Bolsas papel': '🛍️'
|
||||
'Bolsas papel': '🛍️',
|
||||
'Bebida': '🥤',
|
||||
'Refresco': '🥤',
|
||||
'Agua': '💧',
|
||||
'Tarta': '🎂',
|
||||
'Bollo': '🥖',
|
||||
'Empanada': '🥟'
|
||||
};
|
||||
return emojiMap[product] || '📦';
|
||||
}
|
||||
@@ -298,25 +354,17 @@ function getProductUnit(product: string): string {
|
||||
'Mantequilla': 'kg',
|
||||
'Vasos de Café': 'unidades',
|
||||
'Servilletas': 'paquetes',
|
||||
'Bolsas papel': 'unidades'
|
||||
'Bolsas papel': 'unidades',
|
||||
'Bebida': 'litros',
|
||||
'Refresco': 'litros',
|
||||
'Agua': 'litros',
|
||||
'Tarta': 'unidades',
|
||||
'Bollo': 'unidades',
|
||||
'Empanada': 'unidades'
|
||||
};
|
||||
return unitMap[product] || 'unidades';
|
||||
}
|
||||
|
||||
function calculateWeeklyConsumption(product: string, analytics: any): number {
|
||||
// This would ideally come from sales analytics
|
||||
// For now, use realistic estimates based on product type
|
||||
const weeklyEstimates: Record<string, number> = {
|
||||
'Café en Grano': 5, // 5kg per week
|
||||
'Leche Entera': 25, // 25L per week
|
||||
'Mantequilla': 3, // 3kg per week
|
||||
'Vasos de Café': 500, // 500 cups per week
|
||||
'Servilletas': 10, // 10 packs per week
|
||||
'Bolsas papel': 200 // 200 bags per week
|
||||
};
|
||||
|
||||
return weeklyEstimates[product] || 10;
|
||||
}
|
||||
|
||||
function getNextOrderDate(frequency: 'weekly' | 'biweekly', stockDays: number): string {
|
||||
const today = new Date();
|
||||
@@ -333,97 +381,3 @@ function getNextOrderDate(frequency: 'weekly' | 'biweekly', stockDays: number):
|
||||
return nextDate.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
// Mock data functions for when tenant ID is not available
|
||||
function getMockDailyOrders(): DailyOrderItem[] {
|
||||
return [
|
||||
{
|
||||
id: 'daily-pan-molde',
|
||||
product: 'Pan de Molde',
|
||||
emoji: '🍞',
|
||||
suggestedQuantity: 25,
|
||||
currentQuantity: 5,
|
||||
unit: 'unidades',
|
||||
urgency: 'medium' as const,
|
||||
reason: 'Predicción: 25 unidades (tendencia estable)',
|
||||
confidence: 85,
|
||||
supplier: 'Panadería Central Madrid',
|
||||
estimatedCost: 45.00,
|
||||
lastOrderDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0]
|
||||
},
|
||||
{
|
||||
id: 'daily-baguettes',
|
||||
product: 'Baguettes',
|
||||
emoji: '🥖',
|
||||
suggestedQuantity: 20,
|
||||
currentQuantity: 3,
|
||||
unit: 'unidades',
|
||||
urgency: 'high' as const,
|
||||
reason: 'Predicción: 20 unidades (tendencia al alza)',
|
||||
confidence: 92,
|
||||
supplier: 'Panadería Central Madrid',
|
||||
estimatedCost: 56.00,
|
||||
lastOrderDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0]
|
||||
},
|
||||
{
|
||||
id: 'daily-croissants',
|
||||
product: 'Croissants',
|
||||
emoji: '🥐',
|
||||
suggestedQuantity: 15,
|
||||
currentQuantity: 8,
|
||||
unit: 'unidades',
|
||||
urgency: 'low' as const,
|
||||
reason: 'Predicción: 15 unidades (demanda regular)',
|
||||
confidence: 78,
|
||||
supplier: 'Panadería Central Madrid',
|
||||
estimatedCost: 37.50,
|
||||
lastOrderDate: new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString().split('T')[0]
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function getMockWeeklyOrders(): WeeklyOrderItem[] {
|
||||
return [
|
||||
{
|
||||
id: 'weekly-cafe-grano',
|
||||
product: 'Café en Grano',
|
||||
emoji: '☕',
|
||||
suggestedQuantity: 5,
|
||||
currentStock: 2,
|
||||
unit: 'kg',
|
||||
frequency: 'weekly' as const,
|
||||
nextOrderDate: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
||||
supplier: 'Cafés Premium',
|
||||
estimatedCost: 87.50,
|
||||
stockDays: 3,
|
||||
confidence: 95
|
||||
},
|
||||
{
|
||||
id: 'weekly-leche-entera',
|
||||
product: 'Leche Entera',
|
||||
emoji: '🥛',
|
||||
suggestedQuantity: 25,
|
||||
currentStock: 15,
|
||||
unit: 'litros',
|
||||
frequency: 'weekly' as const,
|
||||
nextOrderDate: new Date(Date.now() + 5 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
||||
supplier: 'Lácteos Frescos SA',
|
||||
estimatedCost: 23.75,
|
||||
stockDays: 6,
|
||||
confidence: 88
|
||||
},
|
||||
{
|
||||
id: 'weekly-vasos-cafe',
|
||||
product: 'Vasos de Café',
|
||||
emoji: '🥤',
|
||||
suggestedQuantity: 500,
|
||||
currentStock: 100,
|
||||
unit: 'unidades',
|
||||
frequency: 'biweekly' as const,
|
||||
nextOrderDate: new Date(Date.now() + 1 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
||||
supplier: 'Suministros Hostelería',
|
||||
estimatedCost: 40.00,
|
||||
stockDays: 2,
|
||||
confidence: 90
|
||||
}
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user