1
0

update the dashbord and router

هذا الالتزام موجود في:
raghad
2025-05-19 12:53:59 +03:00
الأصل 9b0d90560e
التزام aacc58c4a6
110 ملفات معدلة مع 6404 إضافات و44 حذوفات

عرض الملف

@@ -0,0 +1,112 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Skeleton } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
import AnalyticsContect from './AnalyticsContect';
const drawerWidth = 230;
const AnalyticsPage = () => {
const [timeFrame, setTimeFrame] = useState('month');
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة التحقق من المنتجات
useEffect(() => {
const checkProducts = async () => {
setIsLoading(true);
const productsExist = await checkIfProductsExist(); // استبدل بمنطقك
setHasProducts(productsExist);
setIsLoading(false);
};
checkProducts();
}, []);
const checkIfProductsExist = async () => {
return new Promise((resolve) => setTimeout(() => resolve(true), 1500)); // محاكاة تأخير
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{ display: 'flex', height: '100vh', backgroundColor: '#F6F6F6', overflow: 'hidden' }}>
<Sidebar open={sidebarOpen} onClose={handleDrawerToggle} isMobile={isMobile} drawerWidth={drawerWidth} />
<Box
sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: { xs: '100%', sm: sidebarOpen ? `calc(100% - ${drawerWidth}px)` : '100%' },
marginLeft: 0,
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}
>
<KitchPlusAppBar onDrawerToggle={handleDrawerToggle} sidebarOpen={sidebarOpen} isMobile={isMobile} />
<Box sx={{
flexGrow: 1,
width: sidebarOpen ? 'calc(100% - 20px)' : '100%',
pt: { xs: 0.5, sm: 1 },
mt: { xs: 1, sm: 0 },
overflowY: 'auto',
pl: { xs: 0, sm: 1 },
pr: { xs: 1, sm: 1 },
pb: { xs: 1, sm: 2 },
scrollbarWidth: 'none',
'&::-webkit-scrollbar': { display: 'none' },
transition: theme.transitions.create(['margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
{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 }} />
</>
) : (
<AnalyticsContect />
)}
</Box>
</Box>
</Box>
);
};
export default AnalyticsPage;

عرض الملف

@@ -0,0 +1,227 @@
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;

عرض الملف

@@ -0,0 +1,124 @@
import React from 'react';
import {
Box,
Typography,
Paper,
List,
ListItem,
ListItemText,
ListItemSecondaryAction,
Chip,
IconButton,
useTheme,
useMediaQuery
} from '@mui/material';
import MoreVertIcon from '@mui/icons-material/MoreVert';
const SalesByLocation = ({ data }) => {
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
return (
<Paper sx={{
p: { xs: 1, sm: 2 },
borderRadius: '12px',
boxShadow: '0px 1px 3px rgba(0, 0, 0, 0.1)',
height: '95%', // إضافة هذه السطر
display: 'flex', // إضافة
flexDirection: 'column' // إضافة
}}>
<Box sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mb: { xs: 0.5, sm: 1 }
}}>
<Box>
<Typography sx={{
color: '#1A1C21',
fontWeight: 500,
fontSize: { xs: '16px', sm: '18px' },
lineHeight: 1.2
}}>
Sales by Location
</Typography>
<Typography sx={{
color: '#667085',
fontWeight: 500,
fontSize: { xs: '12px', sm: '14px' },
lineHeight: 1.2
}}>
Sales performance by location
</Typography>
</Box>
<IconButton size={isSmallScreen ? 'small' : 'medium'}>
<MoreVertIcon fontSize={isSmallScreen ? 'small' : 'medium'} />
</IconButton>
</Box>
<List dense sx={{
flexGrow: 1, // إضافة هذه السطر
overflowY: 'auto',
'&::-webkit-scrollbar': {
display: 'none'
}
}}>
{data.map((item, i) => (
<ListItem key={i} disableGutters sx={{ py: { xs: 0.5, sm: 1 } }}>
<ListItemText
primary={
<Typography
sx={{
fontSize: { xs: '13px', sm: '14px' },
fontWeight: 400
}}
>
{item.country}
</Typography>
}
secondary={
<Typography
sx={{
fontSize: { xs: '11px', sm: '12px' },
color: theme.palette.text.secondary
}}
>
{item.sales} Sales
</Typography>
}
sx={{ my: 0 }}
/>
<ListItemSecondaryAction sx={{
display: 'flex',
alignItems: 'center',
gap: { xs: 0.5, sm: 1 }
}}>
<Typography
variant="body2"
sx={{
fontSize: { xs: '12px', sm: '14px' },
fontWeight: isSmallScreen ? 500 : 400
}}
>
${item.amount.toLocaleString()}
</Typography>
<Chip
label={`${item.change > 0 ? '+' : ''}${item.change}%`}
color={item.change > 0 ? 'success' : item.change < 0 ? 'error' : 'default'}
size={isSmallScreen ? 'small' : 'medium'}
sx={{
fontSize: { xs: '11px', sm: '12px' },
height: { xs: '24px', sm: '28px' },
'& .MuiChip-label': {
px: { xs: 0.5, sm: 1 }
}
}}
/>
</ListItemSecondaryAction>
</ListItem>
))}
</List>
</Paper>
);
};
export default SalesByLocation;

عرض الملف

@@ -0,0 +1,168 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
Box,
IconButton,
Paper,
Typography,
useTheme,
useMediaQuery
} from '@mui/material';
import {
AreaChart,
Area,
XAxis,
YAxis,
Tooltip,
Legend,
ResponsiveContainer,
CartesianGrid
} from 'recharts';
import MoreVertIcon from '@mui/icons-material/MoreVert';
const formatCurrency = (value) => {
if (value >= 1000000) return `$${(value / 1000000).toFixed(1)}M`;
if (value >= 1000) return `$${(value / 1000).toFixed(1)}K`;
return `$${value}`;
};
const StatisticsCard = ({
title = "Statistics",
subtitle = "Delivery Times",
data = [],
dataKeys = [
{ key: 'revenue', name: 'Revenue', color: '#E46A11' }, // << هنا تغيير اللون
{ key: 'sales', name: 'Sales', color: '#0182FC' } // << وهنا أيضاً
],
xDataKey = 'month',
valueFormatter = formatCurrency,
timeFrame = 'month',
onTimeFrameChange
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md'));
const handleTimeFrameChange = (newTimeFrame) => {
if (onTimeFrameChange) onTimeFrameChange(newTimeFrame);
};
return (
<Box sx={{ borderRadius: 2, width: { sm: '100%', md: '167vh' }}}>
<Paper sx={{
p: { xs: 1.5, sm: 2 },
mb: { xs: 2, sm: 2 },
boxShadow: '0px 4px 5px rgba(0, 0, 0, 0.1)',
borderRadius: 2,
position: 'relative'
}}>
<IconButton
aria-label="more-actions"
sx={{
position: 'absolute',
top: { xs: 4, sm: 8 },
right: { xs: 4, sm: 8 },
color: '#667085'
}}
>
<MoreVertIcon fontSize={isMobile ? 'small' : 'medium'} />
</IconButton>
{/* Header */}
<Box sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
mb: 2,
flexWrap: 'wrap',
gap: 1
}}>
<Box>
<Typography variant="h6" sx={{ fontSize: { xs: '15px', sm: '18px' }, fontWeight: 500 }}>
{title}
</Typography>
<Typography sx={{ fontSize: { xs: '11px', sm: '14px' }, fontWeight: 500, color: '#667085' }}>
{subtitle}
</Typography>
</Box>
</Box>
{/* Chart */}
<ResponsiveContainer width="100%" height={isMobile ? 250 : isTablet ? 290 : 295}>
<AreaChart data={data} margin={{
top: isMobile ? -30 : -45,
right: isMobile ? 15 : 30,
left: isMobile ? 10 : 20,
bottom: isMobile ? 10 : 20
}}>
<defs>
{dataKeys.map(({ key, color }) => (
<linearGradient key={key} id={`color-${key}`} x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={color} stopOpacity={0.8} />
<stop offset="100%" stopColor={color} stopOpacity={0} />
</linearGradient>
))}
</defs>
<CartesianGrid stroke="#eee" strokeDasharray="0 0" vertical={false} />
<XAxis
dataKey={xDataKey}
axisLine={false}
tickLine={false}
tickMargin={isMobile ? 8 : 15}
tick={{
fontSize: isMobile ? 11 : 12,
angle: -25, // تدوير النص لتفادي التزاحم
textAnchor: 'end'
}}
interval={0} // عرض كل القيم على محور X
/>
<YAxis
tickFormatter={valueFormatter}
axisLine={false}
tickLine={false}
tickMargin={isMobile ? 8 : 15}
tick={{ fontSize: isMobile ? 11 : 12 }}
/>
<Tooltip formatter={valueFormatter} />
<Legend
verticalAlign="top"
height={isMobile ? 30 : 36}
iconType="circle"
iconSize={isMobile ? 8 : 10}
wrapperStyle={{ paddingBottom: isMobile ? '15px' : '20px' }}
/>
{dataKeys.map(({ key, name, color }) => (
<Area
key={key}
name={name}
type="monotone"
dataKey={key}
stroke={color} // لون الخط
strokeWidth={isMobile ? 2 : 3}
fill={`url(#color-${key})`} // لون التعبئة بتدرج
/>
))}
</AreaChart>
</ResponsiveContainer>
</Paper>
</Box>
);
};
StatisticsCard.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string,
data: PropTypes.arrayOf(PropTypes.object),
dataKeys: PropTypes.arrayOf(PropTypes.shape({
key: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
color: PropTypes.string.isRequired
})),
xDataKey: PropTypes.string,
valueFormatter: PropTypes.func,
timeFrame: PropTypes.oneOf(['day', 'week', 'month', 'year']),
onTimeFrameChange: PropTypes.func
};
export default StatisticsCard;

