update the dashbord and router

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

871
package-lock.json مولّد

تم حذف اختلاف الملف لأن الملف كبير جداً تحميل الاختلاف

عرض الملف

@@ -1,15 +1,22 @@
{
"name": "front-end-my-resturant",
"name": "resturant-dashBord",
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@mui/icons-material": "^7.1.0",
"@mui/material": "^7.1.0",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
"react": "^19.1.0",
"react-circular-progressbar": "^2.2.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.0",
"react-scripts": "5.0.1",
"recharts": "^2.15.3",
"web-vitals": "^2.1.4"
},
"scripts": {

ثنائية
public/favicon.ico

ملف ثنائي غير معروض.

قبل

العرض:  |  الارتفاع:  |  الحجم: 3.8 KiB

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_18pt-Black.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_18pt-Bold.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_18pt-Italic.ttf Normal file

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_18pt-Light.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_18pt-Medium.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_18pt-Thin.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_24pt-Black.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_24pt-Bold.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_24pt-Italic.ttf Normal file

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_24pt-Light.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_24pt-Medium.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_24pt-Thin.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_28pt-Black.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_28pt-Bold.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_28pt-Italic.ttf Normal file

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_28pt-Light.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_28pt-Medium.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/fonts/inter/Inter_28pt-Thin.ttf Normal file

ملف ثنائي غير معروض.

ملف ثنائي غير معروض.

ثنائية
public/icon.ico Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 7.8 KiB

ثنائية
public/image.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 6.2 KiB

ثنائية
public/images/compeoter.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 24 KiB

ثنائية
public/images/hand.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 55 KiB

ثنائية
public/images/icons/email.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 2.4 KiB

ثنائية
public/images/icons/image.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 6.6 KiB

ثنائية
public/images/icons/key.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 3.0 KiB

ثنائية
public/images/icons/pen.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 3.6 KiB

ثنائية
public/images/icons/rocket.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 4.3 KiB

ثنائية
public/images/waiterss2.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 44 KiB

ثنائية
public/images/waiterss4.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 45 KiB

ثنائية
public/images/waitress.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 1.2 MiB

ثنائية
public/images/waitress3.png Normal file

ملف ثنائي غير معروض.

بعد

العرض:  |  الارتفاع:  |  الحجم: 47 KiB

عرض الملف

@@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="icon" href="/image.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
@@ -10,34 +10,19 @@
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<style>
* {
margin: 0
}
</style>
<title>Restaurant</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>

عرض الملف

@@ -22,6 +22,7 @@
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
@@ -36,3 +37,88 @@
transform: rotate(360deg);
}
}
/* CUSTOM FONTS */
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-Thin.ttf');
font-weight: 100;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-ExtraLight.ttf');
font-weight: 200;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-Light.ttf');
font-weight: 300;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-Regular.ttf');
font-weight: 400;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-Medium.ttf');
font-weight: 500;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-SemiBold.ttf');
font-weight: 600;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-Bold.ttf');
font-weight: 700;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-ExtraBold.ttf');
font-weight: 800;
}
@font-face {
font-family: INTER;
src: url('../public/fonts/inter/Inter_18pt-Black.ttf');
font-weight: 900;
}
@font-face {
font-family: PlusJakartaSans ;
src: url('../public/fonts/PlusJakartaSans/PlusJakartaSans-Medium.ttf');
font-weight: 500;
}
@font-face {
font-family: PlusJakartaSans ;
src: url('../public/fonts/PlusJakartaSans/PlusJakartaSans-SemiBold.ttf');
font-weight: 600;
}
@font-face {
font-family: PlusJakartaSans ;
src: url('../public/fonts/PlusJakartaSans/PlusJakartaSans-Regular.ttf');
font-weight: 400;
}
/* === CUSTOM FONTS ===*/

عرض الملف

@@ -1,24 +1,48 @@
import logo from './logo.svg';
import React from 'react';
import './App.css';
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import LoginForm from './components/Authentication/SignUp_In/LoginForm';
import RegisterForm from './components/Authentication/SignUp_In/RegisterForm';
import ForgetPassword from './components/Authentication/ForgetPassword/ForgetFormMain';
import Dashboard from './components/Home/Dashboard/Dashboard';
import Inventory from './components/Home/Inventory/Inventory';
import Analytics from './components/Home/Analytics&Reporting/Analytics';
import Supplier from './components/Home/Supplier/Supplier';
import Cashier from './components/Home/Cashier/Cashier';
import CreateYourRestaurant from './components/Home/CreateYourRestaurant/CreateRestaurant';
import Training from './components/Home/Training/Training';
import RestaurantProfile from './components/Home/RestaurantProfile/RestaurantProfile';
import HostKitchen from './components/Home/HostKitchen/HostKitchen';
import Settings from './components/Home/Settings/Setting';
function App() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
</div>
<ThemeProvider theme={theme}>
<Router>
<Routes>
<Route path="/" element={<LoginForm />} />
<Route path="/login" element={<LoginForm />} />
<Route path="/register" element={<RegisterForm />} />
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/inventory" element={<Inventory />} />
<Route path="/settings" element={<Settings />} />
<Route path="/profile" element={<RestaurantProfile />} />
<Route path="/create-kitchen" element={<CreateYourRestaurant />} />
<Route path="/host-kitchen" element={<HostKitchen />} />
<Route path="/cashier" element={<Cashier />} />
<Route path="/supplier" element={<Supplier />} />
<Route path="/analytics" element={<Analytics />} />
<Route path="/forget" element={<ForgetPassword />} />
<Route path="/training" element={<Training />} />
</Routes>
</Router>
</ThemeProvider>
);
}

