2025-08-28 10:41:04 +02:00
|
|
|
import React from 'react';
|
2025-09-22 11:04:03 +02:00
|
|
|
import { useNavigate } from 'react-router-dom';
|
|
|
|
|
import { useTranslation } from 'react-i18next';
|
2025-08-28 10:41:04 +02:00
|
|
|
import { PageHeader } from '../../components/layout';
|
2025-09-22 11:04:03 +02:00
|
|
|
import { Button } from '../../components/ui/Button';
|
|
|
|
|
import { Card, CardHeader, CardBody } from '../../components/ui/Card';
|
2025-09-19 16:17:04 +02:00
|
|
|
import StatsGrid from '../../components/ui/Stats/StatsGrid';
|
|
|
|
|
import RealTimeAlerts from '../../components/domain/dashboard/RealTimeAlerts';
|
|
|
|
|
import ProcurementPlansToday from '../../components/domain/dashboard/ProcurementPlansToday';
|
|
|
|
|
import ProductionPlansToday from '../../components/domain/dashboard/ProductionPlansToday';
|
2025-10-02 13:20:30 +02:00
|
|
|
import PurchaseOrdersTracking from '../../components/domain/dashboard/PurchaseOrdersTracking';
|
2025-09-22 11:04:03 +02:00
|
|
|
import { useTenant } from '../../stores/tenant.store';
|
2025-09-19 16:17:04 +02:00
|
|
|
import {
|
|
|
|
|
AlertTriangle,
|
|
|
|
|
Clock,
|
2025-09-22 16:10:08 +02:00
|
|
|
Euro,
|
2025-09-19 16:17:04 +02:00
|
|
|
Package,
|
2025-09-22 11:04:03 +02:00
|
|
|
Plus,
|
|
|
|
|
Building2
|
2025-09-19 16:17:04 +02:00
|
|
|
} from 'lucide-react';
|
2025-08-28 10:41:04 +02:00
|
|
|
|
|
|
|
|
const DashboardPage: React.FC = () => {
|
2025-09-22 11:04:03 +02:00
|
|
|
const { t } = useTranslation();
|
|
|
|
|
const navigate = useNavigate();
|
|
|
|
|
const { availableTenants } = useTenant();
|
|
|
|
|
|
|
|
|
|
const handleAddNewBakery = () => {
|
|
|
|
|
navigate('/app/onboarding?new=true');
|
|
|
|
|
};
|
|
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
const criticalStats = [
|
2025-08-28 10:41:04 +02:00
|
|
|
{
|
2025-09-22 11:04:03 +02:00
|
|
|
title: t('dashboard:stats.sales_today', 'Sales Today'),
|
2025-09-19 16:17:04 +02:00
|
|
|
value: '€1,247',
|
2025-09-22 16:10:08 +02:00
|
|
|
icon: Euro,
|
2025-09-19 16:17:04 +02:00
|
|
|
variant: 'success' as const,
|
2025-08-28 10:41:04 +02:00
|
|
|
trend: {
|
|
|
|
|
value: 12,
|
2025-09-19 16:17:04 +02:00
|
|
|
direction: 'up' as const,
|
2025-09-22 11:04:03 +02:00
|
|
|
label: t('dashboard:trends.vs_yesterday', '% vs yesterday')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
2025-09-22 11:04:03 +02:00
|
|
|
subtitle: '+€135 ' + t('dashboard:messages.more_than_yesterday', 'more than yesterday')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
|
|
|
|
{
|
2025-09-22 11:04:03 +02:00
|
|
|
title: t('dashboard:stats.pending_orders', 'Pending Orders'),
|
2025-09-19 16:17:04 +02:00
|
|
|
value: '23',
|
|
|
|
|
icon: Clock,
|
|
|
|
|
variant: 'warning' as const,
|
2025-08-28 10:41:04 +02:00
|
|
|
trend: {
|
2025-09-19 16:17:04 +02:00
|
|
|
value: 4,
|
2025-08-28 10:41:04 +02:00
|
|
|
direction: 'down' as const,
|
2025-09-22 11:04:03 +02:00
|
|
|
label: t('dashboard:trends.vs_yesterday', '% vs yesterday')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
2025-09-22 11:04:03 +02:00
|
|
|
subtitle: t('dashboard:messages.require_attention', 'Require attention')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
|
|
|
|
{
|
2025-09-22 11:04:03 +02:00
|
|
|
title: t('dashboard:stats.products_sold', 'Products Sold'),
|
2025-09-19 16:17:04 +02:00
|
|
|
value: '156',
|
|
|
|
|
icon: Package,
|
|
|
|
|
variant: 'info' as const,
|
2025-08-28 10:41:04 +02:00
|
|
|
trend: {
|
2025-09-19 16:17:04 +02:00
|
|
|
value: 8,
|
2025-08-28 10:41:04 +02:00
|
|
|
direction: 'up' as const,
|
2025-09-22 11:04:03 +02:00
|
|
|
label: t('dashboard:trends.vs_yesterday', '% vs yesterday')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
2025-09-22 11:04:03 +02:00
|
|
|
subtitle: '+12 ' + t('dashboard:messages.more_units', 'more units')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
|
|
|
|
{
|
2025-09-22 11:04:03 +02:00
|
|
|
title: t('dashboard:stats.stock_alerts', 'Critical Stock'),
|
2025-09-19 16:17:04 +02:00
|
|
|
value: '4',
|
|
|
|
|
icon: AlertTriangle,
|
|
|
|
|
variant: 'error' as const,
|
2025-08-28 10:41:04 +02:00
|
|
|
trend: {
|
|
|
|
|
value: 100,
|
2025-09-19 16:17:04 +02:00
|
|
|
direction: 'up' as const,
|
2025-09-22 11:04:03 +02:00
|
|
|
label: t('dashboard:trends.vs_yesterday', '% vs yesterday')
|
2025-08-28 10:41:04 +02:00
|
|
|
},
|
2025-09-22 11:04:03 +02:00
|
|
|
subtitle: t('dashboard:messages.action_required', 'Action required')
|
2025-09-19 16:17:04 +02:00
|
|
|
}
|
2025-08-28 10:41:04 +02:00
|
|
|
];
|
|
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
const handleOrderItem = (itemId: string) => {
|
|
|
|
|
console.log('Ordering item:', itemId);
|
2025-08-28 10:41:04 +02:00
|
|
|
};
|
|
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
const handleStartOrder = (orderId: string) => {
|
|
|
|
|
console.log('Starting production order:', orderId);
|
2025-08-28 10:41:04 +02:00
|
|
|
};
|
|
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
const handlePauseOrder = (orderId: string) => {
|
|
|
|
|
console.log('Pausing production order:', orderId);
|
|
|
|
|
};
|
2025-08-28 10:41:04 +02:00
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
const handleViewDetails = (id: string) => {
|
|
|
|
|
console.log('Viewing details for:', id);
|
|
|
|
|
};
|
2025-08-28 10:41:04 +02:00
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
const handleViewAllPlans = () => {
|
|
|
|
|
console.log('Viewing all plans');
|
|
|
|
|
};
|
2025-08-28 10:41:04 +02:00
|
|
|
|
|
|
|
|
return (
|
2025-09-19 16:17:04 +02:00
|
|
|
<div className="space-y-6 p-4 sm:p-6">
|
2025-08-28 10:41:04 +02:00
|
|
|
<PageHeader
|
2025-09-22 11:04:03 +02:00
|
|
|
title={t('dashboard:title', 'Dashboard')}
|
|
|
|
|
description={t('dashboard:subtitle', 'Overview of your bakery operations')}
|
2025-08-28 10:41:04 +02:00
|
|
|
/>
|
|
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
{/* Critical Metrics using StatsGrid */}
|
|
|
|
|
<StatsGrid
|
|
|
|
|
stats={criticalStats}
|
|
|
|
|
columns={4}
|
|
|
|
|
gap="lg"
|
|
|
|
|
className="mb-6"
|
|
|
|
|
/>
|
2025-08-28 10:41:04 +02:00
|
|
|
|
2025-09-22 11:04:03 +02:00
|
|
|
{/* Quick Actions - Add New Bakery */}
|
|
|
|
|
{availableTenants && availableTenants.length > 0 && (
|
|
|
|
|
<Card>
|
|
|
|
|
<CardHeader>
|
|
|
|
|
<h3 className="text-lg font-semibold text-[var(--text-primary)]">{t('dashboard:sections.quick_actions', 'Quick Actions')}</h3>
|
|
|
|
|
<p className="text-sm text-[var(--text-secondary)]">{t('dashboard:messages.manage_organizations', 'Manage your organizations')}</p>
|
|
|
|
|
</CardHeader>
|
|
|
|
|
<CardBody>
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
|
|
|
<Button
|
|
|
|
|
onClick={handleAddNewBakery}
|
|
|
|
|
variant="outline"
|
|
|
|
|
size="lg"
|
|
|
|
|
className="h-auto p-6 flex flex-col items-center gap-3 bg-gradient-to-br from-[var(--color-primary)]/5 to-[var(--color-primary)]/10 border-[var(--color-primary)]/20 hover:border-[var(--color-primary)]/40 hover:bg-[var(--color-primary)]/20 transition-all duration-200"
|
|
|
|
|
>
|
|
|
|
|
<div className="w-12 h-12 bg-[var(--color-primary)]/10 rounded-lg flex items-center justify-center">
|
|
|
|
|
<Plus className="w-6 h-6 text-[var(--color-primary)]" />
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="font-semibold text-[var(--text-primary)]">{t('dashboard:quick_actions.add_new_bakery', 'Add New Bakery')}</div>
|
|
|
|
|
<div className="text-sm text-[var(--text-secondary)] mt-1">{t('dashboard:messages.setup_new_business', 'Set up a new business from scratch')}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Button>
|
|
|
|
|
|
|
|
|
|
<div className="flex flex-col items-center justify-center p-6 bg-[var(--bg-secondary)] rounded-lg border border-[var(--border-primary)]">
|
|
|
|
|
<Building2 className="w-8 h-8 text-[var(--text-tertiary)] mb-2" />
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<div className="text-sm font-medium text-[var(--text-secondary)]">{t('dashboard:messages.active_organizations', 'Active Organizations')}</div>
|
|
|
|
|
<div className="text-2xl font-bold text-[var(--color-primary)]">{availableTenants.length}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</CardBody>
|
|
|
|
|
</Card>
|
|
|
|
|
)}
|
|
|
|
|
|
2025-09-19 16:17:04 +02:00
|
|
|
{/* Full width blocks - one after another */}
|
|
|
|
|
<div className="space-y-6">
|
|
|
|
|
{/* 1. Real-time alerts block */}
|
|
|
|
|
<RealTimeAlerts />
|
|
|
|
|
|
2025-10-02 13:20:30 +02:00
|
|
|
{/* 2. Purchase Orders Tracking block */}
|
|
|
|
|
<PurchaseOrdersTracking />
|
|
|
|
|
|
|
|
|
|
{/* 3. Procurement plans block */}
|
2025-09-19 16:17:04 +02:00
|
|
|
<ProcurementPlansToday
|
|
|
|
|
onOrderItem={handleOrderItem}
|
|
|
|
|
onViewDetails={handleViewDetails}
|
|
|
|
|
onViewAllPlans={handleViewAllPlans}
|
|
|
|
|
/>
|
|
|
|
|
|
2025-10-02 13:20:30 +02:00
|
|
|
{/* 4. Production plans block */}
|
2025-09-19 16:17:04 +02:00
|
|
|
<ProductionPlansToday
|
|
|
|
|
onStartOrder={handleStartOrder}
|
|
|
|
|
onPauseOrder={handlePauseOrder}
|
|
|
|
|
onViewDetails={handleViewDetails}
|
|
|
|
|
onViewAllPlans={handleViewAllPlans}
|
|
|
|
|
/>
|
2025-08-28 10:41:04 +02:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default DashboardPage;
|