نسخ من RaghadAlkhous/RestaurantDash
246 أسطر
7.5 KiB
JavaScript
246 أسطر
7.5 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import { useRestaurant } from '../../../contexts/RestaurantContext';
|
|
import StatisticsCard from './StatisticsCard';
|
|
import TablesManager from './TablesManager';
|
|
import {
|
|
Box,
|
|
useTheme,
|
|
useMediaQuery,
|
|
Button,
|
|
ButtonGroup,
|
|
TextField
|
|
} from '@mui/material';
|
|
import authService from '../../../services/authService';
|
|
import dayjs from 'dayjs';
|
|
|
|
const AnalyticsPage = () => {
|
|
const { restaurantId } = useRestaurant();
|
|
const [timeFrame, setTimeFrame] = useState('12m'); // '12m', '30d', '24h'
|
|
const [customDate, setCustomDate] = useState(dayjs().format('YYYY-MM-DD'));
|
|
const theme = useTheme();
|
|
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
|
|
const [chartData, setChartData] = useState([]);
|
|
|
|
const handleTimeFrameChange = (newTimeFrame) => {
|
|
setTimeFrame(newTimeFrame);
|
|
};
|
|
|
|
const handleCustomDateChange = (event) => {
|
|
setCustomDate(event.target.value);
|
|
};
|
|
|
|
const fetchStatistics = async () => {
|
|
if (!restaurantId) return;
|
|
|
|
let period = 'daily';
|
|
let labels = [];
|
|
let mappedData = [];
|
|
|
|
switch (timeFrame) {
|
|
case '24h': // يومي
|
|
period = 'daily';
|
|
labels = Array.from({ length: 24 }, (_, i) => `${i.toString().padStart(2, '0')}:00`);
|
|
try {
|
|
const response = await authService.getReservationStatistics(restaurantId, period, customDate);
|
|
if (response.success && response.data.length > 0) {
|
|
mappedData = response.data.map(item => ({
|
|
label: item.label || item.date || '',
|
|
reservations_total: item.reservations_total || 0,
|
|
number_of_people_total: item.number_of_people_total || 0
|
|
}));
|
|
} else {
|
|
mappedData = labels.map(label => ({
|
|
label,
|
|
reservations_total: 0,
|
|
number_of_people_total: 0
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
mappedData = labels.map(label => ({
|
|
label,
|
|
reservations_total: 0,
|
|
number_of_people_total: 0
|
|
}));
|
|
}
|
|
break;
|
|
|
|
case '30d': // شهري
|
|
period = 'monthly';
|
|
labels = Array.from({ length: 30 }, (_, i) => dayjs().startOf('month').add(i, 'day').format('MM-DD'));
|
|
try {
|
|
const response = await authService.getReservationStatistics(restaurantId, period, customDate);
|
|
if (response.success && response.data.length > 0) {
|
|
mappedData = response.data.map(item => ({
|
|
label: item.label ? dayjs(item.label).format('MM-DD') : item.date ? dayjs(item.date).format('MM-DD') : '',
|
|
reservations_total: item.reservations_total || 0,
|
|
number_of_people_total: item.number_of_people_total || 0
|
|
}));
|
|
} else {
|
|
mappedData = labels.map(label => ({
|
|
label,
|
|
reservations_total: 0,
|
|
number_of_people_total: 0
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
mappedData = labels.map(label => ({
|
|
label,
|
|
reservations_total: 0,
|
|
number_of_people_total: 0
|
|
}));
|
|
}
|
|
break;
|
|
|
|
case '12m': // سنوي
|
|
default:
|
|
period = 'yearly';
|
|
labels = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
|
try {
|
|
const response = await authService.getReservationStatistics(restaurantId, period, customDate);
|
|
if (response.success && response.data.length > 0) {
|
|
mappedData = response.data.map(item => ({
|
|
label: item.label || item.date || '',
|
|
reservations_total: item.reservations_total || 0,
|
|
number_of_people_total: item.number_of_people_total || 0
|
|
}));
|
|
} else {
|
|
mappedData = labels.map(label => ({
|
|
label,
|
|
reservations_total: 0,
|
|
number_of_people_total: 0
|
|
}));
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
mappedData = labels.map(label => ({
|
|
label,
|
|
reservations_total: 0,
|
|
number_of_people_total: 0
|
|
}));
|
|
}
|
|
break;
|
|
}
|
|
|
|
setChartData(mappedData);
|
|
};
|
|
|
|
|
|
useEffect(() => {
|
|
fetchStatistics();
|
|
}, [timeFrame, restaurantId, customDate]);
|
|
|
|
return (
|
|
<Box p={{ xs: 1, sm: 2 }} maxWidth="100%" overflowX="hidden">
|
|
{/* Tables Manager */}
|
|
<Box mb={1.5}>
|
|
{restaurantId && <TablesManager restaurantId={restaurantId} />}
|
|
</Box>
|
|
|
|
{/* Header Buttons */}
|
|
<Box
|
|
display="flex"
|
|
flexDirection={{ xs: 'column', sm: 'row' }}
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
gap={2}
|
|
mb={1.5}
|
|
>
|
|
<ButtonGroup
|
|
size="small"
|
|
variant="outlined"
|
|
sx={{
|
|
backgroundColor: '#ffffff',
|
|
borderRadius: '8px',
|
|
boxShadow: 'inset 0 0 0 1px #e0e0e0',
|
|
'& .MuiButton-root': {
|
|
textTransform: 'none',
|
|
fontSize: '13px',
|
|
padding: '6px 12px',
|
|
border: 'none',
|
|
borderRadius: '8px',
|
|
color: '#555',
|
|
'&:hover': { backgroundColor: '#f5f5f5' }
|
|
},
|
|
'& .MuiButton-contained': {
|
|
backgroundColor: 'rgba(255, 117, 34, 0.08)',
|
|
color: '#ff5722',
|
|
fontWeight: 'bold'
|
|
}
|
|
}}
|
|
>
|
|
{[{ label: '12 Months', value: '12m' }, { label: '30 Days', value: '30d' }, { label: '24 Hours', value: '24h' }].map(({ label, value }) => (
|
|
<Button
|
|
key={value}
|
|
variant={timeFrame === value ? 'contained' : 'text'}
|
|
onClick={() => handleTimeFrameChange(value)}
|
|
>
|
|
{label}
|
|
</Button>
|
|
))}
|
|
</ButtonGroup>
|
|
|
|
{/* Date Picker + Today Button */}
|
|
<Box
|
|
display="flex"
|
|
gap={1}
|
|
alignItems="center"
|
|
sx={{
|
|
backgroundColor: theme.palette.background.paper,
|
|
borderRadius: 2,
|
|
p: '4px 8px',
|
|
boxShadow: 'inset 0 0 0 1px #e0e0e0'
|
|
}}
|
|
>
|
|
<TextField
|
|
type="date"
|
|
value={customDate}
|
|
onChange={handleCustomDateChange}
|
|
size="small"
|
|
sx={{
|
|
width: isMobile ? '100%' : 150,
|
|
'& .MuiInputBase-input': { fontSize: isMobile ? 12 : 13, padding: '6px 8px' },
|
|
'& .MuiOutlinedInput-notchedOutline': { border: 'none' }
|
|
}}
|
|
/>
|
|
<Button
|
|
variant="contained"
|
|
size="small"
|
|
onClick={() => setCustomDate(dayjs().format('YYYY-MM-DD'))}
|
|
sx={{
|
|
backgroundColor: 'rgba(255, 117, 34, 0.08)',
|
|
color: '#ff5722',
|
|
textTransform: 'none',
|
|
boxShadow: 'none',
|
|
fontSize: isMobile ? 12 : 13,
|
|
'&:hover': { backgroundColor: 'rgba(255, 117, 34, 0.15)' }
|
|
}}
|
|
>
|
|
Today
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* StatisticsCard */}
|
|
<Box>
|
|
<StatisticsCard
|
|
title="Analytics Overview"
|
|
subtitle="Reservation Statistics"
|
|
data={chartData}
|
|
dataKeys={[
|
|
{ key: 'reservations_total', name: 'Reservations', color: '#4CAF50' },
|
|
{ key: 'number_of_people_total', name: 'People', color: '#9C27B0' },
|
|
]}
|
|
xDataKey="label"
|
|
valueFormatter={(value) => value}
|
|
timeFrame={timeFrame}
|
|
onTimeFrameChange={handleTimeFrameChange}
|
|
/>
|
|
</Box>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default AnalyticsPage;
|