fix: responsiveness of sideNav component
This commit is contained in:
22
src/features/profile/components/PageWrapper.tsx
Normal file
22
src/features/profile/components/PageWrapper.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Box } from '@mui/material';
|
||||
import React from 'react';
|
||||
|
||||
interface PageWrapperProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function PageWrapper({ children }: PageWrapperProps) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mx: 'auto',
|
||||
width: { xs: '100%', sm: '754px' },
|
||||
backgroundColor: 'background.paper',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { DeviceMessage, Logout } from 'iconsax-react';
|
||||
import Logo from '@/components/Logo';
|
||||
import { CardContainer } from '@/components/CardContainer';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
export function ActiveDevices() {
|
||||
const { t } = useTranslation('activeDevices');
|
||||
@@ -39,25 +40,13 @@ export function ActiveDevices() {
|
||||
];
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mx: 'auto',
|
||||
backgroundColor: 'background.paper',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
py: 2,
|
||||
height: 84,
|
||||
}}
|
||||
>
|
||||
<PageWrapper>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', py: 2, height: 84 }}>
|
||||
<Logo />
|
||||
</Box>
|
||||
|
||||
<Box sx={{ width: '100%', height: 1, bgcolor: 'divider' }} />
|
||||
|
||||
<CardContainer
|
||||
title={t('active.activeDevices')}
|
||||
subtitle={t('active.activeDevicesCaption')}
|
||||
@@ -68,8 +57,8 @@ export function ActiveDevices() {
|
||||
borderRadius: '10px',
|
||||
borderColor: 'error.main',
|
||||
color: 'error.main',
|
||||
border: '1px solid',
|
||||
textTransform: 'none',
|
||||
width: { xs: '100%', sm: 'auto' },
|
||||
}}
|
||||
>
|
||||
{t('active.deletDevicesButton')}
|
||||
@@ -82,111 +71,125 @@ export function ActiveDevices() {
|
||||
py: 2,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
flex: 1,
|
||||
// gap: 2,
|
||||
}}
|
||||
>
|
||||
<Box sx={{ width: '100%', maxWidth: '754px' }}>
|
||||
{devices.map((device) => (
|
||||
{devices.map((device) => (
|
||||
<Box
|
||||
key={device.id}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
alignItems: { xs: 'flex-start', sm: 'center' },
|
||||
minHeight: 50,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
minWidth: { sm: '138px' },
|
||||
order: { xs: 1, sm: 1 },
|
||||
}}
|
||||
>
|
||||
{device.timeAndDate}
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
key={device.id}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
height: 50,
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
minWidth: { sm: '138px' },
|
||||
order: { xs: 2, sm: 2 },
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ width: { xs: '100%', sm: '138px' } }}
|
||||
>
|
||||
{device.timeAndDate}
|
||||
<DeviceMessage size={24} color="#82B1FF" />
|
||||
<Typography variant="body2" noWrap>
|
||||
{device.deviceModel}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
width: { xs: '100%', sm: '138px' },
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<DeviceMessage size={24} color="#82B1FF" />
|
||||
<Typography
|
||||
variant="body2"
|
||||
noWrap
|
||||
sx={{ width: { xs: '100%', sm: '138px' } }}
|
||||
>
|
||||
{device.deviceModel}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ width: { xs: '100%', sm: '138px' } }}
|
||||
>
|
||||
{device.ip}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={{
|
||||
width: { xs: '100%', sm: '138px' },
|
||||
textAlign: { xs: 'left', sm: 'center' },
|
||||
}}
|
||||
>
|
||||
{device.current && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
sx={{
|
||||
borderRadius: '15px',
|
||||
border: '2px solid',
|
||||
borderColor: 'success.main',
|
||||
height: '30px',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'success.main',
|
||||
// width: '93px',
|
||||
textTransform: 'none',
|
||||
}}
|
||||
>
|
||||
{t('active.currentDevice')}
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
width: { xs: '100%', sm: '138px' },
|
||||
textAlign: { xs: 'left', sm: 'center' },
|
||||
}}
|
||||
>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
minWidth: { sm: '138px' },
|
||||
order: { xs: 3, sm: 3 },
|
||||
}}
|
||||
>
|
||||
{device.ip}
|
||||
</Typography>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
textAlign: { xs: 'left', sm: 'center' },
|
||||
minWidth: { sm: '138px' },
|
||||
order: { xs: 4, sm: 4 },
|
||||
}}
|
||||
>
|
||||
{device.current && (
|
||||
<Button
|
||||
size="small"
|
||||
variant="outlined"
|
||||
startIcon={<Logout size={18} color="#E53935" />}
|
||||
disabled={device.current}
|
||||
sx={{
|
||||
color: 'error.main',
|
||||
// width: '80%',
|
||||
minWidth: 0,
|
||||
borderRadius: '15px',
|
||||
borderColor: 'error.main',
|
||||
p: '4px 8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
border: '2px solid',
|
||||
borderColor: 'success.main',
|
||||
height: '30px',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'success.main',
|
||||
textTransform: 'none',
|
||||
'& .MuiButton-startIcon': {
|
||||
marginRight: '4px',
|
||||
marginLeft: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{t('active.deleteDevice')}
|
||||
{t('active.currentDevice')}
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
textAlign: { xs: 'left', sm: 'center' },
|
||||
minWidth: { sm: '150px' },
|
||||
order: { xs: 5, sm: 5 },
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
size="small"
|
||||
variant="outlined"
|
||||
startIcon={<Logout size={18} color="#E53935" />}
|
||||
disabled={device.current}
|
||||
sx={{
|
||||
color: 'error.main',
|
||||
minWidth: 0,
|
||||
borderRadius: '15px',
|
||||
borderColor: 'error.main',
|
||||
p: '4px 8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
whiteSpace: 'nowrap',
|
||||
textTransform: 'none',
|
||||
'& .MuiButton-startIcon': {
|
||||
marginRight: '4px',
|
||||
marginLeft: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{t('active.deleteDevice')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { PasswordValidationItem } from './PasswordValidation';
|
||||
import { Toast } from '@/components/Toast';
|
||||
import Logo from '@/components/Logo';
|
||||
import { CardContainer } from '@/components/CardContainer';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
export function PasswordSecurity() {
|
||||
const theme = useTheme();
|
||||
@@ -70,14 +71,7 @@ export function PasswordSecurity() {
|
||||
}, [password, validPassword]);
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mx: 'auto',
|
||||
backgroundColor: 'background.paper',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<PageWrapper>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', py: 2, height: 84 }}>
|
||||
<Logo />
|
||||
</Box>
|
||||
@@ -148,7 +142,6 @@ export function PasswordSecurity() {
|
||||
</Typography>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
@@ -198,7 +191,6 @@ export function PasswordSecurity() {
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 } }}
|
||||
/>
|
||||
|
||||
{password && showValidation && (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Box sx={{ maxWidth: '364px', width: '100%' }}>
|
||||
@@ -221,7 +213,6 @@ export function PasswordSecurity() {
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
label={t('securityForm.confirmPassword')}
|
||||
type="password"
|
||||
@@ -257,7 +248,6 @@ export function PasswordSecurity() {
|
||||
mt: 2,
|
||||
}}
|
||||
/>
|
||||
|
||||
{password && showValidation && (
|
||||
<Box sx={{ display: 'flex', justifyContent: 'center' }}>
|
||||
<Box sx={{ maxWidth: '364px', width: '100%' }}>
|
||||
@@ -280,7 +270,6 @@ export function PasswordSecurity() {
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
label={t('securityForm.confirmPassword')}
|
||||
type="password"
|
||||
@@ -325,7 +314,6 @@ export function PasswordSecurity() {
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Toast
|
||||
color="success"
|
||||
open={showPasswordAlert}
|
||||
@@ -335,6 +323,6 @@ export function PasswordSecurity() {
|
||||
</Toast>
|
||||
</Box>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Box, Typography, Button } from '@mui/material';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CardContainer } from '@/components/CardContainer';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
export function RecentLogins() {
|
||||
const { t } = useTranslation('security');
|
||||
@@ -22,27 +23,25 @@ export function RecentLogins() {
|
||||
];
|
||||
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
mx: 'auto',
|
||||
backgroundColor: 'background.paper',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
}}
|
||||
>
|
||||
<PageWrapper>
|
||||
<CardContainer
|
||||
title={t('securityForm.recentLogins')}
|
||||
subtitle={t('securityForm.description')}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
px: { xs: 2, sm: 3, md: 4 },
|
||||
// px: { xs: 2, sm: 3, md: 4 },
|
||||
py: 2,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
bgcolor: 'background.paper',
|
||||
flex: 1,
|
||||
borderBottom: '1px solid',
|
||||
borderColor: 'divider',
|
||||
'&:last-child': {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box sx={{ width: '100%', maxWidth: '754px', px: 4 }}>
|
||||
@@ -50,31 +49,54 @@ export function RecentLogins() {
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
height: '50px',
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
alignItems: { xs: 'flex-start', sm: 'center' },
|
||||
minHeight: 50,
|
||||
}}
|
||||
key={d.id}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ width: { xs: '100%', sm: '172.5px' } }}
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
minWidth: { sm: '172.5px' },
|
||||
order: { xs: 1, sm: 1 },
|
||||
}}
|
||||
>
|
||||
{d.time}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ width: { xs: '100%', sm: '172.5px' } }}
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
minWidth: { sm: '172.5px' },
|
||||
order: { xs: 1, sm: 1 },
|
||||
}}
|
||||
>
|
||||
{d.device}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body2"
|
||||
sx={{ width: { xs: '100%', sm: '172.5px' } }}
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
minWidth: { sm: '172.5px' },
|
||||
order: { xs: 1, sm: 1 },
|
||||
}}
|
||||
>
|
||||
{d.ip}
|
||||
</Typography>
|
||||
<Box sx={{ width: { xs: '100%', sm: '172.5px' } }}>
|
||||
<Box
|
||||
sx={{
|
||||
flexBasis: { xs: '100%', sm: 'auto' },
|
||||
mb: { xs: 1, sm: 0 },
|
||||
textAlign: { xs: 'left', sm: 'center' },
|
||||
minWidth: { sm: '172.5px' },
|
||||
order: { xs: 4, sm: 4 },
|
||||
}}
|
||||
>
|
||||
{d.current && (
|
||||
<Button
|
||||
variant="outlined"
|
||||
@@ -85,9 +107,7 @@ export function RecentLogins() {
|
||||
height: '30px',
|
||||
whiteSpace: 'nowrap',
|
||||
color: 'success.main',
|
||||
width: '93px',
|
||||
textTransform: 'none',
|
||||
fontSize: '0.75rem',
|
||||
}}
|
||||
>
|
||||
{t('securityForm.currentDevice')}
|
||||
@@ -99,6 +119,6 @@ export function RecentLogins() {
|
||||
</Box>
|
||||
</Box>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import { CardContainer } from '@/components/CardContainer';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ThemeToggleButton } from '@/components/ThemToggle';
|
||||
import Logo from '@/components/Logo';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
export function Setting() {
|
||||
const { t, i18n } = useTranslation(['setting']);
|
||||
@@ -57,113 +58,143 @@ export function Setting() {
|
||||
isEditing ? handleSave() : setIsEditing(true);
|
||||
|
||||
return (
|
||||
<Box sx={{ backgroundColor: 'background.paper', minHeight: '100vh' }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
py: 2,
|
||||
height: 84,
|
||||
}}
|
||||
>
|
||||
<PageWrapper>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', py: 2, height: 84 }}>
|
||||
<Logo />
|
||||
</Box>
|
||||
<Box sx={{ width: '100%', height: 1, bgcolor: 'divider' }} />
|
||||
<CardContainer
|
||||
title={t('settings.title')}
|
||||
subtitle={t('settings.description')}
|
||||
highlighted={isEditing}
|
||||
action={
|
||||
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
|
||||
{isEditing && (
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%', // always span full width
|
||||
px: { xs: 0, sm: 3 }, // no side padding on xs, keep padding on sm+
|
||||
mx: 0, // zero out any horizontal margin
|
||||
}}
|
||||
>
|
||||
<CardContainer
|
||||
title={t('settings.title')}
|
||||
subtitle={t('settings.description')}
|
||||
highlighted={isEditing}
|
||||
action={
|
||||
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
|
||||
{isEditing && (
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={handleCancel}
|
||||
size="large"
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
textTransform: 'none',
|
||||
width: { xs: '100%', sm: 'auto' },
|
||||
fontSize: { xs: '0.85rem', sm: '1rem' },
|
||||
}}
|
||||
>
|
||||
{t('settings.rejectButton')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="text"
|
||||
onClick={handleCancel}
|
||||
onClick={handleEditToggle}
|
||||
size="large"
|
||||
variant="outlined"
|
||||
sx={{
|
||||
color: 'primary.main',
|
||||
textTransform: 'none',
|
||||
width: { xs: '100%', sm: 'auto' },
|
||||
fontSize: { xs: '0.85rem', sm: '1rem' },
|
||||
border: '1px solid',
|
||||
borderColor: 'primary.main',
|
||||
borderRadius: '4px',
|
||||
bgcolor: isEditing ? 'primary.main' : 'background.paper',
|
||||
color: isEditing ? 'primary.contrastText' : 'primary.main',
|
||||
px: { xs: 2, sm: '22px' },
|
||||
py: { xs: '6px', sm: '8px' },
|
||||
width: { xs: '100%', sm: isEditing ? '85px' : '93px' },
|
||||
fontSize: { xs: '0.9rem', sm: '1rem' },
|
||||
}}
|
||||
>
|
||||
{t('settings.rejectButton')}
|
||||
{isEditing
|
||||
? t('settings.saveButton')
|
||||
: t('settings.editButton')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={handleEditToggle}
|
||||
size="large"
|
||||
variant="outlined"
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
border: '1px solid',
|
||||
borderColor: 'primary.main',
|
||||
borderRadius: '4px',
|
||||
bgcolor: isEditing ? 'primary.main' : 'background.paper',
|
||||
color: isEditing ? 'primary.contrastText' : 'primary.main',
|
||||
px: { xs: 2, sm: '22px' },
|
||||
py: { xs: '6px', sm: '8px' },
|
||||
width: { xs: '100%', sm: isEditing ? '85px' : '93px' },
|
||||
fontSize: { xs: '0.9rem', sm: '1rem' },
|
||||
}}
|
||||
>
|
||||
{isEditing ? t('settings.saveButton') : t('settings.editButton')}
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
px: { xs: 2, sm: 3, md: 4 },
|
||||
py: 2,
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
bgcolor: 'background.paper',
|
||||
}}
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
px: { xs: 2, sm: 3, md: 4 },
|
||||
py: 2,
|
||||
display: 'flex',
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
mt: 2,
|
||||
mx: 'auto',
|
||||
width: { xs: '100%', md: 690 },
|
||||
// px: 4,
|
||||
bgcolor: 'background.paper',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: 1, maxWidth: { sm: 310 }, width: '100%' }}>
|
||||
{isEditing ? (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Typography variant="body1">{t('settings.theme')}</Typography>
|
||||
<ThemeToggleButton />
|
||||
</Box>
|
||||
) : (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t('settings.theme')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{mode === 'light'
|
||||
? t('settings.light')
|
||||
: t('settings.dark')}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
gap: 2,
|
||||
mt: 2,
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
{isEditing ? (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
<Typography variant="body1">
|
||||
{t('settings.theme')}
|
||||
</Typography>
|
||||
<ThemeToggleButton />
|
||||
</Box>
|
||||
) : (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t('settings.theme')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{mode === 'light'
|
||||
? t('settings.light')
|
||||
: t('settings.dark')}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ flex: 1 }}>
|
||||
{isEditing ? (
|
||||
<Autocomplete
|
||||
options={languageOptions}
|
||||
getOptionLabel={(o) => o.label}
|
||||
value={
|
||||
languageOptions.find((o) => o.code === draftLanguage) ||
|
||||
null
|
||||
}
|
||||
onChange={handleDraftLanguageChange}
|
||||
renderInput={(p) => (
|
||||
<TextField {...p} label={t('settings.language')} />
|
||||
)}
|
||||
size="medium"
|
||||
fullWidth
|
||||
/>
|
||||
) : (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t('settings.language')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{
|
||||
languageOptions.find((o) => o.code === savedLanguage)
|
||||
?.label
|
||||
}
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ flex: 1, maxWidth: { sm: 310 }, width: '100%' }}>
|
||||
<Box sx={{ mt: 2, width: '100%' }}>
|
||||
{isEditing ? (
|
||||
<Autocomplete
|
||||
options={languageOptions}
|
||||
getOptionLabel={(o) => o.label}
|
||||
value={
|
||||
languageOptions.find((o) => o.code === draftLanguage) ||
|
||||
null
|
||||
}
|
||||
onChange={handleDraftLanguageChange}
|
||||
options={calendarOptions}
|
||||
value={selectedCalendar}
|
||||
onChange={(_, v) => v && setSelectedCalendar(v)}
|
||||
renderInput={(p) => (
|
||||
<TextField {...p} label={t('settings.language')} />
|
||||
<TextField {...p} label={t('settings.calendar')} />
|
||||
)}
|
||||
size="medium"
|
||||
fullWidth
|
||||
@@ -171,41 +202,15 @@ export function Setting() {
|
||||
) : (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t('settings.language')}
|
||||
</Typography>
|
||||
<Typography variant="body1">
|
||||
{
|
||||
languageOptions.find((o) => o.code === savedLanguage)
|
||||
?.label
|
||||
}
|
||||
{t('settings.calendar')}
|
||||
</Typography>
|
||||
<Typography variant="body1">{selectedCalendar}</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ mt: 2, maxWidth: { sm: 310 }, width: '100%' }}>
|
||||
{isEditing ? (
|
||||
<Autocomplete
|
||||
options={calendarOptions}
|
||||
value={selectedCalendar}
|
||||
onChange={(_, v) => v && setSelectedCalendar(v)}
|
||||
renderInput={(p) => (
|
||||
<TextField {...p} label={t('settings.calendar')} />
|
||||
)}
|
||||
size="medium"
|
||||
fullWidth
|
||||
/>
|
||||
) : (
|
||||
<Box>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{t('settings.calendar')}
|
||||
</Typography>
|
||||
<Typography variant="body1">{selectedCalendar}</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ProfileImage } from './personlInformation/ProfileImage';
|
||||
import { InfoRowDisplay } from './personlInformation/InfoRowDisplay';
|
||||
import { InfoRowEdit } from './personlInformation/InfoRowEdit';
|
||||
import Logo from '@/components/Logo';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
export function PersonalInformation() {
|
||||
const { t } = useTranslation('profileSetting');
|
||||
@@ -39,7 +40,7 @@ export function PersonalInformation() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ backgroundColor: 'background.paper' }}>
|
||||
<PageWrapper>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
@@ -138,6 +139,6 @@ export function PersonalInformation() {
|
||||
)}
|
||||
</Box>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import React, { useState, type ChangeEvent } from 'react';
|
||||
import { useState, type ChangeEvent } from 'react';
|
||||
import { Box, Typography, Button, TextField, IconButton } from '@mui/material';
|
||||
import { Edit, Refresh, TickCircle } from 'iconsax-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CardContainer } from '@/components/CardContainer';
|
||||
import { CountDownTimer } from '@/components/CountDownTimer';
|
||||
import { Toast } from '@/components/Toast';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
export function PhoneNumber() {
|
||||
const { t } = useTranslation('profileSetting');
|
||||
@@ -72,7 +73,7 @@ export function PhoneNumber() {
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ backgroundColor: 'background.paper' }}>
|
||||
<PageWrapper>
|
||||
<CardContainer
|
||||
title={t('settingForm.titlePhoneNumber')}
|
||||
subtitle={t('settingForm.descriptionPhoneNumber')}
|
||||
@@ -283,6 +284,6 @@ export function PhoneNumber() {
|
||||
</Box>
|
||||
)}
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import {
|
||||
ListItemText,
|
||||
useMediaQuery,
|
||||
} from '@mui/material';
|
||||
import Slide from '@mui/material/Slide';
|
||||
import type { TransitionProps } from '@mui/material/transitions';
|
||||
import type { Theme } from '@mui/material/styles';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CardContainer } from '@/components/CardContainer';
|
||||
@@ -27,17 +29,34 @@ import {
|
||||
Message,
|
||||
ArrowDown3,
|
||||
} from 'iconsax-react';
|
||||
import { PageWrapper } from '../PageWrapper';
|
||||
|
||||
const MobileSlide = React.forwardRef(function MobileSlide(
|
||||
props: TransitionProps & { children: React.ReactElement<any, any> },
|
||||
ref: React.Ref<unknown>,
|
||||
) {
|
||||
return <Slide direction="up" ref={ref} {...props} />;
|
||||
});
|
||||
|
||||
export function SocialMedia() {
|
||||
const { t } = useTranslation('profileSetting');
|
||||
|
||||
const [openDialog, setOpenDialog] = useState(false);
|
||||
const [emailInput, setEmailInput] = useState('');
|
||||
const [emailError, setEmailError] = useState(false);
|
||||
const [anchor, setAnchor] = useState<null | HTMLElement>(null);
|
||||
|
||||
const openMenu = Boolean(anchor);
|
||||
const fullScreen = useMediaQuery((theme: Theme) =>
|
||||
theme.breakpoints.down('sm'),
|
||||
);
|
||||
const downMd = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
|
||||
const computedMaxWidth = (fullScreen ? 'xs' : downMd ? 'sm' : 'md') as
|
||||
| 'xs'
|
||||
| 'sm'
|
||||
| 'md'
|
||||
| 'lg'
|
||||
| 'xl';
|
||||
|
||||
const handleOpenDialog = () => setOpenDialog(true);
|
||||
const handleCloseDialog = () => setOpenDialog(false);
|
||||
@@ -59,7 +78,7 @@ export function SocialMedia() {
|
||||
] as const;
|
||||
|
||||
return (
|
||||
<Box sx={{ backgroundColor: 'background.paper' }}>
|
||||
<PageWrapper>
|
||||
<CardContainer
|
||||
title={t('settingForm.titleSocial')}
|
||||
subtitle={t('settingForm.descriptionSocial')}
|
||||
@@ -196,7 +215,7 @@ export function SocialMedia() {
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
<IconButton size="small">
|
||||
<IconButton size="small" aria-label="Delete">
|
||||
<Trash size="20" color="gray" variant="Outline" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
@@ -207,10 +226,18 @@ export function SocialMedia() {
|
||||
open={openDialog}
|
||||
onClose={handleCloseDialog}
|
||||
fullWidth
|
||||
maxWidth="xs"
|
||||
fullScreen={fullScreen}
|
||||
sx={{
|
||||
'& .MuiDialog-paper': { m: { xs: 1, sm: 'auto' }, borderRadius: 2 },
|
||||
maxWidth={computedMaxWidth}
|
||||
scroll="paper"
|
||||
keepMounted
|
||||
TransitionComponent={fullScreen ? MobileSlide : undefined}
|
||||
PaperProps={{
|
||||
sx: {
|
||||
m: { xs: 0, sm: 2 },
|
||||
borderRadius: { xs: 0, sm: 2 },
|
||||
width: { xs: '100%', sm: 'auto' },
|
||||
height: { xs: '100%', sm: 'auto' },
|
||||
},
|
||||
}}
|
||||
>
|
||||
<DialogTitle
|
||||
@@ -221,113 +248,122 @@ export function SocialMedia() {
|
||||
fontWeight: 'bold',
|
||||
fontSize: '16px',
|
||||
gap: 1,
|
||||
p: { xs: 1.5, sm: 2 },
|
||||
position: { xs: 'sticky', sm: 'static' },
|
||||
top: 0,
|
||||
bgcolor: 'background.paper',
|
||||
zIndex: 1,
|
||||
}}
|
||||
>
|
||||
<IconButton onClick={handleCloseDialog}>
|
||||
<IconButton onClick={handleCloseDialog} aria-label="Close">
|
||||
<CloseSquare size={24} color="#82B1FF" />
|
||||
</IconButton>
|
||||
{t('settingForm.addEmailButton')}
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
<DialogContent
|
||||
dividers
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
px: { xs: 2, sm: 3 },
|
||||
py: { xs: 1.5, sm: 2 },
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Typography fontWeight="bold">
|
||||
{t('settingForm.newEmail')}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{t('settingForm.dialogHeader')}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
type="email"
|
||||
value={emailInput}
|
||||
onChange={handleEmailChange}
|
||||
error={emailError}
|
||||
helperText={emailError ? t('settingForm.emailError') : ''}
|
||||
label={t('settingForm.email')}
|
||||
placeholder="abc@email.com"
|
||||
autoComplete="email"
|
||||
inputMode="email"
|
||||
sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2 } }}
|
||||
autoFocus
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
sx={{ textTransform: 'none', borderRadius: 2 }}
|
||||
disabled={emailError || emailInput === ''}
|
||||
>
|
||||
{t('settingForm.verificationCodeButton')}
|
||||
</Button>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', my: 2 }}>
|
||||
<Box sx={{ flex: 1, height: 1, bgcolor: 'divider' }} />
|
||||
<Typography sx={{ mx: 1, fontSize: 12, color: 'text.secondary' }}>
|
||||
{t('settingForm.or')}
|
||||
</Typography>
|
||||
<Box sx={{ flex: 1, height: 1, bgcolor: 'divider' }} />
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 2,
|
||||
gap: 1,
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Typography fontWeight="bold">
|
||||
{t('settingForm.newEmail')}
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
{t('settingForm.dialogHeader')}
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<TextField
|
||||
fullWidth
|
||||
type="email"
|
||||
value={emailInput}
|
||||
onChange={handleEmailChange}
|
||||
error={emailError}
|
||||
helperText={emailError ? t('settingForm.emailError') : ''}
|
||||
label={t('settingForm.email')}
|
||||
placeholder="abc@email.com"
|
||||
sx={{ '& .MuiOutlinedInput-root': { borderRadius: '8px' } }}
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
fullWidth
|
||||
sx={{ textTransform: 'none', borderRadius: '8px' }}
|
||||
disabled={emailError || emailInput === ''}
|
||||
>
|
||||
{t('settingForm.verificationCodeButton')}
|
||||
</Button>
|
||||
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', my: 2 }}>
|
||||
<Box sx={{ flex: 1, height: 1, bgcolor: '#ccc' }} />
|
||||
<Typography sx={{ mx: 1, fontSize: '12px', color: 'gray' }}>
|
||||
{t('settingForm.or')}
|
||||
</Typography>
|
||||
<Box sx={{ flex: 1, height: 1, bgcolor: '#ccc' }} />
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
border: 2,
|
||||
borderColor: 'primary.main',
|
||||
color: 'primary.main',
|
||||
borderRadius: 2,
|
||||
display: 'flex',
|
||||
gap: 1,
|
||||
flexDirection: { xs: 'column', sm: 'row' },
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
fullWidth
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
border: 2,
|
||||
borderColor: '#1976d2',
|
||||
color: '#1976d2',
|
||||
borderRadius: '8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Google
|
||||
size="20"
|
||||
color="#4285F4"
|
||||
style={{ marginInlineStart: 8 }}
|
||||
/>
|
||||
{t('settingForm.google')}
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
border: 2,
|
||||
borderColor: '#1976d2',
|
||||
color: '#1976d2',
|
||||
borderRadius: '8px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Apple
|
||||
size="20"
|
||||
color="black"
|
||||
style={{ marginInlineStart: 8 }}
|
||||
/>
|
||||
{t('settingForm.apple')}
|
||||
</Button>
|
||||
</Box>
|
||||
<Google
|
||||
size="20"
|
||||
color="#4285F4"
|
||||
style={{ marginInlineStart: 8 }}
|
||||
/>
|
||||
{t('settingForm.google')}
|
||||
</Button>
|
||||
<Button
|
||||
fullWidth
|
||||
sx={{
|
||||
textTransform: 'none',
|
||||
border: 2,
|
||||
borderColor: 'primary.main',
|
||||
color: 'primary.main',
|
||||
borderRadius: 2,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
>
|
||||
<Apple
|
||||
size="20"
|
||||
color="black"
|
||||
style={{ marginInlineStart: 8 }}
|
||||
/>
|
||||
{t('settingForm.apple')}
|
||||
</Button>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</CardContainer>
|
||||
</Box>
|
||||
</PageWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user