عرض الملف

@@ -0,0 +1,22 @@
import React from 'react';
import { Button, Stack } from '@mui/material';
const options = ['All Time', '12 Months', '30 Days', '7 Days', '24 Hour'];
const TimeFrameSelector = ({ selected, onChange }) => (
<Stack direction="row" spacing={1} sx={{ flexWrap: 'wrap', mb: 2 }}>
{options.map(option => (
<Button
key={option}
size="small"
variant={selected === option ? 'contained' : 'outlined'}
onClick={() => onChange(option)}
sx={{ textTransform: 'none' }}
>
{option}
</Button>
))}
</Stack>
);
export default TimeFrameSelector;

عرض الملف

@@ -0,0 +1,215 @@
import React, { useState } from 'react';
import { useTheme } from '@mui/material/styles';
import { useMediaQuery } from '@mui/material';
import {
Box,
Typography,
Paper,
Table,
TableBody,
TableCell,
TableHead,
TableRow,
Chip,
Pagination,
Button,
Avatar,
TableContainer
} from '@mui/material';
import TuneIcon from '@mui/icons-material/Tune';
import { green } from '@mui/material/colors';
import AssignmentIcon from '@mui/icons-material/Assignment';
const TopSellingProduct = ({ data = [] }) => {
const theme = useTheme();
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 5;
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const pageCount = Math.ceil(data.length / itemsPerPage);
const paginatedData = data.slice(
(currentPage - 1) * itemsPerPage,
currentPage * itemsPerPage
);
return (
<Paper sx={{
borderRadius: 2,
width: '100%',
maxWidth: { xs: '100%', md: '115vh' },
height: { xs: 'auto', md: '100vh' },
display: 'flex',
flexDirection: 'column',
overflow: 'hidden',
boxShadow: theme.shadows[1]
}}>
{/* العنوان وزر الفلاتر */}
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
p={{ xs: 1, sm: 2 }}
sx={{ backgroundColor: theme.palette.background.paper }}
>
<Typography variant="h6" sx={{ fontSize: { xs: '1rem', sm: '1.25rem' } }}>
Top Selling Product
</Typography>
<Button
sx={{
fontSize: { xs: '12px', sm: '16px' },
fontWeight: 500,
border: '1px solid #e0e0e0',
color: '#667085',
textTransform: 'none',
p: { xs: '4px 8px', sm: '6px 16px' }
}}
startIcon={<TuneIcon fontSize={isMobile ? 'small' : 'medium'} />}
>
{isMobile ? '' : 'Filters'}
</Button>
</Box>
{/* جدول البيانات */}
<TableContainer
sx={{
flexGrow: 1,
overflowX: 'auto',
maxHeight: { xs: '60vh', md: 'calc(100vh - 160px)' },
'&::-webkit-scrollbar': { height: 4 },
}}
>
<Table
size={isMobile ? 'small' : 'medium'}
sx={{
minWidth: 650,
'& .MuiTableCell-root': {
borderBottom: '1px solid #e0e0e0',
py: { xs: 0.5, sm: 1.5 },
px: { xs: 0.5, sm: 2 },
},
'& thead .MuiTableCell-root': {
borderBottom: 'none',
fontWeight: 600,
fontSize: { xs: '11px', sm: '14px' },
px: { xs: 0.5, sm: 2 },
},
}}
>
<TableHead sx={{ backgroundColor: '#F0F1F3' }}>
<TableRow sx={{ height: { xs: '6vh', sm: '10vh' } }}>
<TableCell>Product</TableCell>
{!isMobile && <TableCell>Sales</TableCell>}
<TableCell>Amount</TableCell>
{!isMobile && <TableCell>Price</TableCell>}
<TableCell>Status</TableCell>
</TableRow>
</TableHead>
<TableBody>
{paginatedData.map((row, i) => (
<TableRow key={i} sx={{ height: { xs: '8vh', sm: '13vh' } }}>
<TableCell>
<Box sx={{ display: 'flex', alignItems: 'center', gap: { xs: 1, sm: 2 } }}>
<Avatar
sx={{
bgcolor: green[50],
width: { xs: 28, sm: 40 },
height: { xs: 28, sm: 40 }
}}
variant="rounded"
>
<AssignmentIcon fontSize={isMobile ? 'small' : 'medium'} />
</Avatar>
<Box sx={{
fontSize: { xs: '11px', sm: '14px' },
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
maxWidth: { xs: '80px', sm: '200px' }
}}>
{row.product}
</Box>
</Box>
</TableCell>
{!isMobile && <TableCell sx={{ fontSize: { xs: '11px', sm: '14px' } }}>{row.sales}</TableCell>}
<TableCell sx={{ fontSize: { xs: '11px', sm: '14px' } }}>${row.amount.toLocaleString()}</TableCell>
{!isMobile && <TableCell sx={{ fontSize: { xs: '11px', sm: '14px' } }}>${row.price}</TableCell>}
<TableCell>
<Chip
label={isMobile ? row.status.substring(0, 3) : row.status}
size={isMobile ? 'small' : 'medium'}
sx={{
fontSize: { xs: '10px', sm: '14px' },
fontWeight: 600,
backgroundColor:
row.status === 'Published' ? '#E7F4EE' :
row.status === 'Low Stock' ? '#FDF1E8' :
row.status === 'Out of Stock' ? '#FFCDD2' : '#E0E0E0',
color:
row.status === 'Published' ? '#0D894F' :
row.status === 'Low Stock' ? '#E46A11' :
row.status === 'Out of Stock' ? '#C62828' : '#424242',
minWidth: { xs: '50px', sm: '100px' }
}}
/>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
{/* التذييل مع الترقيم */}
<Box
display="flex"
justifyContent="space-between"
alignItems="center"
p={{ xs: 1, sm: 2 }}
sx={{
position: 'sticky',
bottom: 0,
backgroundColor: theme.palette.background.paper,
borderTop: '1px solid #f0f0f0',
zIndex: 1
}}
>
<Typography
variant="body2"
color="text.secondary"
sx={{
fontSize: { xs: '11px', sm: '14px' },
whiteSpace: 'nowrap'
}}
>
Showing {(currentPage - 1) * itemsPerPage + 1} to {Math.min(currentPage * itemsPerPage, data.length)} of {data.length}
</Typography>
<Pagination
count={pageCount}
page={currentPage}
onChange={(event, value) => setCurrentPage(value)}
size={isMobile ? 'small' : 'medium'}
sx={{
'& .MuiPaginationItem-root': {
fontSize: { xs: '12px', sm: '14px' },
minWidth: { xs: 24, sm: 32 },
height: { xs: 24, sm: 32 },
backgroundColor: '#FFECE0',
color: theme.palette.primary.main,
borderRadius: '8px',
'&.Mui-selected': {
backgroundColor: '#FFB088',
color: '#fff',
},
'&:hover': {
backgroundColor: '#FFD6B5',
},
},
}}
/>
</Box>
</Paper>
);
};
export default TopSellingProduct;

عرض الملف

@@ -0,0 +1,210 @@
import React from 'react';
import {
AppBar,
Toolbar,
Typography,
Box,
IconButton,
Divider,
Avatar,
Button,
Autocomplete,
TextField,
InputAdornment,
useTheme,
useMediaQuery,
} from '@mui/material';
import { useLocation } from 'react-router-dom';
import MenuIcon from '@mui/icons-material/Menu';
import NotificationsOutlinedIcon from '@mui/icons-material/NotificationsOutlined';
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
import SearchIcon from '@mui/icons-material/Search';
const top100Films = [
{ title: 'The Shawshank Redemption' },
{ title: 'The Godfather' },
{ title: 'The Dark Knight' },
{ title: 'Pulp Fiction' },
];
const KitchPlusAppBar = ({ onDrawerToggle, sidebarOpen, isMobile }) => {
const location = useLocation();
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
const isMediumScreen = useMediaQuery(theme.breakpoints.between('sm', 'md'));
return (
<AppBar
sx={{
height: { xs: 56, sm: 64, md: 66 },
backgroundColor: '#F6F6F6',
color: 'black',
boxShadow: 'none',
borderBottom: '1px solid #e0e0e0',
position: 'sticky',
top: 0,
zIndex: theme.zIndex.appBar,
}}
>
<Toolbar
sx={{
px: { xs: 2, sm: 3, md: '24px' },
minHeight: { xs: '56px !important', sm: '64px !important' },
display: 'flex',
justifyContent: 'space-between',
}}
>
{/* Left side with toggle button */}
<Box sx={{ display: 'flex', alignItems: 'center' }}>
{/* Toggle button for mobile/tablet */}
{(isMobile || isMediumScreen) && (
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={onDrawerToggle}
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
)}
{location.pathname === '/dashboard' ? (
<Typography
variant="h6"
component="div"
sx={{
fontWeight: '500',
fontSize: { xs: '18px', sm: '20px', md: '24px' },
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
maxWidth: { xs: '200px', sm: 'none' }
}}
>
Welcome to KitchPlus
</Typography>
) : (
<Autocomplete
sx={{
width: { xs: '200px', sm: '250px', md: '300px' },
borderRadius: '8px',
}}
freeSolo
id="free-solo-2-demo"
disableClearable
options={top100Films.map((option) => option.title)}
renderInput={(params) => (
<TextField
{...params}
placeholder="Search"
InputProps={{
...params.InputProps,
type: 'search',
endAdornment: (
<InputAdornment position="end">
<SearchIcon sx={{ color: '#667085' }} />
</InputAdornment>
),
}}
sx={{
'& .MuiInputBase-root': {
backgroundColor: 'white',
height: { xs: 36, sm: 38, md: 40 },
},
}}
/>
)}
/>
)}
</Box>
{/* Right side */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: { xs: 0.8, sm: 1, md: 1.5 } }}>
{location.pathname === '/dashboard' && !isSmallScreen && (
<Button
variant="contained"
sx={{
display: { xs: 'none', sm: 'none', md: 'flex' }, // هذا السطر يخفي الزر عند xs و sm ويظهره من md وما فوق
color: 'white',
height: { xs: 32, sm: 36, md: 40 },
mr: { xs: '6px', sm: '8px', md: '10px' },
backgroundColor: '#61677F',
borderRadius: '8px',
fontWeight: 600,
fontSize: { xs: '12px', sm: '13px', md: '14px' },
textTransform: 'none',
whiteSpace: 'nowrap',
}}
>
{isMediumScreen ? 'Switch Company' : 'Switch Company Profits'}
</Button>
)}
{location.pathname === '/dashboard' && (
<Divider
orientation="vertical"
flexItem
sx={{
height: { xs: 30, sm: 36, md: 40 },
alignSelf: 'center',
mx: 1 // إضافة هامش أفقي إذا لزم الأمر
}}
/>
)}
<IconButton color="#667085" size={isSmallScreen ? 'small' : 'medium'}>
<NotificationsOutlinedIcon fontSize={isSmallScreen ? 'small' : 'medium'} />
</IconButton>
<Divider
orientation="vertical"
flexItem
sx={{
height: { xs: 30, sm: 36, md: 40 },
alignSelf: 'center'
}}
/>
<Avatar
alt="Admin"
src="/images/waitress3.png"
sx={{
width: { xs: 28, sm: 32, md: 40 },
height: { xs: 28, sm: 32, md: 40 }
}}
/>
{!isSmallScreen && (
<Typography
variant="body1"
sx={{
ml: { sm: 0.5, md: 1 },
color: '#61677F',
fontSize: { xs: '12px', sm: '13px', md: '14px' },
whiteSpace: 'nowrap',
overflow: 'hidden',
textOverflow: 'ellipsis',
maxWidth: { xs: '100px', sm: '120px', md: 'none' }
}}
>
Admin@gmail.com
</Typography>
)}
<IconButton
color="inherit"
sx={{
mt: 0.5,
color: '#A6ACB8',
padding: { xs: '4px', sm: '8px' }
}}
size={isSmallScreen ? 'small' : 'medium'}
>
<KeyboardArrowDownIcon fontSize={isSmallScreen ? 'small' : 'medium'} />
</IconButton>
</Box>
</Toolbar>
</AppBar>
);
};
export default KitchPlusAppBar;

عرض الملف

@@ -0,0 +1,105 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const Cashier = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي)
useEffect(() => {
// هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات
// مثلاً استدعاء API أو التحقق من state
const checkProducts = async () => {
// محاكاة لاستدعاء API
const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي
setHasProducts(productsExist);
};
checkProducts();
}, []);
// دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي)
const checkIfProductsExist = async () => {
// محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state
// return true;
return false; // غير هذه القيمة حسب منطقك
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor:'#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>Cashier</Typography>
</Box>
</Box>
);
};
export default Cashier;

