1
0

Linking of login, logout and registration interfaces.

هذا الالتزام موجود في:
raghad
2025-06-24 21:33:32 +03:00
الأصل 4a72e96c76
التزام 9f05ca5f9c
19 ملفات معدلة مع 452 إضافات و170 حذوفات

عرض الملف

@@ -3,27 +3,47 @@ import { TextField, Button, Typography, Stack, Box, IconButton, InputAdornment }
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';
import SidePanel from './SidePanel';
import { useNavigate, Link } from 'react-router-dom';
import authService from '../../../services/authService';
const LoginForm = () => {
const navigate = useNavigate();
const theme = useTheme();
const [showPassword, setShowPassword] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const handleTogglePassword = () => {
setShowPassword((prev) => !prev);
setShowPassword(prev => !prev);
};
const handleLogin = () => {
// بعد تنفيذ عملية تسجيل الدخول بنجاح، يتم التوجيه
navigate('/dashboard');
const handleLogin = async () => {
setLoading(true);
setError('');
const result = await authService.login(email, password);
if (!result.success) {
setError(result.message || 'Login failed');
setLoading(false);
return;
}
localStorage.setItem('token', result.data.token);
localStorage.setItem('refresh_token', result.data.refresh_token);
setLoading(false);
// الانتقال للداشبورد مع منع الرجوع
navigate('/dashboard', { replace: true });
};
return (
<Box
bgcolor={"background.default"}
color={"text.primary"}
@@ -38,14 +58,11 @@ const LoginForm = () => {
},
}}
>
{/* SidePanel ثابت */}
<SidePanel />
{/* Login Content */}
<Box
sx={{
marginLeft: { xs: 0, sm: '50%' },
width: { xs: '100%', sm: '50%' ,md:'70%'},
marginLeft: { xs: 0, sm: '50%' },
width: { xs: '100%', sm: '50%', md: '70%' },
}}
>
<Box
@@ -76,7 +93,7 @@ const LoginForm = () => {
>
<Stack spacing={2}>
{/* Logo */}
{/* الشعار */}
<Box>
<img
src="/image.png"
@@ -90,30 +107,16 @@ const LoginForm = () => {
/>
</Box>
<Typography
variant="h4"
fontWeight={700}
sx={{
fontSize: {
xs: '1.8rem',
sm: '2rem',
md: '2.2rem'
}
}}
>
{/* عنوان تسجيل الدخول */}
<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 }}
>
<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
@@ -123,15 +126,17 @@ const LoginForm = () => {
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': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
'&.Mui-focused fieldset': {
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)'
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
@@ -142,7 +147,7 @@ const LoginForm = () => {
/>
</Box>
{/* Password Input */}
{/* إدخال كلمة السر */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="body2" color="black" sx={{ fontWeight: '500', fontSize: '16px' }}>
Password
@@ -153,15 +158,17 @@ const LoginForm = () => {
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': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
'&.Mui-focused fieldset': {
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)'
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
@@ -184,14 +191,22 @@ const LoginForm = () => {
/>
</Box>
{/* Login Button */}
{/* عرض الخطأ */}
{error && (
<Typography color="error" textAlign="center">
{error}
</Typography>
)}
{/* زر تسجيل الدخول */}
<Box sx={{ pt: 2 }}>
<Button
variant="contained"
fullWidth
onClick={handleLogin}
disabled={loading}
sx={{
fontFamily: 'PlusJakartaSans' ,
fontFamily: 'PlusJakartaSans',
fontWeight: 600,
fontSize: { xs: '14px', sm: '16px' },
height: { xs: '45px', sm: '52px' },
@@ -204,7 +219,7 @@ const LoginForm = () => {
}
}}
>
Log in
{loading ? 'Loading...' : 'Log in'}
</Button>
</Box>

عرض الملف

@@ -4,12 +4,22 @@ 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';
import { Link, useNavigate } from 'react-router-dom';
import authService from '../../../services/authService';
const Register = () => {
const theme = useTheme();
const navigate = useNavigate();
const [showPassword, setShowPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
const [successMessage, setSuccessMessage] = useState('');
const handleTogglePassword = () => {
setShowPassword((prev) => !prev);
};
@@ -18,6 +28,36 @@ const Register = () => {
setShowConfirmPassword((prev) => !prev);
};
const handleRegister = async () => {
setLoading(true);
setError('');
setSuccessMessage('');
const result = await authService.register(email, password, confirmPassword);
if (!result.success) {
if (result.errors) {
const firstError = Object.values(result.errors)[0][0];
setError(firstError);
} else if (result.message && result.message.includes('Duplicate entry')) {
setError('The email has already been taken.');
} else {
setError(result.message || 'Registration failed');
}
setLoading(false);
return;
}
// تسجيل ناجح
localStorage.setItem('token', result.data.token);
localStorage.setItem('refresh_token', result.data.refresh_token);
setTimeout(() => {
navigate('/dashboard', { replace: true }); // استبدال الرابط وعدم السماح بالعودة
setLoading(false);
}, 500);
};
return (
<Box bgcolor={"background.default"} color={"text.primary"} display="flex" sx={{
width: '100vw',
@@ -28,17 +68,12 @@ const Register = () => {
display: 'none',
},
}}>
{/* SidePanel ثابت */}
<SidePanel />
{/* Login Content */}
<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}
@@ -66,8 +101,6 @@ const Register = () => {
}}
>
<Stack spacing={2}>
{/* Logo */}
<Box>
<img
src="/image.png"
@@ -105,7 +138,6 @@ const Register = () => {
create your account successfully.
</Typography>
{/* Email Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
@@ -122,6 +154,8 @@ const Register = () => {
type="email"
variant="outlined"
fullWidth
value={email}
onChange={(e) => setEmail(e.target.value)}
sx={{
'& input': {
fontWeight: 500,
@@ -133,9 +167,9 @@ const Register = () => {
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
'&.Mui-focused fieldset': {
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)'
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
@@ -146,7 +180,6 @@ const Register = () => {
/>
</Box>
{/* Password Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
@@ -164,6 +197,8 @@ const Register = () => {
fullWidth
variant="outlined"
autoComplete="new-password"
value={password}
onChange={(e) => setPassword(e.target.value)}
sx={{
'& input': {
fontWeight: 500,
@@ -175,9 +210,9 @@ const Register = () => {
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
'&.Mui-focused fieldset': {
borderColor: theme.palette.primary.main,
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)'
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
@@ -200,7 +235,6 @@ const Register = () => {
/>
</Box>
{/* Confirm Password Input */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography
variant="body2"
@@ -218,6 +252,8 @@ const Register = () => {
fullWidth
variant="outlined"
autoComplete="new-password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
sx={{
'& input': {
fontWeight: 500,
@@ -229,9 +265,9 @@ const Register = () => {
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
transition: '0.3s',
'&.Mui-focused fieldset': { // أضف هذا الجزء لتغيير لون الحدود عند التركيز
'&.Mui-focused fieldset': {
borderColor: '#FF914D',
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)' // ظل برتقالي خفيف
boxShadow: '0 0 0 2px rgba(255, 145, 77, 0.2)'
}
},
'& .MuiOutlinedInput-root.Mui-focused': {
@@ -254,21 +290,28 @@ const Register = () => {
/>
</Box>
{/* Login Button */}
{/* 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'
},
fontSize: { xs: '14px', sm: '16px' },
height: { xs: '45px', sm: '52px' },
borderRadius: '50px',
textTransform: 'none',
color: 'white',
@@ -278,7 +321,7 @@ const Register = () => {
}
}}
>
Continue
{loading ? 'Loading...' : 'Continue'}
</Button>
</Box>
@@ -298,7 +341,7 @@ const Register = () => {
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#E0E0E0' }} />
</Box>
{/* Google Button */}
{/* Google */}
<Button
variant="outlined"
fullWidth
@@ -327,7 +370,7 @@ const Register = () => {
Login with Google
</Button>
{/* Facebook Button */}
{/* Facebook */}
<Button
variant="outlined"
fullWidth
@@ -356,8 +399,6 @@ const Register = () => {
Login with Facebook
</Button>
{/* login Link */}
<Typography
variant="body2"
sx={{
@@ -379,7 +420,6 @@ const Register = () => {
</Link>
</Typography>
{/* Terms */}
<Typography
variant="caption"
sx={{
@@ -389,7 +429,7 @@ const Register = () => {
pt: 5
}}
>
By log in, I agree to the and {' '}
By log in, I agree to the and{' '}
<a href="#" style={{ color: '#2261FF', textDecoration: 'none' }}>
Terms of Service
</a>{' '}
@@ -406,4 +446,4 @@ const Register = () => {
);
};
export default Register;
export default Register;

عرض الملف

@@ -15,12 +15,12 @@ const SidePanel = ({ setMode, mode }) => {
const slides = [
{
image: '/images/waitress3.png',
image: '/images/waitress1.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',
image: '/images/waitress2.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."
},
@@ -30,7 +30,7 @@ const SidePanel = ({ setMode, mode }) => {
description: "Welcome to our cutting-edge postal application, where sending and receiving mail has never been more convenient and efficient."
},
{
image: '/images/waitress3.png',
image: '/images/waitress4.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."
}