عرض الملف

@@ -0,0 +1,132 @@
import React from 'react';
import { Box, TextField, Typography, Button, useTheme } from '@mui/material';
import { useNavigate } from 'react-router-dom';
const Congratulations = ({ emailOrPhone, setEmailOrPhone }) => {
const navigate = useNavigate();
const theme = useTheme();
return (
<Box
sx={{
width: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
overflow: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
mt: { xs: 4, sm: 8, md: 2 } // هامش علوي متجاوب
}}
>
<Box
sx={{
marginTop: '90px',
position: 'relative',
width: 132,
height: 132,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Box
sx={{
position: 'absolute',
width: 139,
height: 139,
borderRadius: '50%',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
zIndex: 0,
backgroundColor: '#FAFAFA'
}}
/>
<Box
sx={{
width: 120,
height: 120,
backgroundColor: '#E9EFFF',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 1,
}}
>
<img
src="/images/hand.png"
style={{ width: 60, height: 60, objectFit: 'contain' }}
/>
</Box>
</Box>
<Typography
variant="h4"
fontWeight={700}
marginTop={3}
marginBottom={2}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
Congratulations!
</Typography>
<Typography
variant="h4"
fontWeight={400}
width='390px'
marginLeft='20px'
sx={{
color: '#5F6868',
fontSize: {
xs: '0.8rem',
md: '1.1rem'
}
}}
>
Your password has been successfully updated. Thank you for choosing our service
</Typography>
{/* زر التنقل إلى صفحة تسجيل الدخول */}
<Button
variant="contained"
fullWidth
onClick={() => navigate('/login')}
sx={{
marginTop: '20px',
color: 'white',
backgroundColor: theme.palette.primary.main,
borderRadius: '30px',
textTransform: 'none',
fontWeight: 500,
fontSize: '16px',
height: '52px',
padding: '12px',
maxWidth: '390px',
px: 2,
'&:hover': {
backgroundColor: theme.palette.primary.hover,
transition: 'all 0.4s ease'
}
}}
>
Login
</Button>
</Box>
);
};
export default Congratulations;

عرض الملف

@@ -0,0 +1,147 @@
// EmailInputSection.js
import React, { useState } from 'react';
import { Box, Button, TextField, Typography ,useTheme} from '@mui/material';
const EmailInputSection = ({ emailOrPhone, setEmailOrPhone }) => {
const theme = useTheme();
const [currentSlide, setCurrentSlide] = useState(0);
const slides = [0, 1, 2, 3];
const handleSend = () => {
// عملية الإرسال
};
const handleNext = () => {
if (currentSlide < slides.length - 1) {
setCurrentSlide(prev => prev + 1);
}
};
const handleBack = () => {
if (currentSlide > 0) {
setCurrentSlide(prev => prev - 1);
}
};
return (
<>
<Box>
<Box
component="img"
src="/image.png"
alt="logo"
sx={{
width: { xs: '5vh', sm: '7vh' },
maxWidth: { xs: '40px', sm: '80px' },
height: 'auto',
objectFit: 'contain',
overflow: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
}}
/>
</Box>
<Typography
variant="h4"
fontWeight={700}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
Forget Password
</Typography>
<Typography variant="body1" color="text.secondary">
Enter your email to reset it and regain access to your account.
</Typography>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
color="black"
sx={{
fontWeight: '500',
fontSize: '16px'
}}
>
Email/Phone
</Typography>
<TextField
placeholder="Enter your email"
type="email"
variant="outlined"
fullWidth
value={emailOrPhone}
onChange={(e) => setEmailOrPhone(e.target.value)}
sx={{
'& input': {
fontWeight: 500,
fontSize: '15px'
},
'& input::placeholder': {
color: '#969BA7'
},
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: '#FF914D',
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
}
}}
/>
</Box>
{/* send */}
<Button
variant="contained"
fullWidth
onClick={handleSend}
sx={{
color:'white',
backgroundColor: theme.palette.primary.main,
borderRadius: '30px',
textTransform: 'none',
fontWeight: 600,
fontSize: '16px',
height: '48px',
'&:hover': {
backgroundColor: theme.palette.primary.hover ,
transition: 'all 0.4s ease'
}
}}
>
Send
</Button>
<Typography
textAlign="center"
fontWeight={500}
sx={{
fontSize: '16px',
display: 'block',
width: '100%',
mx: 'auto',
color: '#969BA7'
}}
>
By log in, I agree to the&nbsp;
<a href="#" style={{ color: '#007bff', textDecoration: 'none' }}>Terms of Service</a> and&nbsp;
<a href="#" style={{ color: '#007bff', textDecoration: 'none' }}>Privacy Policy</a>
</Typography>
</>
);
};
export default EmailInputSection;

عرض الملف

@@ -0,0 +1,125 @@
import React, { useState } from 'react';
import { Box, Stack ,useTheme} from '@mui/material';
import Side from './Side';
import EmailInputSection from './EmailInputSection';
import OtpVerification from './OtpVerification';
import NewPassword from './NewPassword';
import Congratulations from './Congratulations';
const ForgetForm = () => {
const [emailOrPhone, setEmailOrPhone] = useState('');
const [currentSlide, setCurrentSlide] = useState(0);
const theme = useTheme();
const slides = [
{ component: EmailInputSection, title: "Email Verification" },
{ component: OtpVerification, title: "OTP Verification" },
{ component: NewPassword, title: "New Password" },
{ component: Congratulations, title: "Congratulations" }
];
const handleNext = () => {
if (currentSlide < slides.length - 1) {
setCurrentSlide(prev => prev + 1);
}
};
const handleBack = () => {
if (currentSlide > 0) {
setCurrentSlide(prev => prev - 1);
}
};
const CurrentComponent = slides[currentSlide].component;
return (
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', sm: 'row' },
minHeight: '100vh',
backgroundColor: '#fff',
}}
>
{/* ✅ Sidebar يظهر فقط من sm+ */}
<Box sx={{ width: { sm: '40%', xs: '0%' }, display: { xs: 'none', sm: 'block' } }}>
<Side currentStepIndex={currentSlide} onNext={handleNext} onBack={handleBack} />
</Box>
{/* ✅ Form */}
<Box
sx={{
width: { sm: '60%' },
minHeight: { xs: '100vh', sm: '130vh', md: '90vh' },
position: 'relative',
display: 'flex',
justifyContent: 'center',
alignItems: 'flex-start',
paddingTop: { xs: 2, sm: 4 },
paddingLeft: { xs: 2, sm: 4 },
backgroundColor: '#fff',
}}
>
<Box
sx={{
width: '100%',
maxWidth: 686,
pr: { xs: 3, sm: 2, md: 1 },
pt: { xs: 2, sm: 4, md: 1 },
}}
>
<Stack spacing={2} alignItems="flex-start">
{/* إظهار المكون الحالي فقط */}
<CurrentComponent
emailOrPhone={emailOrPhone}
setEmailOrPhone={setEmailOrPhone}
/>
</Stack>
</Box>
{/* ✅ مؤشر الشرائح السفلي */}
<Box
sx={{
position: { xs: 'absolute', sm: 'absolute' },
bottom: { xs: '5%', sm: '-1%', md: '2%' },
left: '50%',
transform: 'translateX(-50%)',
display: 'flex',
gap: 1,
width: '80%',
maxWidth: 600,
justifyContent: 'center',
height: {
xs: 3,
sm: 5,
md: 6,
},
}}
>
{slides.map((_, index) => (
<Box
key={index}
sx={{
width: '100vh',
height: 5,
bgcolor: index === currentSlide ? theme.palette.primary.main : 'rgba(0, 0, 0, 0.2)',
borderRadius: 2,
cursor: 'pointer',
transition: 'background-color 0.3s',
}}
// onClick={() => setCurrentSlide(index)} // يمكنك تفعيلها لاحقًا
/>
))}
</Box>
</Box>
</Box>
);
};
export default ForgetForm;

