1
0

Initial commit - restaurant dashboard

هذا الالتزام موجود في:
RaghadMAlkous
2025-09-04 01:17:15 +03:00
الأصل 13891b47fd
التزام 7b2f8840cb
136 ملفات معدلة مع 16638 إضافات و6033 حذوفات

عرض الملف

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState ,useContext } 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';
@@ -6,6 +6,19 @@ import { VisibilityOutlined } from '@mui/icons-material';
import SidePanel from './SidePanel';
import { Link, useNavigate } from 'react-router-dom';
import authService from '../../../services/authService';
import { UserContext } from '../../../contexts/UserContext';
// import { useGoogleRegister } from '@react-oauth/google';
const generateStrongPassword = () => {
const length = 12;
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+";
let password = "";
for (let i = 0, n = charset.length; i < length; ++i) {
password += charset.charAt(Math.floor(Math.random() * n));
}
return password;
};
const Register = () => {
const theme = useTheme();
@@ -19,7 +32,11 @@ const Register = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [successMessage, setSuccessMessage] = useState('');
const [snackbarOpen, setSnackbarOpen] = useState(false);
const { setUser } = useContext(UserContext);
// تفعيل/تعطيل إظهار كلمة السر
const handleTogglePassword = () => {
setShowPassword((prev) => !prev);
};
@@ -28,7 +45,8 @@ const Register = () => {
setShowConfirmPassword((prev) => !prev);
};
const handleRegister = async () => {
const handleRegister = async () => {
setLoading(true);
setError('');
setSuccessMessage('');
@@ -52,28 +70,93 @@ const Register = () => {
localStorage.setItem('token', result.data.token);
localStorage.setItem('refresh_token', result.data.refresh_token);
// ✅ تحديث الـ User Context مباشرة بعد التسجيل
setUser({
email: email,
token: result.data.token,
refresh_token: result.data.refresh_token,
adminData: result.data.Admin || null,
});
setTimeout(() => {
navigate('/dashboard', { replace: true }); // استبدال الرابط وعدم السماح بالعودة
navigate('/restaurant', { replace: true });
setLoading(false);
}, 500);
};
const handleGoogleSuccess = async (tokenResponse) => {
try {
const res = await fetch('https://www.googleapis.com/oauth2/v3/userinfo', {
headers: {
Authorization: `Bearer ${tokenResponse.access_token}`,
},
});
const userInfo = await res.json();
console.log('Google User Info:', userInfo);
if (userInfo.email) {
const generatedPassword = generateStrongPassword(); // كلمة مرور مقترحة
setEmail(userInfo.email);
setPassword(generatedPassword);
setConfirmPassword(generatedPassword);
setError('');
setTimeout(() => {
setSuccessMessage('');
}, 5000);
} else {
setError('Google Register failed: No email found');
}
} catch (e) {
console.error('Google Register failed:', e);
setError('Google Register failed');
}
};
const handleGoogleError = () => {
setError('Google Register failed');
};
const handleSnackbarClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
setSnackbarOpen(false);
};
// // تهيئة تسجيل الدخول عبر جوجل باستخدام useGoogleRegister
// const RegisterWithGoogle = useGoogleRegister({
// onSuccess: handleGoogleSuccess,
// onError: handleGoogleError,
// });
return (
<Box bgcolor={"background.default"} color={"text.primary"} display="flex" sx={{
width: '100vw',
height: '100vh',
overflow: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
}}>
<Box
bgcolor={'background.default'}
color={'text.primary'}
display="flex"
sx={{
width: '100vw',
height: '100vh',
overflow: 'auto',
scrollbarWidth: 'none',
'&::-webkit-scrollbar': {
display: 'none',
},
}}
>
<SidePanel />
<Box sx={{
marginLeft: { xs: 0, sm: '50%' },
width: { xs: '100%', sm: '50%' },
}}>
<Box
sx={{
marginLeft: { xs: 0, sm: '50%' },
width: { xs: '100%', sm: '50%' },
}}
>
<Box
flex={1}
paddingTop={4}
@@ -95,12 +178,13 @@ const Register = () => {
xs: '120%',
sm: '100%',
md: '120%',
lg: '120%'
lg: '120%',
},
maxWidth: '600px'
maxWidth: '600px',
}}
>
<Stack spacing={2}>
{/* logo */}
<Box>
<img
src="/image.png"
@@ -109,7 +193,7 @@ const Register = () => {
width: '4vw',
maxWidth: '80px',
height: 'auto',
objectFit: 'contain'
objectFit: 'contain',
}}
/>
</Box>
@@ -121,323 +205,291 @@ const Register = () => {
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.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 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>
<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"
{/* حقل الايميل */}
<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
value={email}
onChange={(e) => setEmail(e.target.value)}
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>
{/* حقل كلمة المرور */}
<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"
value={password}
onChange={(e) => setPassword(e.target.value)}
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>
{/* حقل التاكيد لكلمة المرور */}
<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"
value={confirmPassword}
onChange={(e) => setConfirmPassword(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)',
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleToggleConfirmPassword} edge="end">
{showConfirmPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
),
}}
/>
</Box>
{/* Error & Success Message */}
{error && (
<Typography color="error" textAlign="center">
{error}
</Typography>
)}
{successMessage && (
<Typography color="green" textAlign="center">
{successMessage}
</Typography>
)}
{/* زر التسجيل */}
<Box sx={{ pt: 2 }}>
<Button
variant="contained"
fullWidth
onClick={handleRegister}
disabled={loading}
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,
},
}}
>
{loading ? 'Loading...' : '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>
{/* زر التسجيل عبر جوجل */}
{/* <Button
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
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>
<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"
value={password}
onChange={(e) => setPassword(e.target.value)}
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>
<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"
value={confirmPassword}
onChange={(e) => setConfirmPassword(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)'
},
'& input::-ms-reveal, & input::-ms-clear': {
display: 'none',
},
}}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={handleToggleConfirmPassword} edge="end">
{showConfirmPassword ? <VisibilityOffOutlinedIcon /> : <VisibilityOutlined />}
</IconButton>
</InputAdornment>
)
}}
/>
</Box>
{/* Error & Success Message */}
{error && (
<Typography color="error" textAlign="center">
{error}
</Typography>
)}
{successMessage && (
<Typography color="green" textAlign="center">
{successMessage}
</Typography>
)}
<Box sx={{ pt: 2 }}>
<Button
variant="contained"
fullWidth
onClick={handleRegister}
disabled={loading}
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
}
}}
>
{loading ? 'Loading...' : '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"
// onClick={() => RegisterWithGoogle()}
sx={{
fontWeight: 500,
fontSize: '16px',
color: 'black'
borderRadius: '50px',
height: '50px',
textTransform: 'none',
gap: 1,
borderColor: '#E6E6E6',
color: 'black',
'&:hover': {
borderColor: 'black',
backgroundColor: 'transparent',
},
}}
>
Or
<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>
Register with 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/0/05/Facebook_Logo_%282019%29.png"
alt="Facebook"
style={{ width: 25, height: 25 }}
/>
</Box>
Register with Facebook
</Button> */}
<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>
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#E0E0E0' }} />
</Box>
{/* Google */}
<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
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>
<Typography
variant="body2"
sx={{
fontSize: '16px',
textAlign: 'center',
color: '#969BA7',
pt: 3
}}
variant="caption"
sx={{
fontSize: '14px',
textAlign: 'center',
color: '#969BA7',
pt: 2
}}
>
Already have an account?{' '}
<Link
to="/login"
style={{
color: '#2261FF',
textDecoration: 'none'
}}
>
Login
</Link>
By logging in, I agree to the{' '}
<Box
component="span"
sx={{ color: '#2261FF', cursor: 'pointer', textDecoration: 'none' }}
onClick={() => window.open('/terms', 'TermsOfService')}
>
Terms of Service
</Box>{' '}
and{' '}
<Box
component="span"
sx={{ color: '#2261FF', cursor: 'pointer', textDecoration: 'none' }}
onClick={() => window.open('/privacy', 'PrivacyPolicy')}
>
Privacy Policy
</Box>.
</Typography>
<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>