عرض الملف

@@ -0,0 +1,105 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const CreateRestaurant = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي)
useEffect(() => {
// هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات
// مثلاً استدعاء API أو التحقق من state
const checkProducts = async () => {
// محاكاة لاستدعاء API
const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي
setHasProducts(productsExist);
};
checkProducts();
}, []);
// دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي)
const checkIfProductsExist = async () => {
// محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state
// return true;
return false; // غير هذه القيمة حسب منطقك
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor: '#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>CreateYourRestaurant</Typography>
</Box>
</Box>
);
};
export default CreateRestaurant;

عرض الملف

@@ -0,0 +1,107 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Skeleton } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
import DashbordContect from './DashboardContcet';
import NoProdectDash from './NoProdectDash';
const drawerWidth = 230;
const Dashboard = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة التحقق من المنتجات
useEffect(() => {
const checkProducts = async () => {
setIsLoading(true);
const productsExist = await checkIfProductsExist(); // استبدل بمنطقك
setHasProducts(productsExist);
setIsLoading(false);
};
checkProducts();
}, []);
const checkIfProductsExist = async () => {
return new Promise((resolve) => setTimeout(() => resolve(true), 1500)); // محاكاة تأخير
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{ display: 'flex', height: '100vh', backgroundColor: '#F6F6F6', overflow: 'hidden' }}>
<Sidebar open={sidebarOpen} onClose={handleDrawerToggle} isMobile={isMobile} drawerWidth={drawerWidth} />
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: { xs: '100%', sm: '100%', md: '100%' },
marginLeft: { xs: 0, sm: sidebarOpen ? `${drawerWidth}px` : 0, md: 0 },
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar onDrawerToggle={handleDrawerToggle} sidebarOpen={sidebarOpen} isMobile={isMobile} />
<Box sx={{
flexGrow: 1,
width: sidebarOpen ? 'calc(100% - 20px)' : '100%',
pt: { xs: 0.5, sm: 1 },
mt: { xs: 1, sm: 2 },
overflowY: 'auto',
pl: { xs: 0, sm: 2 },
pr: { xs: 1, sm: 2 },
pb: { xs: 1, sm: 2 },
scrollbarWidth: 'none',
'&::-webkit-scrollbar': { display: 'none' },
transition: theme.transitions.create(['margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
{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 }} />
</>
) : (
hasProducts ? <DashbordContect /> : <NoProdectDash />
)}
</Box>
</Box>
</Box>
);
};
export default Dashboard;