عرض الملف

@@ -0,0 +1,217 @@
// EmailInputSection.js
import React, { useState } from 'react';
import { Box, Button, TextField, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { IconButton, InputAdornment } from '@mui/material';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
import { VisibilityOutlined } from '@mui/icons-material';
const EmailInputSection = ({ emailOrPhone, setEmailOrPhone }) => {
const theme = useTheme();
const handleTogglePassword = () => {
setShowPassword((prev) => !prev);
};
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [currentSlide, setCurrentSlide] = useState(0);
const slides = [0, 1, 2, 3];
const handleSend = () => {
// عملية الإرسال
};
const handleToggleConfirmPassword = () => {
setShowConfirmPassword((prev) => !prev);
};
const handleNext = () => {
if (currentSlide < slides.length - 1) {
setCurrentSlide(prev => prev + 1);
}
};
const handleBack = () => {
if (currentSlide > 0) {
setCurrentSlide(prev => prev - 1);
}
};
return (
<>
<Box>
<Box
component="img"
src="/image.png"
alt="logo"
sx={{
width: { xs: '5vh', sm: '7vh' },
maxWidth: { xs: '40px', sm: '80px' },
height: 'auto',
objectFit: 'contain'
}}
/>
</Box>
<Typography
variant="h4"
fontWeight={700}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
Create a New Password
</Typography>
<Typography variant="body1" color="text.secondary">
Enter your email to reset it and regai access to your account.
</Typography>
{/* Password Input */}
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
color="black"
sx={{
fontWeight: '500',
fontSize: '16px'
}}
>
Password
</Typography>
<TextField
type={showPassword ? 'text' : 'password'}
placeholder="Enter your password"
fullWidth
variant="outlined"
autoComplete="new-password"
sx={{
'& input': {
fontWeight: 500,
fontSize: '15px'
},
'& input::placeholder': {
color: '#969BA7'
},
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleTogglePassword} edge="end">
{showPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Box>
{/* Confirm Password Input */}
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
color="black"
sx={{
fontWeight: '500',
fontSize: '16px'
}}
>
Confirm Password
</Typography>
<TextField
type={showConfirmPassword ? 'text' : 'password'}
placeholder="Confirm your password"
fullWidth
variant="outlined"
autoComplete="new-password"
sx={{
'& input': {
fontWeight: 500,
fontSize: '15px'
},
'& input::placeholder': {
color: '#969BA7'
},
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: '#FF914D',
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleToggleConfirmPassword} edge="end">
{showConfirmPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Box>
{/* send */}
<Button
variant="contained"
fullWidth
onClick={handleSend}
sx={{
color: 'white',
backgroundColor: theme.palette.primary.main,
borderRadius: '30px',
textTransform: 'none',
fontWeight: 600,
fontSize: '16px',
height: '48px',
'&:hover': {
backgroundColor: theme.palette.primary.hover ,
transition: 'all 0.4s ease'
}
}}
>
Send
</Button>
<Typography
textAlign="center"
fontWeight={500}
sx={{
fontSize: '16px',
display: 'block',
width: '100%',
mx: 'auto',
color: '#969BA7'
}}
>
By log in, I agree to the&nbsp;
<a href="#" style={{ color: '#007bff', textDecoration: 'none' }}>Terms of Service</a> and&nbsp;
<a href="#" style={{ color: '#007bff', textDecoration: 'none' }}>Privacy Policy</a>
</Typography>
</>
);
};
export default EmailInputSection;

عرض الملف

@@ -0,0 +1,183 @@
import React, { useState, useRef } from 'react';
import { Box, TextField, Typography, Button, Stack ,useTheme} from '@mui/material';
const OtpVerification = () => {
const [emailOrPhone, setEmailOrPhone] = useState('');
const [currentSlide, setCurrentSlide] = useState(0);
const slides = [0, 1, 2, 3];
const [otp, setOtp] = useState(Array(7).fill(''));
const inputRefs = useRef(Array(7).fill().map(() => React.createRef()));
const handleSend = () => {
const otpCode = otp.join('');
console.log('Submitted OTP:', otpCode);
// عملية التحقق من الكود
};
const handleOtpChange = (e, index) => {
const value = e.target.value;
if (!/^[0-9]?$/.test(value)) return;
const newOtp = [...otp];
newOtp[index] = value;
setOtp(newOtp);
if (value && index < 6) {
inputRefs.current[index + 1].current.focus();
}
};
const handleKeyDown = (e, index) => {
if (e.key === 'Backspace' && !otp[index] && index > 0) {
inputRefs.current[index - 1].current.focus();
}
};
const handleNext = () => {
if (currentSlide < slides.length - 1) {
setCurrentSlide(prev => prev + 1);
}
};
const handleBack = () => {
if (currentSlide > 0) {
setCurrentSlide(prev => prev - 1);
}
};
const theme = useTheme();
return (
<>
<Box>
<Box
component="img"
src="/image.png"
alt="logo"
sx={{
width: { xs: '5vh', sm: '7vh' },
maxWidth: { xs: '40px', sm: '80px' },
height: 'auto',
objectFit: 'contain'
}}
/>
</Box>
<Typography
variant="h4"
fontWeight={700}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
Enter OTP Verification
</Typography>
<Typography variant="body1" color="text.secondary">
Kindly enter the OTP code sent to your registered email/phone for account verification.
</Typography>
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column', gap: 1 }}>
<Stack
direction="row"
spacing={{ xs: 0, sm: 1, md: 1.5 }}
justifyContent={{ xs: 'center', sm: 'center', md: 'flex-start' }}
flexWrap="wrap"
sx={{
width: '100%',
px: { xs: 0, sm: '0.5rem', md: '1.5rem' },
gap: { xs: '1.5rem', sm: '1.5rem', md: '1rem' }
}}
>
{otp.map((digit, index) => (
<TextField
key={index}
inputRef={inputRefs.current[index]}
value={digit}
onChange={(e) => handleOtpChange(e, index)}
onKeyDown={(e) => handleKeyDown(e, index)}
inputProps={{
maxLength: 1,
style: {
textAlign: 'center',
fontSize: '20px',
},
}}
sx={{
width: { xs: '3rem', sm: '3.25rem', md: '4rem' },
height: { xs: '3rem', sm: '3.25rem', md: '4rem' },
'& .MuiOutlinedInput-root': {
borderRadius: '0.5rem',
height: '100%', // تأكيد تطابق الطول
'& fieldset': {
borderColor: '#ccc',
},
'&:hover fieldset': {
borderColor: theme.palette.primary.main,
},
'&.Mui-focused fieldset': {
borderColor: theme.palette.primary.main,
},
},
'& .MuiInputBase-input': {
color: theme.palette.primary.main,
textAlign: 'center',
fontSize: '20px',
padding: 0,
height: '100%',
},
}}
/>
))}
</Stack>
</Box>
<Button
variant="contained"
fullWidth
onClick={handleSend}
sx={{
color:'white',
backgroundColor: theme.palette.primary.main,
borderRadius: '30px',
textTransform: 'none',
fontWeight: 600,
fontSize: '16px',
width: '95%',
height: '48px',
'&:hover': {
backgroundColor: theme.palette.primary.hover ,
transition: 'all 0.4s ease'
}
}}
>
Send
</Button>
<Typography
textAlign="center"
fontWeight={500}
sx={{
fontSize: '16px',
display: 'block',
width: '100%',
mx: 'auto',
color: '#969BA7'
}}
>
By log in, I agree to the&nbsp;
<a href="#" style={{ color: '#007bff', textDecoration: 'none' }}>Terms of Service</a> and&nbsp;
<a href="#" style={{ color: '#007bff', textDecoration: 'none' }}>Privacy Policy</a>
</Typography>
</>
);
};
export default OtpVerification;

عرض الملف

@@ -0,0 +1,187 @@
import React from 'react';
import { Box, Typography, Stack, Button ,useTheme } from '@mui/material';
import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos';
import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos';
const steps = [
{
title: 'Forget Password',
description: 'Provide an email to change your password',
icon: '/images/icons/key.png',
},
{
title: 'Verify your email',
description: 'Enter your otp verification',
icon: '/images/icons/email.png',
},
{
title: 'Create a new password',
description: 'Create your a new password',
icon: '/images/icons/pen.png',
},
{
title: 'Welcome to KitchPlus app',
description: 'Get up and running in 3 minutes',
icon: '/images/icons/rocket.png',
},
];
const Side = ({ currentStepIndex, onNext, onBack }) => {
const theme = useTheme();
return (
<Box
sx={{
height: { xs: '100vh', sm: '130vh', md: '87.5vh' },
backgroundColor: '#FAFAFA',
px: { xs: 2, sm: 4 },
py: 5,
display: { xs: 'none', sm: 'block' },
position: 'relative',
}}
>
<Typography variant="h6" fontWeight={700} mb={2}>
Step for change your password
</Typography>
<Typography variant="body2" color="text.secondary" mb={4}>
Instructions for secure password modification. Follow simple steps for password change.
</Typography>
<Stack spacing={6} position="relative" sx={{ ml: 3 }}>
{steps.map((step, index) => (
<Box key={index} display="flex" alignItems="flex-start" gap={2} position="relative">
{index !== steps.length - 1 && (
<Box
sx={{
position: 'absolute',
left: '3.8vh',
top: '6vh',
width: '2px',
height: 'calc(100% + 24px)',
backgroundColor: '#e0e0e0',
zIndex: 0,
}}
/>
)}
<Box
sx={{
position: 'relative',
width: 50,
height: 53,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Box
sx={{
position: 'absolute',
width: 60,
height: 63,
borderRadius: '50%',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
zIndex: 0,
backgroundImage:
index === currentStepIndex
? 'linear-gradient(0deg, #FF914D, #F3F3F3 )'
: 'none',
backgroundColor: index === currentStepIndex ? 'transparent' : '#F3F3F3',
}}
/>
<Box
sx={{
width: 50,
height: 53,
backgroundColor: '#FFFFFF',
borderRadius: '50%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
zIndex: 1,
}}
>
<img
src={step.icon}
alt={step.title}
style={{ width: 24, height: 24, objectFit: 'contain' }}
/>
</Box>
</Box>
<Box>
<Typography variant="subtitle1" sx={{ fontSize: '16px', fontWeight: 600 }}>
{step.title}
</Typography>
<Typography variant="body2" sx={{ color: '#A0A0A0', fontSize: '12px', fontWeight: 500 }}>
{step.description}
</Typography>
</Box>
</Box>
))}
</Stack>
{/* ... (بقية محتوى الـ Side كما هو بدون تغيير) ... */}
{/* أزرار التنقل */}
<Box
sx={{
position: 'absolute',
bottom: 2,
left: '50%',
transform: 'translateX(-50%)',
width: '90%',
maxWidth: 600,
display: 'flex',
justifyContent: 'space-between',
px: 2,
}}
>
{/* Back */}
<Button
variant="text"
startIcon={<ArrowBackIosIcon sx={{ fontSize: '16px' }} />}
onClick={onBack}
disabled={currentStepIndex === 0}
sx={{
color: currentStepIndex === 0 ? '#C2C2C2' : '#6B7283',
minWidth: '100px',
fontWeight: 400,
fontSize: '16px',
textTransform: 'none',
'&:hover': {
backgroundColor: 'transparent',
color: theme.palette.primary.main
}
}}
>
Back
</Button>
{/* Next */}
<Button
variant="text"
endIcon={<ArrowForwardIosIcon sx={{ fontSize: '16px' }} />}
onClick={onNext}
disabled={currentStepIndex === steps.length - 1}
sx={{
color: currentStepIndex === steps.length - 1 ? '#C2C2C2' : '#6B7283',
minWidth: '100px',
fontWeight: 400,
fontSize: '16px',
textTransform: 'none',
'&:hover': {
backgroundColor: 'transparent',
color: theme.palette.primary.main,
transition: 'all 0.4s ease'
}
}}
>
Next
</Button>
</Box>
</Box>
);
};
export default Side;

عرض الملف

@@ -0,0 +1,349 @@
import React, { useState } from 'react';
import { TextField, Button, Typography, Stack, Box, IconButton, InputAdornment } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
import { VisibilityOutlined } from '@mui/icons-material';
import SidePanel from './SidePanel'; // استدعاء SidePanel من نفس المجلد أو حسب المسار المناسب
import { useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
const LoginForm = () => {
const navigate = useNavigate();
const theme = useTheme();
const [showPassword, setShowPassword] = useState(false);
const handleTogglePassword = () => {
setShowPassword((prev) => !prev);
};
const handleLogin = () => {
// بعد تنفيذ عملية تسجيل الدخول بنجاح، يتم التوجيه
navigate('/dashboard');
};
return (
<Box
bgcolor={"background.default"}
color={"text.primary"}
display="flex"
sx={{
width: '100vw',
height: '100vh',
overflow: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
}}
>
{/* SidePanel ثابت */}
<SidePanel />
{/* Login Content */}
<Box
sx={{
marginLeft: { xs: 0, sm: '50%' },
width: { xs: '100%', sm: '50%' ,md:'70%'},
}}
>
<Box
flex={1}
paddingTop={4}
paddingBottom={4}
paddingLeft={2}
paddingRight={2}
sx={{
backgroundColor: '#FFFFFF',
minHeight: '10vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
position: 'sticky',
}}
>
<Box
sx={{
width: {
xs: '120%',
sm: '100%',
md: '150%',
lg: '150%'
},
maxWidth: '600px'
}}
>
<Stack spacing={2}>
{/* Logo */}
<Box>
<img
src="/image.png"
alt="logo"
style={{
width: '4vw',
maxWidth: '80px',
height: 'auto',
objectFit: 'contain'
}}
/>
</Box>
<Typography
variant="h4"
fontWeight={700}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
Login
</Typography>
<Typography
variant="body2"
color="text.secondary"
fontWeight={500}
sx={{ pb: 1 }}
>
Enter your username and password to access your account securely. Welcome back to our service!
</Typography>
{/* Email Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="body2" color="black" sx={{ fontWeight: '500', fontSize: '16px' }}>
Email
</Typography>
<TextField
placeholder="Enter your email"
type="email"
variant="outlined"
fullWidth
sx={{
'& input': { fontWeight: 500, fontSize: '15px' },
'& input::placeholder': { color: '#969BA7' },
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
}
}}
/>
</Box>
{/* Password Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="body2" color="black" sx={{ fontWeight: '500', fontSize: '16px' }}>
Password
</Typography>
<TextField
type={showPassword ? 'text' : 'password'}
placeholder="Enter your password"
fullWidth
variant="outlined"
autoComplete="new-password"
sx={{
'& input': { fontWeight: 500, fontSize: '15px' },
'& input::placeholder': { color: '#969BA7' },
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleTogglePassword} edge="end">
{showPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Box>
{/* Login Button */}
<Box sx={{ pt: 2 }}>
<Button
variant="contained"
fullWidth
onClick={handleLogin}
sx={{
fontWeight: 600,
fontSize: { xs: '14px', sm: '16px' },
height: { xs: '45px', sm: '52px' },
borderRadius: '50px',
textTransform: 'none',
color: 'white',
backgroundColor: theme.palette.primary.main,
'&:hover': {
backgroundColor: theme.palette.primary.hover
}
}}
>
Log in
</Button>
</Box>
{/* Divider */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, py: 2 }}>
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#E0E0E0' }} />
<Typography variant="body1" sx={{ fontWeight: 500, fontSize: '16px', color: 'black' }}>
Or
</Typography>
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#E0E0E0' }} />
</Box>
{/* Google Button */}
<Button
variant="outlined"
fullWidth
sx={{
fontWeight: 500,
fontSize: '16px',
borderRadius: '50px',
height: '50px',
textTransform: 'none',
gap: 1,
borderColor: '#E6E6E6',
color: 'black',
'&:hover': {
borderColor: 'black',
backgroundColor: 'transparent'
}
}}
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<img
src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg"
alt="Google"
style={{ width: 25, height: 25 }}
/>
</Box>
Login with Google
</Button>
{/* Facebook Button */}
<Button
variant="outlined"
fullWidth
sx={{
fontWeight: 500,
fontSize: '16px',
borderRadius: '50px',
height: '50px',
textTransform: 'none',
gap: 1,
borderColor: '#E6E6E6',
color: 'black',
'&:hover': {
borderColor: 'black',
backgroundColor: 'transparent'
}
}}
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<img
src="https://upload.wikimedia.org/wikipedia/commons/0/05/Facebook_Logo_%282019%29.png"
alt="Facebook"
style={{ width: 25, height: 25 }}
/>
</Box>
Login with Facebook
</Button>
{/* Register Link */}
<Typography
variant="body2"
sx={{
fontSize: '16px',
textAlign: 'center',
color: '#969BA7',
pt: 3
}}
>
Dont have an account?{' '}
<Link
to="/register"
style={{
color: '#2261FF',
textDecoration: 'none'
}}
>
Register
</Link>
</Typography>
{/* ForgetPassword Link */}
<Typography
variant="body2"
sx={{
fontSize: '14px',
textAlign: 'center',
color: '#969BA7',
pt: 3
}}
>
Did you forget the password?{' '}
<Link
to="/forget"
style={{
color: '#2261FF',
textDecoration: 'none'
}}
>
Forget Password
</Link>
</Typography>
{/* Terms */}
<Typography
variant="caption"
sx={{
fontSize: '14px',
textAlign: 'center',
color: '#969BA7',
pt: 5
}}
>
By logging in, I agree to the{' '}
<a href="#" style={{ color: '#2261FF', textDecoration: 'none' }}>
Terms of Service
</a>{' '}
and{' '}
<a href="#" style={{ color: '#2261FF', textDecoration: 'none' }}>
Privacy Policy
</a>.
</Typography>
</Stack>
</Box>
</Box>
</Box>
</Box>
);
};
export default LoginForm;

عرض الملف

@@ -0,0 +1,409 @@
import React, { useState } from 'react';
import { TextField, Button, Typography, Stack, Box, IconButton, InputAdornment } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import VisibilityOffOutlinedIcon from '@mui/icons-material/VisibilityOffOutlined';
import { VisibilityOutlined } from '@mui/icons-material';
import SidePanel from './SidePanel';
import { Link } from 'react-router-dom';
const Register = () => {
const theme = useTheme();
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const handleTogglePassword = () => {
setShowPassword((prev) => !prev);
};
const handleToggleConfirmPassword = () => {
setShowConfirmPassword((prev) => !prev);
};
return (
<Box bgcolor={"background.default"} color={"text.primary"} display="flex" sx={{
width: '100vw',
height: '100vh',
overflow: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
}}>
{/* SidePanel ثابت */}
<SidePanel />
{/* Login Content */}
<Box
sx={{
marginLeft: { xs: 0, sm: '50%' },
width: { xs: '100%', sm: '50%' },
}}
>
<Box
flex={1}
paddingTop={4}
paddingBottom={4}
paddingLeft={2}
paddingRight={2}
sx={{
backgroundColor: '#FFFFFF',
minHeight: '10vh',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
position: 'sticky',
}}
>
<Box
sx={{
width: {
xs: '120%',
sm: '100%',
md: '120%',
lg: '120%'
},
maxWidth: '600px'
}}
>
<Stack spacing={2}>
{/* Logo */}
<Box>
<img
src="/image.png"
alt="logo"
style={{
width: '4vw',
maxWidth: '80px',
height: 'auto',
objectFit: 'contain'
}}
/>
</Box>
<Typography
variant="h4"
fontWeight={700}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
Register
</Typography>
<Typography
variant="body2"
color="text.secondary"
fontWeight={500}
sx={{ pb: 1 }}
>
Please fill out the registration form with accurate information to
create your account successfully.
</Typography>
{/* Email Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
color="black"
sx={{
fontWeight: '500',
fontSize: '16px'
}}
>
Email
</Typography>
<TextField
placeholder="Enter your email"
type="email"
variant="outlined"
fullWidth
sx={{
'& input': {
fontWeight: 500,
fontSize: '15px'
},
'& input::placeholder': {
color: '#969BA7'
},
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
}
}}
/>
</Box>
{/* Password Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
color="black"
sx={{
fontWeight: '500',
fontSize: '16px'
}}
>
Password
</Typography>
<TextField
type={showPassword ? 'text' : 'password'}
placeholder="Enter your password"
fullWidth
variant="outlined"
autoComplete="new-password"
sx={{
'& input': {
fontWeight: 500,
fontSize: '15px'
},
'& input::placeholder': {
color: '#969BA7'
},
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleTogglePassword} edge="end">
{showPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Box>
{/* Confirm Password Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
color="black"
sx={{
fontWeight: '500',
fontSize: '16px'
}}
>
Confirm Password
</Typography>
<TextField
type={showConfirmPassword ? 'text' : 'password'}
placeholder="Confirm your password"
fullWidth
variant="outlined"
autoComplete="new-password"
sx={{
'& input': {
fontWeight: 500,
fontSize: '15px'
},
'& input::placeholder': {
color: '#969BA7'
},
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
borderColor: '#FF914D',
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
borderColor: '#3f51b5',
boxShadow: '0 0 0 2px rgba(63,81,181,0.1)'
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleToggleConfirmPassword} edge="end">
{showConfirmPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Box>
{/* Login Button */}
<Box sx={{ pt: 2 }}>
<Button
variant="contained"
fullWidth
sx={{
fontWeight: 600,
fontSize: {
xs: '14px',
sm: '16px'
},
height: {
xs: '45px',
sm: '52px'
},
borderRadius: '50px',
textTransform: 'none',
color: 'white',
backgroundColor: theme.palette.primary.main,
'&:hover': {
backgroundColor: theme.palette.primary.hover
}
}}
>
Continue
</Button>
</Box>
{/* Divider */}
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2, py: 2 }}>
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#E0E0E0' }} />
<Typography
variant="body1"
sx={{
fontWeight: 500,
fontSize: '16px',
color: 'black'
}}
>
Or
</Typography>
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#E0E0E0' }} />
</Box>
{/* Google Button */}
<Button
variant="outlined"
fullWidth
sx={{
fontWeight: 500,
fontSize: '16px',
borderRadius: '50px',
height: '50px',
textTransform: 'none',
gap: 1,
borderColor: '#E6E6E6',
color: 'black',
'&:hover': {
borderColor: 'black',
backgroundColor: 'transparent'
}
}}
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<img
src="https://upload.wikimedia.org/wikipedia/commons/c/c1/Google_%22G%22_logo.svg"
alt="Google"
style={{ width: 25, height: 25 }}
/>
</Box>
Login with Google
</Button>
{/* Facebook Button */}
<Button
variant="outlined"
fullWidth
sx={{
fontWeight: 500,
fontSize: '16px',
borderRadius: '50px',
height: '50px',
textTransform: 'none',
gap: 1,
borderColor: '#E6E6E6',
color: 'black',
'&:hover': {
borderColor: 'black',
backgroundColor: 'transparent'
}
}}
>
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<img
src="https://upload.wikimedia.org/wikipedia/commons/0/05/Facebook_Logo_%282019%29.png"
alt="Facebook"
style={{ width: 25, height: 25 }}
/>
</Box>
Login with Facebook
</Button>
{/* login Link */}
<Typography
variant="body2"
sx={{
fontSize: '16px',
textAlign: 'center',
color: '#969BA7',
pt: 3
}}
>
Already have an account?{' '}
<Link
to="/login"
style={{
color: '#2261FF',
textDecoration: 'none'
}}
>
Login
</Link>
</Typography>
{/* Terms */}
<Typography
variant="caption"
sx={{
fontSize: '14px',
textAlign: 'center',
color: '#969BA7',
pt: 5
}}
>
By log in, I agree to the and {' '}
<a href="#" style={{ color: '#2261FF', textDecoration: 'none' }}>
Terms of Service
</a>{' '}
and{' '}
<a href="#" style={{ color: '#2261FF', textDecoration: 'none' }}>
Privacy Policy
</a>.
</Typography>
</Stack>
</Box>
</Box>
</Box>
</Box>
);
};
export default Register;

عرض الملف

@@ -0,0 +1,194 @@
import React, { useState, useEffect } from 'react';
import {
Button,
Typography,
Stack,
Box
} from '@mui/material';
import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; // استيراد أيقونة السهم
const SidePanel = ({ setMode, mode }) => {
const [currentSlide, setCurrentSlide] = useState(0);
const slides = [
{
image: '/images/waitress3.png',
title: "Welcome to our cutting-edge postal application,",
description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient."
},
{
image: '/images/waitress3.png',
title: "Second Slide Title",
description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient."
},
{
image: '/images/waitress3.png',
title: "Third Slide Title",
description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient."
},
{
image: '/images/waitress3.png',
title: "Fourth Slide Title",
description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient."
}
];
useEffect(() => {
const interval = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % slides.length);
}, 5000);
return () => clearInterval(interval);
}, [slides.length]);
return (
<Box
sx={{
display: { xs: 'none', sm: 'block' },
width: { sm: '50%' },
position: 'fixed',
height: '100vh',
top: 0,
left: 0,
zIndex: 10,
}}
>
<Box
flex={1}
padding={2}
sx={{
display: { xs: "none", sm: "block" },
position: 'sticky',
height: 'calc(102vh - 40px)', // لضمان ملاءمته للشاشة
}}
>
<Stack spacing={2} sx={{ width: '100%', height: '100%' }}>
<Box
sx={{
width: '100%',
height: '100vh',
position: 'relative',
overflow: 'hidden',
borderRadius: '20px',
}}
>
{/* الصورة الحالية */}
<img
src={slides[currentSlide].image}
alt={`Slide ${currentSlide + 1}`}
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
display: 'block'
}}
/>
{/* مربع النص في الأسفل */}
<Box
sx={{
position: 'absolute',
bottom: 0,
left: 0,
width: '100%',
height: {
md: '37vh', // الافتراضي للشاشات الصغيرة
// xs: '5vh',
sm: '42vh',// عندما تكون الشاشة متوسطة أو أكبر
lg: '31vh', // من 1200px إلى أقل من 1536px
},
bgcolor: 'rgba(0, 0, 0, 0.2)',
color: 'white',
borderBottomLeftRadius: '20px',
borderBottomRightRadius: '20px',
p: 3,
boxSizing: 'border-box',
boxShadow: '0px -40px 20px rgba(0, 0, 0, 0.2)',
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'flex-start',
}}
>
<Button
variant="contained"
size="small"
onClick={() => window.open('https://www.google.com', '_blank')}
sx={{
mb: 1,
bgcolor: 'rgba(255, 255, 255, 0.24)',
color: 'white',
textTransform: 'none',
borderRadius: '12px', // زاوية منحنية
display: 'flex', // لتوزيع الأيقونة والنص بشكل أفقي
alignItems: 'center', // لضبط الأيقونة والنص في المنتصف
padding: '6px 20px', // يمكن تعديل المسافة حول النص والأيقونة
borderRadius: '50px',
fontSize: '16px',
fontWeight: 500,
marginBottom: '20px'
}}
>
KITCHPLUS
{/* إضافة أيقونة السهم مع تعديل زاوية الدوران */}
<ArrowForwardIcon sx={{ ml: 1, transform: 'rotate(-45deg)' }} /> {/* تعديل زاوية السهم */}
</Button>
<Typography
sx={{
wordBreak: 'break-word',
fontSize: '120%',
fontWeight: 400,
}}
>
{slides[currentSlide].description}
</Typography>
</Box>
{/* مؤشرات الشرائح */}
<Box
sx={{
position: 'absolute',
bottom: '1vh', // جعل المؤشرات تحت النص
left: '50%',
transform: 'translateX(-50%)',
display: 'flex',
gap: 1,
width: '100%',
justifyContent: 'center', // تأكد من أن المؤشرات تأخذ عرض الصورة بالكامل
}}
>
{slides.map((_, index) => (
<Box
key={index}
sx={{
width: '20%',
height: 5,
bgcolor: index === currentSlide ? 'white' : 'rgba(255, 255, 255, 0.5)',
borderRadius: 2,
cursor: 'pointer',
transition: 'background-color 0.3s',
}}
onClick={() => setCurrentSlide(index)}
/>
))}
</Box>
</Box>
</Stack>
<Box position="fixed">
</Box>
</Box>
</Box>
)
}
export default SidePanel;

عرض الملف

@@ -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;

لم تُعرض بعض الملفات لأن الكثير من الملفات تغيرت في هذا الاختلاف إظهار المزيد