نسخ من RaghadAlkhous/RestaurantDash
228 أسطر
6.8 KiB
JavaScript
228 أسطر
6.8 KiB
JavaScript
import React, { useState, useEffect } from 'react';
|
|
import StatisticsCard from './StatisticsCard';
|
|
import TopSellingProduct from './TopSellingProduct';
|
|
import SalesByLocation from './SalesByLocation';
|
|
import {
|
|
Box,
|
|
useTheme,
|
|
useMediaQuery,
|
|
Skeleton,
|
|
Button,
|
|
Typography,
|
|
ButtonGroup
|
|
} from '@mui/material';
|
|
import CalendarTodayOutlinedIcon from '@mui/icons-material/CalendarTodayOutlined';
|
|
|
|
const AnalyticsPage = () => {
|
|
const [timeFrame, setTimeFrame] = useState('month');
|
|
const theme = useTheme();
|
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
|
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
|
|
const [hasProducts, setHasProducts] = useState(false);
|
|
const [isLoading, setIsLoading] = useState(true);
|
|
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
|
|
|
|
const dailyData = [
|
|
{ date: '10:00', visitors: 1500, conversions: 300 },
|
|
{ date: '11:00', visitors: 1800, conversions: 320 },
|
|
];
|
|
|
|
const weeklyData = [
|
|
{ label: 'Week 1', visitors: 1500, conversions: 200 },
|
|
{ label: 'Week 2', visitors: 2300, conversions: 400 },
|
|
];
|
|
|
|
const monthlyData = [
|
|
{ label: 'Jan', visitors: 15000, conversions: 3000 },
|
|
{ label: 'Feb', visitors: 18000, conversions: 4000 },
|
|
];
|
|
|
|
const yearlyData = [
|
|
{ label: '2024', visitors: 25000, conversions: 7000 },
|
|
{ label: '2025', visitors: 38000, conversions: 12000 },
|
|
];
|
|
|
|
|
|
const getData = () => {
|
|
switch (timeFrame) {
|
|
case '24h':
|
|
return dailyData;
|
|
case '7d':
|
|
return weeklyData;
|
|
case '30d':
|
|
return monthlyData;
|
|
case '12m':
|
|
return yearlyData;
|
|
case 'all':
|
|
return [...yearlyData, ...monthlyData, ...weeklyData, ...dailyData];
|
|
default:
|
|
return dailyData;
|
|
}
|
|
};
|
|
|
|
const topSellingProducts = [
|
|
{ product: 'Apple Watch', sales: 150, amount: 45000, price: 299, status: 'Published' },
|
|
{ product: 'Samsung Galaxy', sales: 90, amount: 36000, price: 400, status: 'Low Stock' },
|
|
{ product: 'Sony Headphones', sales: 60, amount: 18000, price: 299, status: 'Draft' },
|
|
];
|
|
|
|
const salesData = [
|
|
{ country: 'United Kingdom', amount: 17678, change: 12, sales: 340 },
|
|
{ country: 'Spain', amount: 5500, change: -5, sales: 100 },
|
|
{ country: 'Germany', amount: 24189, change: -25, sales: 540 },
|
|
];
|
|
|
|
useEffect(() => {
|
|
const checkProducts = async () => {
|
|
setIsLoading(true);
|
|
const productsExist = await new Promise((resolve) =>
|
|
setTimeout(() => resolve(true), 1500)
|
|
);
|
|
setHasProducts(productsExist);
|
|
setIsLoading(false);
|
|
};
|
|
checkProducts();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const handleResize = () => {
|
|
setSidebarOpen(window.innerWidth >= theme.breakpoints.values.md);
|
|
};
|
|
handleResize();
|
|
window.addEventListener('resize', handleResize);
|
|
return () => window.removeEventListener('resize', handleResize);
|
|
}, [theme.breakpoints.values.md]);
|
|
|
|
return (
|
|
<Box
|
|
p={{ xs: 1, sm: 2 }}
|
|
maxWidth="100%"
|
|
overflowX="hidden"
|
|
>
|
|
{/* Header Buttons */}
|
|
<Box
|
|
display="flex"
|
|
flexDirection={{ xs: 'column', sm: 'row' }}
|
|
justifyContent="space-between"
|
|
alignItems="center"
|
|
gap={2}
|
|
mb={3}
|
|
>
|
|
<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: 'All Time', value: 'all' },
|
|
{ label: '12 Months', value: '12m' },
|
|
{ label: '30 Days', value: '30d' },
|
|
{ label: '7 Days', value: '7d' },
|
|
{ label: '24 Hour', value: '24h' },
|
|
].map(({ label, value }) => (
|
|
<Button
|
|
key={value}
|
|
variant={timeFrame === value ? 'contained' : 'text'}
|
|
onClick={() => setTimeFrame(value)}
|
|
>
|
|
{label}
|
|
</Button>
|
|
))}
|
|
</ButtonGroup>
|
|
|
|
<Box display="flex" gap={2} flexWrap="wrap" justifyContent={{ xs: 'space-between', sm: 'flex-end' }} width={{ xs: '100%', sm: 'auto' }}>
|
|
<Button
|
|
variant="contained"
|
|
sx={{
|
|
textTransform: 'none',
|
|
color: '#667085',
|
|
backgroundColor: 'white',
|
|
boxShadow: 'none',
|
|
borderRadius: '8px',
|
|
height: '40px',
|
|
fontSize: '13px',
|
|
fontWeight: 500,
|
|
border: '1px solid #e0e0e0',
|
|
gap: 1,
|
|
minWidth: '120px'
|
|
}}
|
|
>
|
|
<CalendarTodayOutlinedIcon sx={{ fontSize: 16 }} />
|
|
{!isSmallScreen && 'Select Dates'}
|
|
</Button>
|
|
|
|
<Button
|
|
variant="contained"
|
|
sx={{
|
|
textTransform: 'none',
|
|
color: 'white',
|
|
backgroundColor: theme.palette.primary.main,
|
|
borderRadius: '8px',
|
|
height: '40px',
|
|
fontWeight: 600,
|
|
fontSize: '14px',
|
|
minWidth: '100px'
|
|
}}
|
|
>
|
|
KPIs Filter
|
|
</Button>
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Data Sections */}
|
|
<Box display="flex" flexDirection={{ xs: 'column', md: 'row' }} gap={2} mb={3}>
|
|
<Box flex={2}>
|
|
<TopSellingProduct data={topSellingProducts} />
|
|
</Box>
|
|
<Box flex={1}>
|
|
<SalesByLocation data={salesData} />
|
|
</Box>
|
|
</Box>
|
|
|
|
{/* Chart Section */}
|
|
<Box>
|
|
{isLoading ? (
|
|
<>
|
|
<Skeleton variant="rectangular" height={50} sx={{ mb: 2 }} />
|
|
<Skeleton variant="rectangular" height={200} sx={{ mb: 2 }} />
|
|
<Skeleton variant="rectangular" height={300} sx={{ mb: 2 }} />
|
|
</>
|
|
) : (
|
|
<StatisticsCard
|
|
title="Analytics Overview"
|
|
subtitle="Performance Metrics"
|
|
data={getData()}
|
|
dataKeys={[
|
|
{ key: 'visitors', name: 'Visitors', color: '#4CAF50' },
|
|
{ key: 'conversions', name: 'Conversions', color: '#9C27B0' },
|
|
]}
|
|
xDataKey={timeFrame === '24h' ? 'date' : 'label'}
|
|
timeFrame={timeFrame}
|
|
onTimeFrameChange={setTimeFrame}
|
|
/>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
export default AnalyticsPage;
|