عرض الملف

@@ -0,0 +1,395 @@
import React from 'react';
import { Box, Button, Card, CardContent, Stack, Typography, useMediaQuery } from '@mui/material';
import AirportShuttleIcon from '@mui/icons-material/AirportShuttle';
import CampaignIcon from '@mui/icons-material/Campaign';
import Inventory2Icon from '@mui/icons-material/Inventory2';
import DeveloperBoardIcon from '@mui/icons-material/DeveloperBoard';
import ArrowOutwardIcon from '@mui/icons-material/ArrowOutward';
import { useTheme } from '@mui/material/styles';
import AddIcon from '@mui/icons-material/Add';
import OrderStatusCard from './OrderStatusCard';
import StatisticsCard from './StatisticsCard';
import RecentActivity from './RecentActivity';
const IconCircle = ({ children, bgColor = '#DEDEFA', outerColor = '#EFEFFD' }) => (
<Box
sx={{
position: 'relative',
width: { xs: 40, sm: 45, md: 50 },
height: { xs: 43, sm: 48, md: 53 },
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Box
sx={{
position: 'absolute',
width: { xs: 32, sm: 36, md: 40 },
height: { xs: 35, sm: 39, md: 43 },
borderRadius: '50%',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
backgroundColor: outerColor,
zIndex: 0,
}}
/>
<Box
sx={{
width: { xs: 24, sm: 27, md: 30 },
height: { xs: 27, sm: 30, md: 33 },
backgroundColor: bgColor,
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 1,
}}
>
{children}
</Box>
</Box>
);
const StatusCard = ({
icon,
statusText,
statusColor,
iconColor,
outerColor,
innerColor,
height = {
xs: 'calc(140px + 0.5vh)',
sm: 'calc(150px + 0.5vh)',
md: 'calc(162px + 0.5vh)'
},
width = {
xs: 'min(90%, 600px)', // تقليل من 90% إلى 85% والحد الأقصى من 300px إلى 280px
sm: 'clamp(220px, 23vw, 280px)', // تقليل جميع القيم
md: 'clamp(220px, 19vw, 300px)'
},
transition = 'width 0.3s ease',
iconSpacing = { xs: 6, sm: 8, md: 12 },
extraButton,
statusButtonWidth,
title = 'Point Of Sale',
}) => {
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
return (
<Card sx={{
height,
width,
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
p: 0,
pb: 2,
borderRadius: '8px',
boxShadow: 'none',
minWidth: { xs: 180, sm: 220 }
}}>
<CardContent>
<Box sx={{ display: 'flex', alignItems: 'center', gap: iconSpacing }}>
<IconCircle bgColor={innerColor} outerColor={outerColor}>
{React.cloneElement(icon, { sx: { color: iconColor, fontSize: { xs: 16, sm: 18, md: 20 } } })}
</IconCircle>
<Button
variant="contained"
sx={{
backgroundColor: '#E7F4EE',
color: statusColor,
textTransform: 'none',
boxShadow: 'none',
borderRadius: '100px',
width: statusButtonWidth || 'auto',
fontSize: { xs: '0.7rem', sm: '0.8rem', md: '0.9rem' },
px: { xs: 1, sm: 1.5 },
py: 0.5
}}
>
{statusText}
</Button>
</Box>
<Typography
variant="h6"
gutterBottom
mt={1.5}
sx={{
color: '#667085',
fontSize: { xs: '14px', sm: '15px', md: '16px' },
fontWeight: 500
}}
>
{title}
</Typography>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mt: 2 }}>
{extraButton ? extraButton : <Box />}
<Button
variant="contained"
sx={{
backgroundColor: '#F7F7F7',
width: { xs: '26px', sm: '28px', md: '30px' },
height: { xs: '26px', sm: '28px', md: '30px' },
minWidth: '0',
padding: 0,
borderRadius: '12px',
boxShadow: 'none',
'&:hover': {
backgroundColor: '#e0e0e0',
},
}}
>
<ArrowOutwardIcon
sx={{
color: theme.palette.primary.main,
width: { xs: '16px', sm: '18px', md: '20px' },
height: { xs: '16px', sm: '18px', md: '20px' },
}}
/>
</Button>
</Box>
</CardContent>
</Card>
);
};
const DashboardContect = () => {
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
const isMediumScreen = useMediaQuery(theme.breakpoints.between('sm', 'md'));
return (
<>
{/* Header Section */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: { xs: 'flex-start', sm: 'center', md: 'center' },
mb: 3,
pl: 1,
pr: { xs: 1, sm: 3 },
flexDirection: { xs: 'column', sm: 'row', md: 'row' },
gap: { xs: 2, sm: 0 }
}}
>
{/* Title */}
<Typography
variant="h6"
sx={{
fontWeight: '500',
fontSize: { xs: '20px', sm: '22px', md: '24px' },
color: '#121212'
}}
>
Dashboard
</Typography>
{/* Buttons */}
<Box sx={{
display: 'flex',
gap: { xs: 1, sm: 2 },
flexWrap: { xs: 'wrap', sm: 'nowrap' },
width: { xs: '100%', sm: 'auto' },
justifyContent: { xs: 'space-between', sm: 'space-between', md: 'flex-end' }
}}>
<Button
variant="contained"
sx={{
textTransform: 'none',
color: 'white',
backgroundColor: theme.palette.primary.main,
boxShadow: 'none',
borderRadius: '8px',
height: '40px',
width: { xs: '48%', sm: '130px', md: '156px' },
fontSize: { xs: '12px', sm: '13px', md: '14px' },
fontWeight: 600,
p: 0,
m: 0,
whiteSpace: 'nowrap',
minWidth: 'unset'
}}
>
<AddIcon sx={{ fontSize: { xs: 16, sm: 18, md: 20 } }} />
{!isSmallScreen && 'Add New Menu'}
</Button>
<Button
variant="contained"
sx={{
textTransform: 'none',
color: 'white',
backgroundColor: '#5F6868',
boxShadow: 'none',
borderRadius: '8px',
height: '40px',
width: { xs: '48%', sm: '150px', md: '208px' },
fontSize: { xs: '12px', sm: '13px', md: '14px' },
fontWeight: 600,
p: 0,
m: 0,
whiteSpace: 'nowrap',
minWidth: 'unset'
}}
>
{isSmallScreen ? 'Marketing' : 'Start Marketing '}
</Button>
<Button
variant="contained"
sx={{
textTransform: 'none',
color: 'black',
backgroundColor: '#FFFFFF',
boxShadow: 'none',
borderRadius: '8px',
height: '40px',
width: { xs: '100%', sm: '120px', md: '141px' },
fontSize: { xs: '12px', sm: '13px', md: '14px' },
fontWeight: 600,
p: 0,
m: 0,
whiteSpace: 'nowrap',
minWidth: 'unset'
}}
>
Check Inventory
</Button>
</Box>
</Box>
{/* Status Cards */}
<Box
sx={{
display: 'flex',
gap: { xs: 1.5, sm: 2 },
flexWrap: 'wrap',
justifyContent: { xs: 'center', sm: 'flex-start' }
}}
>
<StatusCard
icon={<DeveloperBoardIcon />}
statusText="Active"
statusColor="#0D894F"
iconColor="#057DEC"
innerColor="#DEDEFA"
outerColor="#EFEFFD"
iconSpacing={{ xs: 6, sm: 8, md: 12 }}
extraButton={
<Button
variant="contained"
sx={{
backgroundColor: '#F6F6F6',
color: '#5F6868',
textTransform: 'none',
fontSize: { xs: '0.7rem', sm: '0.8rem', md: '0.85rem' },
borderRadius: '8px',
padding: { xs: '2px 8px', sm: '4px 12px' },
boxShadow: 'none',
fontWeight: 600,
height: { xs: 32, sm: 36, md: 40 },
width: { xs: 70, sm: 80, md: 85 },
whiteSpace: 'nowrap',
}}
>
Register
</Button>
}
/>
<StatusCard
icon={<Inventory2Icon />}
statusText="Active"
statusColor="#0D894F"
iconColor="#34B405"
innerColor="#E1F6DF"
outerColor="#EDFBE9"
iconSpacing={{ xs: 6, sm: 8, md: 12 }}
title="Inventory"
/>
<StatusCard
icon={<CampaignIcon />}
statusText="Pending"
statusColor="#BBB50F"
iconColor="#990463"
innerColor="#FEC8EA"
outerColor="#FFE3F5"
iconSpacing={{ xs: 6, sm: 8, md: 12 }}
title="Marketing"
/>
<StatusCard
icon={<AirportShuttleIcon />}
statusText="Action Need"
statusColor="#EF0A0A"
iconColor="#069797"
outerColor="#DBFBFB"
innerColor="#B5F5F5"
iconSpacing={{ xs: 3, sm: 5, md: 7 }}
title="Delivery"
/>
</Box>
{/* OrderStatusCard/ StatisticsCard */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
flexWrap: 'nowrap',
flexDirection: { xs: 'column', sm: 'row' },
gap: { xs: 1, sm: 1, md: 7 }, // gap مرن
mb: 1,
pl: 1,
pr: 1,
mt: 2,
ml: { xs: 2, sm: 0 },
mr: 2,
flexShrink: 0,
}}
>
{/* OrderStatusCard */}
<Box
sx={{
flexGrow: 0,
width: { xs: '100%', sm: '35%', md: '30%' },
minWidth: 220,
ml: { xs: 0, sm: -1 },
flexShrink: 0,
}}
>
<OrderStatusCard />
</Box>
{/* StatisticsCard */}
<Box
sx={{
flexGrow: 1,
minWidth: 0,
ml: { xs: 0, sm: 2 },
// backgroundColor:'red'
}}
>
<StatisticsCard />
</Box>
</Box>
{/* RecentActivity */}
<Box
sx={{
mr: { xs: 4, sm: 3 ,md:0 },
ml: { xs: 2, sm: 0 },
}}
>
<RecentActivity />
</Box>
</>
);
};
export default DashboardContect;

