Overview v1

This commit is contained in:
Flatlogic Bot 2026-01-15 09:54:58 +00:00
parent 9ee76a0742
commit b0b177c6d8

View File

@ -1,14 +1,17 @@
import * as icon from '@mdi/js';
import Head from 'next/head'
import React from 'react'
import React, { useState, useEffect } from 'react'
import type { ReactElement } from 'react'
import LayoutAuthenticated from '../layouts/Authenticated'
import SectionMain from '../components/SectionMain'
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton'
import { getPageTitle } from '../config'
import { useAppSelector, useAppDispatch } from '../stores/hooks';
import axios from 'axios';
import CardBox from '../components/CardBox';
import BaseIcon from '../components/BaseIcon';
import { mdiAccountMultiple, mdiCartOutline, mdiCalendarCheck } from '@mdi/js';
import ChartLineSample from '../components/ChartLineSample/index';
const Dashboard = () => {
const dispatch = useAppDispatch();
@ -16,16 +19,89 @@ const Dashboard = () => {
const corners = useAppSelector((state) => state.style.corners);
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
const [stats, setStats] = useState({
customers: 0,
menuItems: 0,
reservations: 0,
});
const [chartData, setChartData] = useState(null);
const [recentReservations, setRecentReservations] = useState([]);
const [lowStockItems, setLowStockItems] = useState([]);
useEffect(() => {
const loadData = async () => {
try {
const statsPromises = [
axios.get('/customers', { params: { limit: 1 } }),
axios.get('/menu_items', { params: { limit: 1 } }),
axios.get('/reservations', { params: { limit: 1 } }),
];
const chartPromise = axios.get('/payments');
const reservationsPromise = axios.get('/reservations?limit=5&orderBy=createdAt_DESC');
const inventoryPromise = axios.get('/inventory_items');
const [customersResponse, menuItemsResponse, reservationsResponse] = await Promise.all(statsPromises);
setStats({
customers: customersResponse.data.count,
menuItems: menuItemsResponse.data.count,
reservations: reservationsResponse.data.count,
});
const chartResponse = await chartPromise;
const payments = chartResponse.data.rows;
if (payments) {
const groupedData = payments.reduce((acc, payment) => {
const date = new Date(payment.paid_at).toLocaleDateString();
if (!acc[date]) {
acc[date] = 0;
}
acc[date] += parseFloat(payment.amount);
return acc;
}, {});
const labels = Object.keys(groupedData);
const data = Object.values(groupedData);
setChartData({
labels,
datasets: [
{
label: 'Revenue',
data,
fill: true,
borderColor: '#4A5568',
backgroundColor: '#4A556820',
tension: 0.2,
},
],
});
}
const recentReservationsResponse = await reservationsPromise;
setRecentReservations(recentReservationsResponse.data.rows);
const inventoryResponse = await inventoryPromise;
const inventoryItems = inventoryResponse.data.rows;
if (inventoryItems) {
const lowStock = inventoryItems.filter(
(item) => item.quantity <= (item.reorder_level || 10)
);
setLowStockItems(lowStock);
}
} catch (error) {
console.error('Failed to load dashboard data', error);
}
};
loadData();
}, []);
const { currentUser } = useAppSelector((state) => state.auth);
return (
<>
<Head>
@ -40,6 +116,55 @@ const Dashboard = () => {
main>
{''}
</SectionTitleLineWithButton>
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3 mb-6">
<CardBox
title="Clients"
number={stats.customers}
icon={<BaseIcon path={mdiAccountMultiple} w="24" h="24" />}
/>
<CardBox
title="Menu Items"
number={stats.menuItems}
icon={<BaseIcon path={mdiCartOutline} w="24" h="24" />}
/>
<CardBox
title="Reservations"
number={stats.reservations}
icon={<BaseIcon path={mdiCalendarCheck} w="24" h="24" />}
/>
</div>
{chartData && (
<CardBox className="mb-6">
<ChartLineSample data={chartData} />
</CardBox>
)}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
<CardBox>
<h2 className="text-xl font-semibold mb-4">Recent Reservations</h2>
<ul>
{recentReservations.map((reservation) => (
<li key={reservation.id} className="flex justify-between items-center py-2 border-b">
<span>{reservation.code}</span>
<span>{new Date(reservation.start_at).toLocaleString()}</span>
</li>
))}
</ul>
</CardBox>
<CardBox>
<h2 className="text-xl font-semibold mb-4">Low Stock Items</h2>
<ul>
{lowStockItems.map((item) => (
<li key={item.id} className="flex justify-between items-center py-2 border-b">
<span>{item.name}</span>
<span className="text-red-500">{item.quantity}</span>
</li>
))}
</ul>
</CardBox>
</div>
</SectionMain>
</>
)