1
0
الملفات
RestaurantDash/src/components/Home/Analytics&Reporting/AnalyticsContect.js
2025-09-04 01:17:15 +03:00

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;