first commit

This commit is contained in:
2026-06-05 17:28:05 +05:30
commit a162fa89e5
62 changed files with 8729 additions and 0 deletions

206
src/pages/Settings.jsx Normal file
View File

@@ -0,0 +1,206 @@
import { useState } from 'react';
import {
Grid,
Tabs,
Tab,
Box,
Stack,
TextField,
MenuItem,
Switch,
FormControlLabel,
Button,
Typography,
Divider,
Snackbar,
Alert
} from '@mui/material';
import SaveOutlinedIcon from '@mui/icons-material/SaveOutlined';
import TuneOutlinedIcon from '@mui/icons-material/TuneOutlined';
import NotificationsNoneIcon from '@mui/icons-material/NotificationsNone';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import PageHeader from '@/components/PageHeader';
import MainCard from '@/components/MainCard';
const TIMEZONES = ['Asia/Kolkata (IST)', 'Asia/Dubai (GST)', 'UTC', 'America/New_York (EST)'];
const LANGUAGES = ['English', 'हिन्दी (Hindi)', 'العربية (Arabic)'];
function TabPanel({ value, index, children }) {
if (value !== index) return null;
return <Box sx={{ pt: 1 }}>{children}</Box>;
}
export default function Settings() {
const [tab, setTab] = useState(0);
const [toast, setToast] = useState(false);
// General
const [general, setGeneral] = useState({
orgName: 'Doormile Logistics Pvt. Ltd.',
supportEmail: 'support@doormile.in',
contact: '+91 98450 11223',
timezone: TIMEZONES[0],
language: LANGUAGES[0]
});
// Notifications
const [notify, setNotify] = useState({
newOrders: true,
riderStatus: true,
invoicePaid: true,
weeklyDigest: false,
emailAlerts: true,
smsAlerts: false
});
// Security
const [security, setSecurity] = useState({
currentPassword: '',
newPassword: '',
confirmPassword: '',
twoFactor: false
});
const setG = (k) => (e) => setGeneral((p) => ({ ...p, [k]: e.target.value }));
const setN = (k) => (e) => setNotify((p) => ({ ...p, [k]: e.target.checked }));
const setS = (k) => (e) => setSecurity((p) => ({ ...p, [k]: e.target.value ?? e.target.checked }));
const save = () => setToast(true);
return (
<>
<PageHeader
title="Settings"
breadcrumbs={[{ label: 'Settings' }]}
action={
<Button variant="contained" startIcon={<SaveOutlinedIcon />} onClick={save}>
Save Changes
</Button>
}
/>
<Grid container spacing={2.5}>
<Grid item xs={12} md={3}>
<MainCard noPadding>
<Tabs
orientation="vertical"
value={tab}
onChange={(_, v) => setTab(v)}
sx={{
'& .MuiTab-root': { alignItems: 'flex-start', textTransform: 'none', minHeight: 52, fontWeight: 600 }
}}
>
<Tab icon={<TuneOutlinedIcon fontSize="small" />} iconPosition="start" label="General" />
<Tab icon={<NotificationsNoneIcon fontSize="small" />} iconPosition="start" label="Notifications" />
<Tab icon={<LockOutlinedIcon fontSize="small" />} iconPosition="start" label="Security" />
</Tabs>
</MainCard>
</Grid>
<Grid item xs={12} md={9}>
{/* General */}
<TabPanel value={tab} index={0}>
<MainCard title="Organisation">
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<TextField fullWidth label="Organisation Name" value={general.orgName} onChange={setG('orgName')} />
</Grid>
<Grid item xs={12} sm={6}>
<TextField fullWidth label="Support Email" value={general.supportEmail} onChange={setG('supportEmail')} />
</Grid>
<Grid item xs={12} sm={6}>
<TextField fullWidth label="Contact Number" value={general.contact} onChange={setG('contact')} />
</Grid>
<Grid item xs={12} sm={6}>
<TextField select fullWidth label="Timezone" value={general.timezone} onChange={setG('timezone')}>
{TIMEZONES.map((t) => (
<MenuItem key={t} value={t}>{t}</MenuItem>
))}
</TextField>
</Grid>
<Grid item xs={12} sm={6}>
<TextField select fullWidth label="Language" value={general.language} onChange={setG('language')}>
{LANGUAGES.map((l) => (
<MenuItem key={l} value={l}>{l}</MenuItem>
))}
</TextField>
</Grid>
</Grid>
</MainCard>
</TabPanel>
{/* Notifications */}
<TabPanel value={tab} index={1}>
<MainCard title="Notification Preferences">
<Stack divider={<Divider flexItem />} spacing={0}>
{[
{ k: 'newOrders', t: 'New orders', d: 'Notify when a new order is placed' },
{ k: 'riderStatus', t: 'Rider status', d: 'When a rider goes online or offline' },
{ k: 'invoicePaid', t: 'Invoice paid', d: 'When a client settles an invoice' },
{ k: 'weeklyDigest', t: 'Weekly digest', d: 'A summary of operations every Monday' }
].map((row) => (
<Stack key={row.k} direction="row" alignItems="center" justifyContent="space-between" sx={{ py: 1.5 }}>
<Box>
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>{row.t}</Typography>
<Typography variant="caption" color="text.secondary">{row.d}</Typography>
</Box>
<Switch checked={notify[row.k]} onChange={setN(row.k)} />
</Stack>
))}
</Stack>
<Divider sx={{ my: 2 }} />
<Typography variant="subtitle2" sx={{ fontWeight: 700, mb: 1 }}>Channels</Typography>
<Stack direction={{ xs: 'column', sm: 'row' }} spacing={2}>
<FormControlLabel control={<Switch checked={notify.emailAlerts} onChange={setN('emailAlerts')} />} label="Email alerts" />
<FormControlLabel control={<Switch checked={notify.smsAlerts} onChange={setN('smsAlerts')} />} label="SMS alerts" />
</Stack>
</MainCard>
</TabPanel>
{/* Security */}
<TabPanel value={tab} index={2}>
<Stack spacing={2.5}>
<MainCard title="Change Password">
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<TextField fullWidth type="password" label="Current Password" value={security.currentPassword} onChange={setS('currentPassword')} />
</Grid>
<Grid item xs={12} />
<Grid item xs={12} sm={6}>
<TextField fullWidth type="password" label="New Password" value={security.newPassword} onChange={setS('newPassword')} />
</Grid>
<Grid item xs={12} sm={6}>
<TextField fullWidth type="password" label="Confirm New Password" value={security.confirmPassword} onChange={setS('confirmPassword')} />
</Grid>
</Grid>
</MainCard>
<MainCard title="Two-Factor Authentication">
<Stack direction="row" alignItems="center" justifyContent="space-between">
<Box>
<Typography variant="subtitle2" sx={{ fontWeight: 600 }}>Authenticator app</Typography>
<Typography variant="caption" color="text.secondary">
Require a one-time code at sign-in for extra security.
</Typography>
</Box>
<Switch checked={security.twoFactor} onChange={(e) => setSecurity((p) => ({ ...p, twoFactor: e.target.checked }))} />
</Stack>
</MainCard>
</Stack>
</TabPanel>
</Grid>
</Grid>
<Snackbar
open={toast}
autoHideDuration={2500}
onClose={() => setToast(false)}
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
>
<Alert severity="success" variant="filled" onClose={() => setToast(false)} sx={{ width: '100%' }}>
Settings saved successfully.
</Alert>
</Snackbar>
</>
);
}