عرض الملف

@@ -0,0 +1,109 @@
import React from 'react';
import {
Box,
Button,
Card,
CardContent,
Typography,
useMediaQuery
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
import AddIcon from '@mui/icons-material/Add';
const NoProdectDash = () => {
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
return (
<>
{/* Header Section */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: { xs: 'flex-start', sm: 'center', md: 'center' },
mb: 3,
pl: 1,
pr: { xs: 1, sm: 3 },
flexDirection: { xs: 'column', sm: 'row', md: 'row' },
gap: { xs: 2, sm: 0 }
}}
>
<Typography
variant="h6"
sx={{
fontWeight: '500',
fontSize: { xs: '20px', sm: '22px', md: '24px' },
color: '#121212'
}}
>
Dashboard
</Typography>
</Box>
{/* Empty State Content */}
<Card
sx={{
boxShadow: 'none',
p: 4,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
backgroundColor: 'transparent'
}}
>
<CardContent>
{/* Image Placeholder */}
<Box
component="img"
src="/images/compeoter.png"
alt="No products available"
sx={{
width: isSmallScreen ? 150 : 200,
height: 'auto',
mb: 1,
opacity: 0.8
}}
/>
{/* Title with colored "Sorry!" */}
<Typography
variant="h5"
sx={{
fontWeight: 400,
fontSize: { xs: '14px', md: '18px' },
mb: 2,
color: '#5F6868',
whiteSpace: 'pre-line' // هذا يسمح بكسر السطر عند المسافات
}}
>
<Box component="span" sx={{ fontWeight: 600, fontSize: '18px' }}>Sorry!</Box>{' '}
There is no campaign available.
Please initiate the {'\n'}creation of a new campaign.
</Typography>
{/* Action Button */}
{/* <Button
variant="contained"
startIcon={<AddIcon />}
sx={{
textTransform: 'none',
px: 4,
py: 1.5,
fontSize: '16px',
fontWeight: 600,
borderRadius: 2,
color:'white'
}}
>
Create New Product
</Button> */}
</CardContent>
</Card>
</>
);
};
export default NoProdectDash;

عرض الملف

@@ -0,0 +1,260 @@
import React from 'react';
import {
Box,
Typography,
Card,
CardContent,
Divider,
Chip,
useTheme,
IconButton,
useMediaQuery
} from '@mui/material';
import {
TrendingUp as TrendingUpIcon,
TrendingDown as TrendingDownIcon,
CheckCircle as CheckCircleIcon,
Cancel as CancelIcon,
Pending as PendingIcon
} from '@mui/icons-material';
import MoreVertIcon from '@mui/icons-material/MoreVert';
import {
CircularProgressbar,
buildStyles
} from 'react-circular-progressbar';
import 'react-circular-progressbar/dist/styles.css';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
// import { Box, IconButton, Paper, Typography, useTheme, useMediaQuery } from '@mui/material';
import {
ResponsiveContainer,
} from 'recharts';
const OrderStatusCard = ({
title = 'Order Status',
period = 'This Quarter',
progress = 70.5,
progressChange = '+10%',
progressDirection = 'up', // or 'down'
description = 'You succeeded in earning $240 today, its higher than yesterday',
completed = '$20k',
canceled = '$16k',
pending = '$1.5k'
}) => {
const theme = useTheme();
const progressColor = progressDirection === 'up' ? theme.palette.success.main : theme.palette.error.main;
const progressIcon = progressDirection === 'up' ? <TrendingUpIcon fontSize="small" /> : <TrendingDownIcon fontSize="small" />;
const highlightedDescription = description.replace(
/(\$\d+(?:\.\d+)?[kKmM]?)/g,
'<span style="color:#000;font-weight:500;">$1</span>'
);
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md'));
return (
<Card
sx={{
width: { xs: '96%', sm: '94%', md: 360 },
height: 'auto',
borderRadius: 2,
boxShadow: '0px 4px 5px rgba(0, 0, 0, 0.1)',
pl: { xs: 1, sm: 1 },
pr: { xs: 1, sm: 1 },
pb: { xs: 1, sm: 1 },
pt: { xs: 0, sm: 0 },
position: 'relative' // إضافة هذه الخاصية
}}
>
<ResponsiveContainer width="100%" height={isMobile ? '75vh' : isTablet ? '59vh' : 385}>
{/* زر الإجراءات في الزاوية العلوية اليمنى */}
<IconButton
aria-label="more-actions"
sx={{
position: 'absolute',
top: 8,
right: 8,
color: '#667085'
}}
>
<MoreVertIcon />
</IconButton>
<CardContent>
{/* Header */}
<Box
sx={{
display: 'flex',
flexDirection: 'column',
ml: 0 // هامش يسار لإفساح المجال للأيقونة
}}
>
<Typography
variant="h6"
sx={{
fontSize: { xs: '16px', sm: '18px' },
fontWeight: 500
}}
>
{title}
</Typography>
<Typography
sx={{
fontSize: { xs: '12px', sm: '14px' },
fontWeight: 500,
color: '#667085'
}}
>
{period}
</Typography>
</Box>
{/* Progress Circle */}
<Box sx={{ height: 120, mb: 2, position: 'relative' }}>
{/* تغيير النسبة تحت الدائرة */}
<Box
sx={{
position: 'absolute',
top: '80%',
left: '50%',
transform: 'translate(-50%, -50%)',
textAlign: 'center',
}}
>
<Chip
label={progressChange}
size="small"
icon={progressIcon}
sx={{
height: 22,
fontSize: '0.75rem',
color: progressDirection === 'up' ? '#087443' : '#B42318',
backgroundColor: progressDirection === 'up' ? '#ECFDF3' : '#FEF3F2',
'.MuiChip-icon': {
color: progressDirection === 'up' ? '#087443' : '#B42318',
},
}}
/>
</Box>
{/* دائرة التقدم */}
<Box sx={{ position: 'relative', width: '100%', maxWidth: 250, mx: 'auto' }}>
<CircularProgressbar
value={100}
circleRatio={0.5}
strokeWidth={5}
styles={buildStyles({
rotation: 0.75,
strokeLinecap: 'round',
trailColor: '#eee',
pathColor: '#eee',
})}
/>
<Box sx={{ position: 'absolute', top: -1.5, left: 0, width: '100%', height: '100%' }}>
<CircularProgressbar
value={progress}
circleRatio={0.5}
strokeWidth={6}
styles={buildStyles({
rotation: 0.75,
strokeLinecap: 'round',
trailColor: 'transparent',
pathColor: theme.palette.primary.main,
textColor: 'transparent',
})}
/>
</Box>
{/* النص داخل الدائرة */}
<Box
sx={{
position: 'absolute',
top: '22%',
left: '50%',
transform: 'translate(-50%, -50%)',
fontSize: { xs: '18px', sm: '24px' },
fontWeight: 500,
color: theme.palette.text.primary,
}}
>
{`${progress}%`}
</Box>
</Box>
</Box>
{/* الوصف */}
<Typography
variant="body2"
sx={{
mb: 1,
mt: 5,
color: '#667085',
fontSize: { xs: '14px', sm: '16px' },
}}
dangerouslySetInnerHTML={{ __html: highlightedDescription }}
/>
<Divider sx={{ my: 2 }} />
{/* الحقول الثلاثة (Completed / Canceled / Pending) */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
gap: { xs: 1, sm: 2 },
flexDirection: { xs: 'column', sm: 'row' },
ml: -1
}}
>
{/* لكل قسم: */}
{[{
label: 'Completed',
icon: <ArrowUpwardIcon color="success" fontSize="small" sx={{ mt: 0.2, ml: -1 }} />,
value: completed
}, {
label: 'Canceled',
icon: <ArrowDownwardIcon color="error" fontSize="small" sx={{ mt: 0.6, ml: -1 }} />,
value: canceled
}, {
label: 'Pending',
icon: <ArrowDownwardIcon color="warning" fontSize="small" sx={{ mt: 0.6, ml: -1 }} />,
value: pending
}].map(({ label, icon, value }, i) => (
<Box
key={i}
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
flex: 1,
mb: { xs: 1, sm: 0 }
}}
>
<Typography
variant="body2"
sx={{ color: '#667085', fontSize: '12px', fontWeight: 500, mb: 1 }}
>
{label}
</Typography>
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
{icon}
<Typography sx={{ color: '#333843', fontSize: { xs: '14px', sm: '16px',md:'24px'}, fontWeight: 500 }}>
{value}
</Typography>
</Box>
</Box>
))}
</Box>
</CardContent>
</ResponsiveContainer>
</Card>
);
};
export default OrderStatusCard;

