chore: change the styles and add countries to the user profile

This commit is contained in:
Koosha Lahouti
2025-08-10 17:51:46 -07:00
parent 8e6c09225d
commit ed57858c2e
6 changed files with 146 additions and 128 deletions

View File

@@ -11,6 +11,8 @@ import { CardContainer } from '@/components/CardContainer';
import { useTranslation } from 'react-i18next';
import { ThemeToggleButton } from '@/components/ThemToggle';
import { PageWrapper } from '../PageWrapper';
import { Icon } from '@rkheftan/harmony-ui';
import { Sun1, Moon, Calendar1 } from 'iconsax-react';
export function Setting() {
const { t, i18n } = useTranslation(['setting']);
@@ -21,18 +23,18 @@ export function Setting() {
);
const [draftLanguage, setDraftLanguage] = useState<string>(savedLanguage);
const [isEditing, setIsEditing] = useState(false);
const [selectedCalendar, setSelectedCalendar] = useState<string>(
t('settings.solar'),
);
const [selectedCalendar, setSelectedCalendar] = useState<
'christian' | 'solar' | 'lunar'
>('solar');
const languageOptions = [
{ code: 'en', label: 'English' },
{ code: 'fa', label: 'فارسی' },
];
const calendarOptions = [
t('settings.christian'),
t('settings.solar'),
t('settings.lunar'),
const calendarOptions: ('christian' | 'solar' | 'lunar')[] = [
'christian',
'solar',
'lunar',
];
const handleDraftLanguageChange = (
@@ -56,6 +58,10 @@ export function Setting() {
const handleEditToggle = () =>
isEditing ? handleSave() : setIsEditing(true);
// useEffect(() => {
// setSelectedCalendar(t('settings.solar'));
// }, [i18n.language, t]);
return (
<PageWrapper>
<Box
@@ -141,11 +147,26 @@ export function Setting() {
<Typography variant="caption" color="text.secondary">
{t('settings.theme')}
</Typography>
<Typography variant="body1">
{mode === 'light'
? t('settings.light')
: t('settings.dark')}
</Typography>
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: 1,
}}
>
<Icon
Component={mode === 'light' ? Sun1 : Moon}
size="medium"
variant="Bold"
color={mode === 'light' ? 'black' : 'primary.main'}
/>
<Typography variant="body1">
{mode === 'light'
? t('settings.light')
: t('settings.dark')}
</Typography>
</Box>
</Box>
)}
</Box>
@@ -184,10 +205,11 @@ export function Setting() {
{isEditing ? (
<Autocomplete
options={calendarOptions}
getOptionLabel={(key) => t(`settings.${key}`)}
value={selectedCalendar}
onChange={(_, v) => v && setSelectedCalendar(v)}
renderInput={(p) => (
<TextField {...p} label={t('settings.calendar')} />
renderInput={(params) => (
<TextField {...params} label={t('settings.calendar')} />
)}
size="medium"
fullWidth
@@ -197,7 +219,17 @@ export function Setting() {
<Typography variant="caption" color="text.secondary">
{t('settings.calendar')}
</Typography>
<Typography variant="body1">{selectedCalendar}</Typography>
<Box sx={{ display: 'flex', gap: 1 }}>
<Icon
Component={Calendar1}
size="medium"
color={mode === 'light' ? 'black' : 'primary.main'}
variant="Bold"
/>
<Typography variant="body1">
{t(`settings.${selectedCalendar}`)}
</Typography>
</Box>
</Box>
)}
</Box>

View File

@@ -1,7 +1,7 @@
import { Box, Typography, Avatar } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { CountryFlag } from '@/components/CountryFlag';
import { DisplayField } from './DisplayField';
import { CountryFlag } from '@/components/CountryFlag';
import { Gender } from '@/features/profile/types';
interface InfoRowData {
@@ -26,6 +26,7 @@ export function InfoRowDisplay({
const { t } = useTranslation('profileSetting');
const displayValue = (value: string) =>
value?.trim() || t('settingForm.notDetermined');
const getGenderLabel = (gender: Gender | '') => {
switch (gender) {
case Gender.Male:
@@ -36,6 +37,7 @@ export function InfoRowDisplay({
return t('settingForm.notDetermined');
}
};
return (
<Box sx={{ mb: 2 }}>
<Box sx={{ width: '100%' }}>
@@ -70,7 +72,9 @@ export function InfoRowDisplay({
{initials}
</Avatar>
<Typography variant="body1" color="text.primary">
{`${displayValue(data.firstName)} ${displayValue(data.lastName)}`}
{`${displayValue(data.firstName)} ${displayValue(
data.lastName,
)}`}
</Typography>
</Box>
</Box>
@@ -79,7 +83,15 @@ export function InfoRowDisplay({
<Typography variant="caption" color="text.secondary">
{t('settingForm.country')}
</Typography>
<CountryFlag country={data.country} />
<Box sx={{ mt: 0.5 }}>
{data.country ? (
<CountryFlag code={data.country} />
) : (
<Typography variant="body1" color="text.primary">
{t('settingForm.notDetermined')}
</Typography>
)}
</Box>
</Box>
</Box>
</Box>

View File

@@ -7,7 +7,8 @@ import {
Autocomplete,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { CountryFlag, countryCodeMap } from '@/components/CountryFlag';
import { countries } from '@/features/profile/data/countries';
import { CountryFlag } from '@/components/CountryFlag';
import { Gender } from '@/features/profile/types';
import { type InfoRowData } from '@/features/profile/types';
@@ -24,44 +25,50 @@ export function InfoRowEdit({
gender,
setGender,
}: InfoRowEditProps) {
const { t } = useTranslation('profileSetting');
const { t } = useTranslation(['countries', 'profileSetting']);
const labels = [
{
name: 'firstName' as keyof InfoRowData,
label: t('settingForm.name'),
value: data.firstName,
},
{
name: 'lastName' as keyof InfoRowData,
label: t('settingForm.familyName'),
value: data.lastName,
},
{
name: 'nationalCode' as keyof InfoRowData,
label: t('settingForm.nationalCode'),
value: data.nationalCode,
},
];
const countryOptions = countries.map((c) => ({
code: c.code,
label: t(c.label, { ns: 'countries' }),
}));
const currentCountry =
countryOptions.find((c) => c.code === data.country) || null;
return (
<Box sx={{ display: 'flex', gap: 2, flexWrap: 'wrap' }}>
{labels.map((field, idx) => (
{[
{
name: 'firstName' as keyof InfoRowData,
label: t('settingForm.name', { ns: 'profileSetting' }),
value: data.firstName,
},
{
name: 'lastName' as keyof InfoRowData,
label: t('settingForm.familyName', { ns: 'profileSetting' }),
value: data.lastName,
},
{
name: 'nationalCode' as keyof InfoRowData,
label: t('settingForm.nationalCode', { ns: 'profileSetting' }),
value: data.nationalCode,
},
].map(({ name, label, value }) => (
<Box
key={idx}
key={name}
sx={{ width: { xs: '100%', sm: '48%', md: 'calc(50% - 8px)' } }}
>
<TextField
fullWidth
name={field.name}
value={field.value}
name={name}
value={value}
onChange={(e) =>
setData((prev) => ({
...prev,
[field.name]: e.target.value,
[name]: e.target.value,
}))
}
label={field.label}
label={label}
/>
</Box>
))}
@@ -75,36 +82,50 @@ export function InfoRowEdit({
renderValue={(selected) =>
selected ? (
selected === Gender.Male ? (
t('settingForm.man')
t('settingForm.man', { ns: 'profileSetting' })
) : (
t('settingForm.woman')
t('settingForm.woman', { ns: 'profileSetting' })
)
) : (
<span>{t('settingForm.genderPlaceholder')}</span>
<span>
{t('settingForm.genderPlaceholder', { ns: 'profileSetting' })}
</span>
)
}
>
<MenuItem value={Gender.Male}>{t('settingForm.man')}</MenuItem>
<MenuItem value={Gender.Female}>{t('settingForm.woman')}</MenuItem>
<MenuItem value={Gender.Male}>
{t('settingForm.man', { ns: 'profileSetting' })}
</MenuItem>
<MenuItem value={Gender.Female}>
{t('settingForm.woman', { ns: 'profileSetting' })}
</MenuItem>
</Select>
</FormControl>
</Box>
<Autocomplete
sx={{ width: { xs: '100%', sm: '48%', md: 'calc(50% - 8px)' } }}
options={Object.keys(countryCodeMap)}
value={data.country}
options={countryOptions}
getOptionLabel={(option) => option.label}
value={currentCountry}
onChange={(_, newValue) =>
setData((prev) => ({ ...prev, country: newValue || '' }))
setData((prev) => ({
...prev,
country: newValue?.code || '',
}))
}
renderOption={(props, option) => (
<Box component="li" {...props}>
<CountryFlag country={option} />
<Box component="li" {...props} key={option.code}>
<CountryFlag code={option.code} />
</Box>
)}
renderInput={(params) => (
<TextField {...params} label={t('settingForm.country')} />
<TextField
{...params}
label={t('settingForm.country', { ns: 'profileSetting' })}
/>
)}
clearOnEscape
/>
</Box>
);