initial commit

This commit is contained in:
RaghadAlkhous
2026-05-06 15:08:57 +03:00
commit 1ccca905f3
215 changed files with 61375 additions and 0 deletions
@@ -0,0 +1,403 @@
import React, { useState, useEffect } from 'react';
import {
Box,
Typography,
TextField,
Button,
Select,
MenuItem,
Checkbox,
ListItemText,
OutlinedInput,
styled,
useTheme,
LinearProgress
} from '@mui/material';
import AddAPhotoOutlinedIcon from '@mui/icons-material/AddAPhotoOutlined';
import authService from '../../../services/authService';
import { useRestaurant } from '../../../contexts/RestaurantContext';
import AddIcon from "@mui/icons-material/Add";
const AccountProfile = () => {
const theme = useTheme();
const { restaurantId } = useRestaurant();
const [editMode, setEditMode] = useState(false);
const [profileImage, setProfileImage] = useState(null);
const [form, setForm] = useState({
restaurant_name: '',
restaurant_type: '',
Address: '',
City: '',
Postal_code: '',
Phone: '',
Email: '',
Operation_hour: '',
host_type: '',
collaboration_type: '',
closed_days: [],
equipment: [], // array of {name, quantity}
Maximum_orders_per_day: 0,
Number_of_Cheff: 0,
Number_of_Waiters: 0,
Number_of_Cookers: 0,
});
const daysOfWeek = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
const Input = styled('input')({ display: 'none' });
useEffect(() => {
const fetchProfile = async () => {
if (!restaurantId) return;
const data = await authService.getRestaurantProfile(restaurantId);
console.log("PROFILE DATA ===>", data); // 👈 يوضح الأسماء الحقيقية
if (data) {
setForm({
restaurant_name: data.restaurant_name,
restaurant_type: data.restaurant_type,
Address: data.Address,
City: data.City,
Postal_code: data.Postal_code,
Phone: data.Phone,
Email: data.Email,
Operation_hour: data.Operation_hour,
host_type: data.host_type,
collaboration_type: data.collaboration_type,
closed_days: data.closed_days || [],
equipment: Object.entries(data.equipment || {}).map(([name, quantity]) => ({ name, quantity })),
Maximum_orders_per_day: data.Maximum_orders_per_day ?? data.maximum_orders_per_day ?? 0,
Number_of_Cheff: data.Number_of_Cheff ?? data.number_of_cheff ?? 0,
Number_of_Waiters: data.Number_of_Waiters ?? data.number_of_waiters ?? 0,
Number_of_Cookers: data.Number_of_Cookers ?? data.number_of_cookers ?? 0,
});
}
};
fetchProfile();
}, [restaurantId]);
const handleImageUpload = (event) => {
if (event.target.files && event.target.files[0]) {
setProfileImage(event.target.files[0]);
}
};
const handleChange = (field, value) => setForm(prev => ({ ...prev, [field]: value }));
const handleEquipmentChange = (index, key, value) => {
const newEquipment = [...form.equipment];
newEquipment[index][key] = value;
setForm(prev => ({ ...prev, equipment: newEquipment }));
};
const addEquipment = () => {
setForm(prev => ({
...prev,
equipment: [...prev.equipment, { name: '', quantity: 0 }]
}));
};
const removeEquipment = (index) => {
const newEquipment = [...form.equipment];
newEquipment.splice(index, 1);
setForm(prev => ({ ...prev, equipment: newEquipment }));
};
const renderField = (label, value, fieldKey, options = null) => (
<Box
sx={{
flex: 1,
display: 'flex',
flexDirection: 'column',
gap: 1,
pb: 1, // padding bottom
borderBottom: '1px solid #ccc' // الخط الرمادي تحت كل حقل
}}
>
<Typography
variant="body2"
sx={{
fontWeight: 600,
fontSize: '18px',
color: 'black'
}}
>
{label}
</Typography>
{editMode ? (
options ? (
<Select
multiple
value={form[fieldKey]}
onChange={(e) => handleChange(fieldKey, e.target.value)}
input={<OutlinedInput label={label} />}
renderValue={(selected) => selected.join(', ')}
>
{options.map(day => (
<MenuItem key={day} value={day}>
<Checkbox checked={form[fieldKey].includes(day)} />
<ListItemText primary={day.charAt(0).toUpperCase() + day.slice(1)} />
</MenuItem>
))}
</Select>
) : (
<TextField
value={value}
onChange={(e) => handleChange(fieldKey, e.target.value)}
fullWidth
variant="outlined"
sx={{
'& input': { fontWeight: 500, fontSize: '16px', color: 'black' },
'& 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)',
},
},
}}
/>
)
) : (
<Typography
variant="body1"
sx={{
fontWeight: 500,
fontSize: '16px',
color: 'gray'
}}
>
{Array.isArray(value) ? value.join(', ') : value}
</Typography>
)}
</Box>
);
const handleSave = async () => {
if (!restaurantId) return;
const equipmentObj = {};
form.equipment.forEach(eq => {
if (eq.name) equipmentObj[eq.name] = eq.quantity;
});
const payload = {
...form,
equipment: equipmentObj
};
if (profileImage) payload.logo = profileImage;
const result = await authService.updateRestaurantProfile(restaurantId, payload);
if (result.success) {
alert("Profile updated successfully!");
setEditMode(false);
const updated = await authService.getRestaurantProfile(restaurantId);
if (updated) setForm({
...updated,
equipment: Object.entries(updated.equipment || {}).map(([name, quantity]) => ({ name, quantity })),
});
} else {
alert(`Update failed: ${result.message}`);
}
};
// داخل AccountProfile
const collaborationOptions = [
{ value: 'fine_dining', label: 'Fine Dining' },
{ value: 'catering_services', label: 'Catering Services' },
{ value: 'fast_food', label: 'Fast Food' },
{ value: 'cloud_kitchen', label: 'Cloud Kitchen' }
];
return (
<Box sx={{ p: { xs: 2, sm: 3 }, backgroundColor: '#FFFFFF', borderRadius: 2, maxWidth: '100%' }}>
<Typography variant="h4" sx={{ mb: 3, fontWeight: 'bold' }}>Restaurant Profile</Typography>
{/* صورة البروفايل */}
{/* <Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}>
<label htmlFor="icon-button-file">
<Input accept="image/*" id="icon-button-file" type="file" onChange={handleImageUpload} />
<Box
component="span"
sx={{
width: 110, height: 110, border: '2px dashed #4C535F', borderRadius: 2,
display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
color: '#4C535F', cursor: 'pointer', textAlign: 'center', backgroundColor: '#f6f6f6'
}}
>
<AddAPhotoOutlinedIcon sx={{ fontSize: 28, mb: 1 }} />
<Typography sx={{ fontSize: '13px', fontWeight: 500 }}>Upload your photo</Typography>
</Box>
</label>
</Box> */}
<LinearProgress
variant="determinate"
value={100}
sx={{
mt: 2,
mb: 3,
height: 4,
borderRadius: 2,
backgroundColor: "#f0f0f0",
"& .MuiLinearProgress-bar": { backgroundColor: theme.palette.primary.main },
}}
/>
{/* الحقول */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 ,p:3, display: 'flex', flexWrap: 'wrap', border: '1px solid #e0e0e0', borderRadius: 2, boxShadow: '0px 4px 8px rgba(0, 0, 0, 0.1)'}}>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Restaurant Name', form.restaurant_name, 'restaurant_name')}
{renderField('Restaurant Type', form.restaurant_type, 'restaurant_type')}
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Address', form.Address, 'Address')}
{renderField('City', form.City, 'City')}
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Postal Code', form.Postal_code, 'Postal_code')}
{renderField('Phone', form.Phone, 'Phone')}
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Email', form.Email, 'Email')}
{renderField('Operation Hours', form.Operation_hour, 'Operation_hour')}
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Host Type', form.host_type, 'host_type')}
<Box sx={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="body2" sx={{ fontWeight: '500', fontSize: '16px' }}>Collaboration Type</Typography>
{editMode ? (
<Select
value={form.collaboration_type || ''}
onChange={(e) => handleChange('collaboration_type', e.target.value)}
displayEmpty
fullWidth
sx={{
'& .MuiOutlinedInput-root': {
borderRadius: '10px',
}
}}
>
<MenuItem value="">
{/* <em>None</em> اختياري */}
</MenuItem>
{collaborationOptions.map(option => (
<MenuItem key={option.value} value={option.value}>
{option.label}
</MenuItem>
))}
</Select>
) : (
<Typography variant="body1" sx={{ fontWeight: 500, fontSize: '15px' }}>
{form.collaboration_type ? collaborationOptions.find(opt => opt.value === form.collaboration_type)?.label : 'None'}
</Typography>
)}
</Box>
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Closed Days', form.closed_days, 'closed_days', daysOfWeek)}
</Box>
{/* القدرة التشغيلية */}
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Maximum Orders per Day', form.Maximum_orders_per_day, 'Maximum_orders_per_day')}
{renderField('Number of Chefs', form.Number_of_Cheff, 'Number_of_Cheff')}
</Box>
<Box sx={{ display: 'flex', gap: 2 }}>
{renderField('Number of Waiters', form.Number_of_Waiters, 'Number_of_Waiters')}
{renderField('Number of Cookers', form.Number_of_Cookers, 'Number_of_Cookers')}
</Box>
{/* المعدات */}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>
<Typography variant="body2" sx={{ fontWeight: '500', fontSize: '16px' }}>Equipment Name</Typography>
{form.equipment.map((eq, index) => (
<Box key={index} sx={{ display: 'flex', gap: 2, alignItems: 'center' }}>
<TextField
value={eq.name}
onChange={(e) => handleEquipmentChange(index, 'name', e.target.value)}
fullWidth
variant="outlined"
disabled={!editMode}
sx={{ '& input': { fontWeight: 500, fontSize: '16px' } }}
/>
<TextField
label="Quantity"
type="number"
value={eq.quantity}
onChange={(e) => handleEquipmentChange(index, 'quantity', Number(e.target.value))}
fullWidth
variant="outlined"
disabled={!editMode}
sx={{ '& input': { fontWeight: 500, fontSize: '16px' } ,borderRadius:20}}
/>
{editMode && (
<Button color="error" onClick={() => removeEquipment(index)}>
Delete
</Button>
)}
</Box>
))}
{editMode && (
<Button variant="outlined" onClick={addEquipment} startIcon={<AddIcon/>} sx={{ mt: 1, width: 'fit-content' , textTransform:'none' }}>
Add Equipment
</Button>
)}
</Box>
</Box>
{/* أزرار التحكم */}
<Box sx={{ display: 'flex', justifyContent: 'flex-end', gap: 2, flexWrap: 'wrap', mt: 3 }}>
{editMode ? (
<>
<Button
variant="outlined"
onClick={() => setEditMode(false)}
sx={{ px: 4, py: 1.5, borderRadius: 2, textTransform: 'none', fontWeight: 'bold' }}
>
Cancel
</Button>
<Button
variant="contained"
onClick={handleSave}
sx={{
px: 4, py: 1.5, borderRadius: 2,
textTransform: 'none', fontWeight: 'bold',
color: '#FFF', backgroundColor: theme.palette.primary.main
}}
>
Save
</Button>
</>
) : (
<Button
variant="contained"
onClick={() => setEditMode(true)}
sx={{
px: 4, py: 1.5, borderRadius: 2,
textTransform: 'none', fontWeight: 'bold',
color: '#FFF', backgroundColor: theme.palette.primary.main
}}
>
Edit Profile
</Button>
)}
</Box>
</Box>
);
};
export default AccountProfile;