عرض الملف

@@ -0,0 +1,107 @@
import React from 'react';
import {
Box,
Typography,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
Paper,
Button,
Chip
} from '@mui/material';
// import LocalShippingIcon from '@mui/icons-material/LocalShipping';
// import InventoryIcon from '@mui/icons-material/Inventory';
// import AssignmentIcon from '@mui/icons-material/Assignment';
const RecentActivity = () => {
// Sample data
const activities = [
{
id: 1,
order: 'Order #1234 completed',
delivery: 'Delivery en route',
inventory: 'Low stock on item #567'
},
{
id: 2,
order: 'Order #1235 completed',
delivery: 'Delivery delayed',
inventory: 'Low stock on item #890'
},
{
id: 3,
order: 'Order #1236 completed',
delivery: 'Delivery arrived',
inventory: 'Out of stock on item #123'
}
];
return (
<Box sx={{ width: '93.5%', p: 3, backgroundColor: "white", borderRadius: 2, }}>
<Typography variant="h5" gutterBottom sx={{ fontWeight: 600, fontSize: '20px', mb: 2 }}>
Recent Activity
</Typography>
<TableContainer component={Paper} sx={{ boxShadow: 'none', border: '1px solid #e0e0e0', borderRadius: 2 }}>
<Table sx={{ minWidth: 650 }} aria-label="recent activity table">
<TableHead sx={{ backgroundColor: '#f5f5f5', color: '#61677F' }}>
<TableRow sx={{ '& th': { borderBottom: 'none' } }}>
<TableCell sx={{ fontWeight: 500, fontSize: '16px', color: '#61677F' }}>New Orders</TableCell>
<TableCell sx={{ fontWeight: 500, fontSize: '16px', color: '#61677F' }}>Delivery Updates</TableCell>
<TableCell sx={{ fontWeight: 500, fontSize: '16px', color: '#61677F' }}>Inventory Alerts</TableCell>
<TableCell sx={{ fontWeight: 500, fontSize: '16px', color: '#61677F' }}>Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{activities.map((activity) => (
<TableRow key={activity.id}>
<TableCell>
<Box sx={{ display: 'flex', alignItems: 'center', color: '#4F5867', fontSize: '14px', fontWeight: 500 }}>
{activity.order}
</Box>
</TableCell>
<TableCell>
<Box sx={{ display: 'flex', alignItems: 'center', color: '#4F5867', fontSize: '14px', fontWeight: 500 }}>
{activity.delivery}
</Box>
</TableCell>
<TableCell>
<Box sx={{ display: 'flex', alignItems: 'center', color: '#4F5867', fontSize: '14px', fontWeight: 500 }}>
{activity.inventory}
</Box>
</TableCell>
<TableCell sx={{ width: '28%' }} >
<Box sx={{ display: 'flex', gap: 1 }}>
<Button
sx={{ color: 'white', borderRadius: '8px', fontWeight: 600, fontSize: '14px', height: '40px', width: '135px', textTransform: 'none' }}
variant="contained"
size="small"
>
Record Inventory
</Button>
<Button
sx={{ fontWeight: 600, fontSize: '14px', borderRadius: '8px', height: '40px', textTransform: 'none' }}
variant="outlined"
size="small"
>
Assign Task
</Button>
</Box>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</Box>
);
};
export default RecentActivity;

عرض الملف

@@ -0,0 +1,196 @@
import React from 'react';
import { Box, IconButton, Paper, Typography, useTheme, useMediaQuery } from '@mui/material';
import {
LineChart,
Line,
XAxis,
YAxis,
Tooltip,
Legend,
ResponsiveContainer,
Area,
AreaChart,
CartesianGrid,
defs,
linearGradient,
stop
} from 'recharts';
import MoreVertIcon from '@mui/icons-material/MoreVert';
const data = [
{ month: 'Jan', revenue: 4000, sales: 2400 },
{ month: 'Feb', revenue: 3000, sales: 1398 },
{ month: 'Mar', revenue: 2000, sales: 9800 },
{ month: 'Apr', revenue: 2780, sales: 3908 },
{ month: 'May', revenue: 1890, sales: 4800 },
{ month: 'Jun', revenue: 2390, sales: 3800 },
{ month: 'Jul', revenue: 3490, sales: 4300 },
{ month: 'Aug', revenue: 5000, sales: 4000 },
{ month: 'Sep', revenue: 4700, sales: 4200 },
{ month: 'Oct', revenue: 5200, sales: 4600 },
{ month: 'Nov', revenue: 4800, sales: 4400 },
{ month: 'Dec', revenue: 5300, sales: 4800 },
];
const formatCurrency = (value) => {
if (value >= 1000000) {
return `$${(value / 1000000).toFixed(1)}M`;
} else if (value >= 1000) {
return `$${(value / 1000).toFixed(1)}K`;
}
return `$${value}`;
};
const StatisticsCard = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const isTablet = useMediaQuery(theme.breakpoints.between('sm', 'md'));
return (
<Box sx={{ width: '100%' }}>
<Paper sx={{
p: { xs: 1.5, sm: 2 },
mb: { xs: 2, sm: 3 },
boxShadow: '0px 4px 5px rgba(0, 0, 0, 0.1)',
position: 'relative',
borderRadius: 2 ,
}}>
<IconButton
aria-label="more-actions"
sx={{
position: 'absolute',
top: { xs: 4, sm: 8 },
right: { xs: 4, sm: 8 },
color: '#667085'
}}
>
<MoreVertIcon fontSize={isMobile ? 'small' : 'medium'} />
</IconButton>
<Box sx={{
display: 'flex',
flexDirection: 'column',
mb: { xs: 1, sm: 2 },
pr: { xs: 3, sm: 4 }
}}>
<Typography variant="h6" sx={{
fontSize: { xs: '15px', sm: '18px' },
fontWeight: 500
}}>
Statistics
</Typography>
<Typography sx={{
fontSize: { xs: '11px', sm: '14px' },
fontWeight: 500,
color: '#667085'
}}>
Delivery Times
</Typography>
</Box>
<ResponsiveContainer width="100%" height={isMobile ? 250 : isTablet ? 290 : 295}>
<AreaChart data={data} margin={{
top: isMobile ? -30 : -45,
right: isMobile ? 15 : 30,
left: isMobile ? 10 : 20,
bottom: isMobile ? 10 : 20
}}>
<defs>
<linearGradient id="colorRevenue" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={theme.palette.primary.main} stopOpacity={0.8} />
<stop offset="100%" stopColor={theme.palette.primary.main} stopOpacity={0} />
</linearGradient>
<linearGradient id="colorSales" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#81C2FF" stopOpacity={0.8} />
<stop offset="100%" stopColor="#81C2FF" stopOpacity={0} />
</linearGradient>
</defs>
<CartesianGrid stroke="#eee" strokeDasharray="0 0" vertical={false} />
<XAxis
dataKey="month"
axisLine={false}
tickLine={false}
tickMargin={isMobile ? 8 : 15}
tick={{ fontSize: isMobile ? 11 : 12 }}
/>
<YAxis
tickFormatter={formatCurrency}
axisLine={false}
tickLine={false}
tickMargin={isMobile ? 8 : 15}
tick={{ fontSize: isMobile ? 11 : 12 }}
/>
<Tooltip />
<Legend
verticalAlign="top"
height={isMobile ? 30 : 36}
iconType="circle"
iconSize={isMobile ? 8 : 10}
wrapperStyle={{
paddingBottom: isMobile ? '15px' : '20px'
}}
/>
<Area
name="Revenue"
type="monotone"
dataKey="revenue"
stroke='#E46A11'
strokeWidth={isMobile ? 2 : 3}
fill="url(#colorRevenue)"
/>
<Area
type="monotone"
name="Sales"
dataKey="sales"
stroke="#0182FC"
strokeWidth={isMobile ? 2 : 3}
fill="url(#colorSales)"
/>
<Line
type="monotone"
dataKey="revenue"
stroke={theme.palette.primary.main}
strokeWidth={isMobile ? 2 : 3}
dot={{
r: isMobile ? 4 : 6,
fill: theme.palette.primary.main,
stroke: '#fff',
strokeWidth: 2
}}
activeDot={{
r: isMobile ? 6 : 8,
fill: theme.palette.primary.main,
stroke: '#fff',
strokeWidth: 2
}}
/>
<Line
type="monotone"
dataKey="sales"
stroke="#0182FC"
strokeWidth={isMobile ? 2 : 3}
dot={{
r: isMobile ? 4 : 6,
fill: "#0182FC",
stroke: '#fff',
strokeWidth: 2
}}
activeDot={{
r: isMobile ? 6 : 8,
fill: "#0182FC",
stroke: '#fff',
strokeWidth: 2
}}
/>
</AreaChart>
</ResponsiveContainer>
</Paper>
</Box>
);
};
export default StatisticsCard;

عرض الملف

@@ -0,0 +1,103 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const HostKitchen = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
useEffect(() => {
const checkProducts = async () => {
const productsExist = await checkIfProductsExist();
setHasProducts(productsExist);
};
checkProducts();
}, []);
// دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي)
const checkIfProductsExist = async () => {
// محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state
// return true;
return false; // غير هذه القيمة حسب منطقك
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor: '#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>HostKitchen</Typography>
</Box>
</Box>
);
};
export default HostKitchen;

عرض الملف

@@ -0,0 +1,105 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const Inventory = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي)
useEffect(() => {
// هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات
// مثلاً استدعاء API أو التحقق من state
const checkProducts = async () => {
// محاكاة لاستدعاء API
const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي
setHasProducts(productsExist);
};
checkProducts();
}, []);
// دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي)
const checkIfProductsExist = async () => {
// محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state
// return true;
return false; // غير هذه القيمة حسب منطقك
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor: '#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>Inventory</Typography>
</Box>
</Box>
);
};
export default Inventory;

عرض الملف

@@ -0,0 +1,105 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const RestaurantProfile = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة للتحقق من وجود المنتجات (استبدل هذا بمنطقك الفعلي)
useEffect(() => {
// هنا يجب استبدال هذا بمنطق فعلي للتحقق من وجود المنتجات
// مثلاً استدعاء API أو التحقق من state
const checkProducts = async () => {
// محاكاة لاستدعاء API
const productsExist = await checkIfProductsExist(); // استبدل هذه الدالة بمنطقك الفعلي
setHasProducts(productsExist);
};
checkProducts();
}, []);
// دالة مساعدة لمحاكاة التحقق من المنتجات (استبدلها بمنطقك الفعلي)
const checkIfProductsExist = async () => {
// محاكاة - يمكن أن يكون هذا استدعاء لـ API أو تحقق من state
// return true;
return false; // غير هذه القيمة حسب منطقك
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor: '#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>RestaurantProfile</Typography>
</Box>
</Box>
);
};
export default RestaurantProfile;

عرض الملف

@@ -0,0 +1,101 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const Setting = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
useEffect(() => {
const checkProducts = async () => {
const productsExist = await checkIfProductsExist();
setHasProducts(productsExist);
};
checkProducts();
}, []);
const checkIfProductsExist = async () => {
return false;
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor: '#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>Setting</Typography>
</Box>
</Box>
);
};
export default Setting;

عرض الملف

@@ -0,0 +1,207 @@
import React from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import {
Drawer,
List,
ListItem,
ListItemIcon,
ListItemText,
Box,
useTheme,
Typography
} from '@mui/material';
import {
DashboardRounded as DashboardIcon,
PointOfSale as CashierIcon,
AllInbox as SupplierIcon,
Store as InventoryIcon,
School as TrainingIcon,
AutoGraph as AnalyticsIcon,
Restaurant as RestaurantIcon,
CountertopsTwoTone as HostKitchenIcon,
Queue as CreateKitchenIcon,
Settings as SettingsIcon,
Logout as LogoutIcon
} from '@mui/icons-material';
const menuItems = [
{ text: 'Dashboard', icon: <DashboardIcon />, path: '/dashboard' },
{ text: 'Cashier', icon: <CashierIcon />, path: '/cashier' },
{ text: 'Supplier', icon: <SupplierIcon />, path: '/supplier' },
{ text: 'Inventory', icon: <InventoryIcon />, path: '/inventory' },
{ text: 'Training', icon: <TrainingIcon />, path: '/training' },
{ text: 'Analytics & Reporting', icon: <AnalyticsIcon />, path: '/analytics' },
{ text: 'Restaurant Profile', icon: <RestaurantIcon />, path: '/profile' },
{ text: 'Host Kitchen', icon: <HostKitchenIcon />, path: '/host-kitchen' },
{ text: 'Create Kitchen', icon: <CreateKitchenIcon />, path: '/create-kitchen' },
];
const bottomItems = [
{ text: 'Settings', icon: <SettingsIcon />, path: '/settings' },
{ text: 'Log Out', icon: <LogoutIcon />, path: '/login' },
];
const Sidebar = ({ open, onClose, isMobile, drawerWidth }) => {
const theme = useTheme();
const navigate = useNavigate();
const location = useLocation();
const renderListItems = (items) =>
items.map((item, index) => {
const isActive = location.pathname === item.path;
return (
<ListItem key={index} disablePadding sx={{ px: 1 }}>
<Box
onClick={() => {
if (item.text === 'Log Out') {
localStorage.removeItem('token');
}
navigate(item.path);
if (isMobile) onClose();
}}
sx={{
display: 'flex',
alignItems: 'center',
width: '100%',
borderRadius: '5px',
backgroundColor: isActive ? '#F8F6F8' : 'transparent',
px: 2,
py: 1,
cursor: 'pointer',
transition: 'background-color 0.2s',
'&:hover': {
backgroundColor: '#fffcf9d5',
},
}}
>
<ListItemIcon sx={{
color: isActive ? theme.palette.primary.main : '#A6ACB8',
minWidth: 36
}}>
{item.icon}
</ListItemIcon>
<ListItemText
primary={item.text}
primaryTypographyProps={{
sx: {
color: isActive ? theme.palette.primary.main : '#61677F',
fontSize: '0.875rem'
},
}}
/>
</Box>
</ListItem>
);
});
const drawer = (
<Box sx={{
height: '100%',
display: 'flex',
flexDirection: 'column',
bgcolor: 'background.paper'
}}>
<Box
sx={{
px: 2,
py: 1.5,
borderColor: 'divider',
position: 'sticky',
top: 0,
zIndex: 1,
bgcolor: 'background.paper'
}}
>
<Box display="flex" alignItems="center">
<Box
component="img"
src="/image.png"
alt="logo"
sx={{
width: 40,
height: 40,
objectFit: 'contain',
mr: 1.5,
}}
/>
<Box display="flex" alignItems="center">
<Typography
variant="h6"
sx={{
fontWeight: 400,
fontSize: '1.25rem',
color: 'text.primary',
}}
>
KITCH
</Typography>
<Typography
variant="h6"
sx={{
fontWeight: 400,
fontSize: '1.25rem',
color: 'primary.main',
ml: 0.5,
}}
>
PLUS
</Typography>
</Box>
</Box>
</Box>
<Box sx={{
flex: 1,
overflowY: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': { display: 'none' },
py: 1
}}>
<List>{renderListItems(menuItems)}</List>
</Box>
<Box sx={{
position: 'sticky',
bottom: 0,
bgcolor: 'background.paper',
borderColor: 'divider'
}}>
<List>{renderListItems(bottomItems)}</List>
</Box>
</Box>
);
return (
<Box
component="nav"
sx={{
width: { xs: 0, sm: 0, md: drawerWidth },
flexShrink: { xs: 0, sm: 0, md: 0 },
boxShadow: 'none',
}}
>
<Drawer
variant={isMobile ? 'temporary' : 'persistent'}
open={open}
onClose={onClose}
ModalProps={{ keepMounted: true }}
sx={{
'& .MuiDrawer-paper': {
width: drawerWidth,
boxSizing: 'border-box',
borderRight: 'none',
boxShadow: 'none'
},
}}
>
{drawer}
</Drawer>
</Box>
);
};
export default Sidebar;

عرض الملف

@@ -0,0 +1,102 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Typography } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
const drawerWidth = 230;
const Supplier = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false); // حالة لتتبع وجود المنتجات
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
useEffect(() => {
const checkProducts = async () => {
const productsExist = await checkIfProductsExist();
setHasProducts(productsExist);
};
checkProducts();
}, []);
const checkIfProductsExist = async () => {
return false;
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{
display: 'flex',
height: '100vh',
backgroundColor: '#F6F6F6',
overflow: 'hidden',
}}>
<Sidebar
open={sidebarOpen}
onClose={handleDrawerToggle}
isMobile={isMobile}
drawerWidth={drawerWidth}
/>
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: {
xs: '100%',
sm: '100%',
md: '100%'
},
marginLeft: {
xs: 0,
sm: sidebarOpen ? `${drawerWidth}px` : 0,
md: 0
},
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar
onDrawerToggle={handleDrawerToggle}
sidebarOpen={sidebarOpen}
isMobile={isMobile}
/>
<Typography>Supplier</Typography>
</Box>
</Box>
);
};
export default Supplier;

عرض الملف

@@ -0,0 +1,95 @@
import React from 'react';
import {
Box,
Button,
Card,
CardContent,
Typography,
useMediaQuery
} from '@mui/material';
import { useTheme } from '@mui/material/styles';
const NoTraining = () => {
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
return (
<>
{/* Header Section */}
<Box
sx={{
display: 'flex',
justifyContent: 'space-between',
alignItems: { xs: 'flex-start', sm: 'center', md: 'center' },
mb: 3,
pl: 1,
pr: { xs: 1, sm: 3 },
flexDirection: { xs: 'column', sm: 'row', md: 'row' },
gap: { xs: 2, sm: 0 }
}}
>
<Typography
variant="h6"
sx={{
fontWeight: '500',
fontSize: { xs: '20px', sm: '22px', md: '24px' },
color: '#121212'
}}
>
Dashboard
</Typography>
</Box>
{/* Empty State Content */}
<Card
sx={{
boxShadow: 'none',
p: 4,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
textAlign: 'center',
backgroundColor: 'transparent'
}}
>
<CardContent>
{/* Image Placeholder */}
<Box
component="img"
src="/images/compeoter.png"
alt="No products available"
sx={{
width: isSmallScreen ? 150 : 200,
height: 'auto',
mb: 1,
opacity: 0.8
}}
/>
{/* Title with colored "Sorry!" */}
<Typography
variant="h5"
sx={{
fontWeight: 400,
fontSize: { xs: '14px', md: '18px' },
mb: 2,
color: '#5F6868',
whiteSpace: 'pre-line' // هذا يسمح بكسر السطر عند المسافات
}}
>
<Box component="span" sx={{ fontWeight: 600, fontSize: '18px' }}>Sorry!</Box>{' '}
There are no updates now..
{'\n'}check back later.
</Typography>
{/* Action Button */}
</CardContent>
</Card>
</>
);
};
export default NoTraining;

عرض الملف

@@ -0,0 +1,107 @@
import React, { useState, useEffect } from 'react';
import { Box, useTheme, useMediaQuery, Skeleton } from '@mui/material';
import KitchPlusAppBar from '../AppBar';
import Sidebar from '../SideHome';
import NoTraining from './NoTraining';
const drawerWidth = 230;
const Dashboard = () => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const [hasProducts, setHasProducts] = useState(false);
const [isLoading, setIsLoading] = useState(true);
const [sidebarOpen, setSidebarOpen] = useState(!isMobile);
// محاكاة التحقق من المنتجات
useEffect(() => {
const checkProducts = async () => {
setIsLoading(true);
const productsExist = await checkIfProductsExist(); // استبدل بمنطقك
setHasProducts(productsExist);
setIsLoading(false);
};
checkProducts();
}, []);
const checkIfProductsExist = async () => {
return new Promise((resolve) => setTimeout(() => resolve(true), 1500)); // محاكاة تأخير
};
useEffect(() => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
}, [theme.breakpoints.values.md]);
useEffect(() => {
const handleResize = () => {
if (window.innerWidth >= theme.breakpoints.values.md) {
setSidebarOpen(true);
} else {
setSidebarOpen(false);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [theme.breakpoints.values.md]);
const handleDrawerToggle = () => {
setSidebarOpen(!sidebarOpen);
};
return (
<Box sx={{ display: 'flex', height: '100vh', backgroundColor: '#F6F6F6', overflow: 'hidden' }}>
<Sidebar open={sidebarOpen} onClose={handleDrawerToggle} isMobile={isMobile} drawerWidth={drawerWidth} />
<Box sx={{
flexGrow: 1,
display: 'flex',
flexDirection: 'column',
width: { xs: '100%', sm: '100%', md: '100%' },
marginLeft: { xs: 0, sm: sidebarOpen ? `${drawerWidth}px` : 0, md: 0 },
transition: theme.transitions.create(['width'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
<KitchPlusAppBar onDrawerToggle={handleDrawerToggle} sidebarOpen={sidebarOpen} isMobile={isMobile} />
<Box sx={{
flexGrow: 1,
width: sidebarOpen ? 'calc(100% - 20px)' : '100%',
pt: { xs: 0.5, sm: 1 },
mt: { xs: 1, sm: 2 },
overflowY: 'auto',
pl: { xs: 0, sm: 2 },
pr: { xs: 1, sm: 2 },
pb: { xs: 1, sm: 2 },
scrollbarWidth: 'none',
'&::-webkit-scrollbar': { display: 'none' },
transition: theme.transitions.create(['margin'], {
easing: theme.transitions.easing.sharp,
duration: theme.transitions.duration.leavingScreen,
}),
}}>
{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 }} />
</>
) : (
<NoTraining />
)}
</Box>
</Box>
</Box>
);
};
export default Dashboard;