fix: merge errors

This commit is contained in:
Koosha Lahouti
2025-08-16 11:21:30 +03:30
parent 696d8fc06b
commit f7207b8545
57 changed files with 451 additions and 688 deletions

View File

@@ -13,7 +13,7 @@ import { useMemo, useRef, useState, type RefObject } from 'react';
import { ArrowDown2 } from 'iconsax-react';
import ReactCountryFlag from 'react-country-flag';
import { useTranslation } from 'react-i18next';
import { countries, type Country } from '../data/countries';
import { countries, type Country } from '@/data/countries';
interface CountryCodeSelectorProps {
show: boolean;

View File

@@ -1,285 +0,0 @@
import React, { useState, useEffect } from 'react';
import {
Box,
Typography,
Button,
useTheme,
useMediaQuery,
CircularProgress,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { DeviceMessage, Logout } from 'iconsax-react';
import { CardContainer } from '@/components/CardContainer';
import { PageWrapper } from '../PageWrapper';
import { Icon } from '@rkheftan/harmony-ui';
import { fetchProfile, deleteSessions } from '../../api/settingsApi';
import { type ApiSession } from '../../types/settingsApiType';
import { useManualApi } from '@/hooks/useApi';
import { formatDate } from '@/utils/formatSessionDate';
import { type Device } from '../../types/settingsType';
export function ActiveDevices() {
const { t, i18n } = useTranslation('setting');
const [devices, setDevices] = useState<Device[]>([]);
const [loadingDeleteIds, setLoadingDeleteIds] = useState<string[]>([]);
const theme = useTheme();
const isXsup = useMediaQuery(theme.breakpoints.up('xs'));
const {
data: profileData,
loading: isLoading,
error: fetchError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
const {
data: terminateData,
loading: isTerminating,
execute: executeTerminateAll,
} = useManualApi(deleteSessions);
useEffect(() => {
executeFetchProfile();
}, [i18n.language]);
useEffect(() => {
if (profileData?.success && profileData.activeSessions) {
const { sessions, currentKey } = profileData.activeSessions;
const formattedDevices = sessions.map((session: ApiSession) => ({
id: session.key,
timeAndDate: formatDate(session.created, i18n.language, t),
deviceModel: `${session.deviceOs} ${session.deviceName}`,
ip: session.ipAddress,
current: session.key === currentKey,
}));
setDevices(formattedDevices);
}
}, [profileData, i18n.language, t]);
useEffect(() => {
if (terminateData?.success) {
setDevices((prev) => prev.filter((d) => d.current));
}
}, [terminateData]);
const handleDeleteDevice = async (id: string) => {
if (loadingDeleteIds.includes(id)) return;
setLoadingDeleteIds((prev) => [...prev, id]);
try {
const { data } = await deleteSessions({ keys: [id] });
if (data.success) {
setDevices((prevDevices) => prevDevices.filter((d) => d.id !== id));
} else {
console.error('Delete failed:', data.message);
}
} catch (error: unknown) {
console.error('Delete error:', error);
} finally {
setLoadingDeleteIds((prev) =>
prev.filter((loadingId) => loadingId !== id),
);
}
};
const handleTerminateAllOtherSessions = () => {
const otherSessionKeys = devices.filter((d) => !d.current).map((d) => d.id);
if (otherSessionKeys.length > 0) {
executeTerminateAll({ keys: otherSessionKeys });
}
};
const getErrorMessage = (error: unknown): string | null => {
if (!error) return null;
if (error instanceof Error) return error.message;
return String(error);
};
return (
<PageWrapper>
<CardContainer
title={t('active.activeDevices')}
subtitle={t('active.activeDevicesCaption')}
action={
<Button
size="medium"
variant="outlined"
onClick={handleTerminateAllOtherSessions}
sx={{
borderRadius: 1,
borderColor: 'error.main',
color: 'error.main',
textTransform: 'none',
}}
disabled={isLoading || isTerminating}
>
{isTerminating
? t('active.deleting')
: t('active.deleteDevicesButton')}
</Button>
}
>
{isLoading ? (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
p: 4,
minHeight: '200px',
}}
>
<CircularProgress />
</Box>
) : fetchError ? (
<Box sx={{ textAlign: 'center', p: 4 }}>
<Typography color="error.main">
{getErrorMessage(fetchError)}
</Typography>
</Box>
) : (
<Box
sx={{
px: { xs: 2, sm: 3, md: 4 },
py: 2,
display: 'flex',
flexDirection: 'column',
}}
>
{devices.map((device) => (
<React.Fragment key={device.id}>
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', sm: 'row' },
alignItems: { xs: 'flex-start', sm: 'center' },
minHeight: 50,
py: 1.5,
}}
>
<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
sx={{
display: 'flex',
alignItems: 'center',
gap: 1,
width: '100%',
order: { xs: 2, sm: 2 },
}}
>
<Icon
Component={DeviceMessage}
size="medium"
color="primary.main"
/>
<Typography variant="body2" noWrap>
{device.deviceModel}
</Typography>
</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 },
minWidth: { sm: '138px' },
order: { xs: 4, sm: 4 },
alignItems: 'center',
justifyContent: 'center',
}}
>
{device.current && (
<Button
variant="outlined"
size="medium"
sx={{
borderRadius: 12.5,
border: '1px solid',
borderColor: 'success.main',
whiteSpace: 'nowrap',
color: 'success.main',
textTransform: 'none',
'&.Mui-disabled': {
color: 'success.main',
borderColor: 'success.main',
},
}}
disabled
>
{t('active.currentDevice')}
</Button>
)}
</Box>
<Box
sx={{
flexBasis: { xs: '100%', sm: 'auto' },
mb: { xs: 1, sm: 0 },
textAlign: { xs: 'left', sm: 'center' },
minWidth: { sm: '138px' },
order: { xs: 5, sm: 5 },
}}
>
<Button
size="small"
variant="outlined"
startIcon={<Icon Component={Logout} size="small" />}
disabled={
device.current || loadingDeleteIds.includes(device.id)
}
onClick={() => handleDeleteDevice(device.id)}
sx={{
color: 'error.main',
borderRadius: 1,
borderColor: 'error.main',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
whiteSpace: 'nowrap',
textTransform: 'none',
'& .MuiButton-startIcon': {
marginRight: 0.5,
marginLeft: 0,
},
}}
>
{loadingDeleteIds.includes(device.id) ? (
<CircularProgress size={20} color="error" />
) : (
t('active.deleteDevice')
)}
</Button>
</Box>
</Box>
{isXsup && (
<Box sx={{ borderBottom: 1, borderColor: 'divider' }} />
)}
</React.Fragment>
))}
</Box>
)}
</CardContainer>
</PageWrapper>
);
}

View File

@@ -11,13 +11,16 @@ import { useTranslation } from 'react-i18next';
import { CardContainer } from '@/components/CardContainer';
import { PageWrapper } from '../PageWrapper';
import { PasswordDialog } from './PasswordDialog';
import { regex } from '@/utils/regex';
import { useManualApi } from '@/hooks/useApi';
import { useApi } from '@/hooks/useApi';
import {
addPassword,
changePassword,
fetchProfile,
} from '../../api/settingsApi';
import { containsNumber } from '@/utils/regexes/containsNumber';
import { least8Chars } from '@/utils/regexes/least8Chars';
import { hasUpperAndLowerLetter } from '@/utils/regexes/hasUpperAndLowerLetter';
import { containsSymbol } from '@/utils/regexes/containsSymbol';
export function PasswordSecurity() {
const theme = useTheme();
@@ -29,36 +32,36 @@ export function PasswordSecurity() {
const [confirmPassword, setConfirmPassword] = useState('');
const [currentPassword, setCurrentPassword] = useState('');
const [showValidation, setShowValidation] = useState(false);
const [showPasswordAlert, setShowPasswordAlert] = useState(false);
const [changePasswordUI, setChangePasswordUI] = useState(false);
const { validPassword } = regex(password);
const hasNumber = containsNumber(password);
const hasMinLength = least8Chars(password);
const hasUpperAndLower = hasUpperAndLowerLetter(password);
const hasSpecialChar = containsSymbol(password);
const validPassword =
hasNumber && hasMinLength && hasUpperAndLower && hasSpecialChar;
const matchPassword = password === confirmPassword;
const {
data: profileData,
loading: isFetching,
error: fetchError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
} = useApi(fetchProfile, { immediate: true });
const {
data: addData,
loading: isAdding,
error: addError,
execute: executeAddPassword,
} = useManualApi(addPassword);
} = useApi(addPassword);
const {
data: changeData,
loading: isChanging,
error: changeError,
execute: executeChangePassword,
} = useManualApi(changePassword);
useEffect(() => {
executeFetchProfile();
}, []);
} = useApi(changePassword);
useEffect(() => {
if (profileData?.success) {
@@ -76,7 +79,6 @@ export function PasswordSecurity() {
useEffect(() => {
if (addData?.success || changeData?.success) {
setShowPasswordAlert(true);
if (!changePasswordUI) {
setChangePasswordUI(true);
}
@@ -90,14 +92,14 @@ export function PasswordSecurity() {
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const handlePasswordSubmit = () => {
const handlePasswordSubmit = async () => {
if (changePasswordUI) {
executeChangePassword({
await executeChangePassword({
oldPassword: currentPassword,
newPassword: password,
});
} else {
executeAddPassword({ password });
await executeAddPassword({ password });
}
};

View File

@@ -11,7 +11,7 @@ import { CardContainer } from '@/components/CardContainer';
import { PageWrapper } from '../PageWrapper';
import { fetchProfile } from '../../api/settingsApi';
import type { LoginLog } from '../../types/settingsApiType';
import { useManualApi } from '@/hooks/useApi';
import { useApi } from '@/hooks/useApi';
import { formatDate } from '@/utils/formatSessionDate';
export function RecentLogins() {
@@ -24,12 +24,7 @@ export function RecentLogins() {
data: profileData,
loading: isLoading,
error: fetchError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
useEffect(() => {
executeFetchProfile();
}, [i18n.language]);
} = useApi(fetchProfile, { immediate: true });
useEffect(() => {
if (profileData?.success && Array.isArray(profileData.loginLogs)) {

View File

@@ -1,316 +0,0 @@
import { useState, useEffect } from 'react';
import {
Box,
Typography,
Button,
useColorScheme,
Autocomplete,
TextField,
CircularProgress,
} from '@mui/material';
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';
import { useManualApi } from '@/hooks/useApi';
import { fetchProfile, saveSettings } from '../../api/settingsApi';
type ThemeMode = 'light' | 'dark';
type CalendarType = 'christian' | 'solar' | 'lunar';
interface SettingsState {
language: string;
calendar: CalendarType;
theme: ThemeMode;
}
const languageOptions = [
{ code: 'en', label: 'English', apiValue: 1 },
{ code: 'fa', label: 'فارسی', apiValue: 2 },
];
const calendarOptions: { key: CalendarType; apiValue: number }[] = [
{ key: 'christian', apiValue: 1 },
{ key: 'solar', apiValue: 2 },
{ key: 'lunar', apiValue: 3 },
];
const themeApiMap: Record<ThemeMode, number> = { light: 1, dark: 2 };
export function Setting() {
const { t, i18n } = useTranslation(['setting']);
const { mode, setMode } = useColorScheme();
const [savedSettings, setSavedSettings] = useState<SettingsState>({
language: i18n.language,
calendar: 'solar',
theme: mode === 'light' || mode === 'dark' ? mode : 'light',
});
const [draftSettings, setDraftSettings] =
useState<SettingsState>(savedSettings);
const [isEditing, setIsEditing] = useState(false);
const {
data: profileData,
loading: isFetching,
error: fetchError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
const {
data: saveData,
loading: isSaving,
error: saveError,
execute: executeSaveSettings,
} = useManualApi(saveSettings);
useEffect(() => {
executeFetchProfile();
}, []);
useEffect(() => {
if (profileData?.success && profileData.userSettings) {
const { theme, calendarType, language } = profileData.userSettings;
const themeReverseMap: { [key: number]: ThemeMode | undefined } = {
1: 'light',
2: 'dark',
};
const newSettings: SettingsState = {
theme: themeReverseMap[theme] || 'light',
calendar:
calendarOptions.find((c) => c.apiValue === calendarType)?.key ||
'solar',
language:
languageOptions.find((l) => l.apiValue === language)?.code || 'en',
};
setSavedSettings(newSettings);
setDraftSettings(newSettings);
setMode(newSettings.theme);
i18n.changeLanguage(newSettings.language);
}
}, [profileData, setMode, i18n]);
useEffect(() => {
if (saveData?.success) {
setMode(draftSettings.theme);
setSavedSettings(draftSettings);
i18n.changeLanguage(draftSettings.language);
setIsEditing(false);
}
}, [saveData, draftSettings, setMode, i18n]);
useEffect(() => {
if (isEditing) {
const resolvedMode = mode === 'light' || mode === 'dark' ? mode : 'light';
setDraftSettings({ ...savedSettings, theme: resolvedMode });
}
}, [isEditing, savedSettings, mode]);
const handleCancel = () => {
setIsEditing(false);
setDraftSettings(savedSettings);
setMode(savedSettings.theme);
};
const handleEditToggle = () => {
if (isEditing) {
const languageObj = languageOptions.find(
(o) => o.code === draftSettings.language,
);
const calendarObj = calendarOptions.find(
(c) => c.key === draftSettings.calendar,
);
if (languageObj && calendarObj) {
executeSaveSettings({
theme: themeApiMap[draftSettings.theme],
calendarType: calendarObj.apiValue,
language: languageObj.apiValue,
});
}
} else {
setIsEditing(true);
}
};
const getErrorMessage = (error: unknown): string | null => {
if (!error) return null;
if (error instanceof Error) return error.message;
return String(error);
};
return (
<PageWrapper>
<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',
fontSize: { xs: '0.85rem', sm: '1rem' },
}}
disabled={isSaving || isFetching}
>
{t('settings.rejectButton')}
</Button>
)}
<Button
onClick={handleEditToggle}
size="large"
variant={isEditing ? 'contained' : 'outlined'}
disabled={isSaving || isFetching}
>
{isSaving
? t('settings.saving')
: isEditing
? t('settings.saveButton')
: t('settings.editButton')}
</Button>
</Box>
}
>
{isFetching ? (
<Box
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
p: 4,
minHeight: '200px',
}}
>
<CircularProgress />
</Box>
) : fetchError ? (
<Box sx={{ textAlign: 'center', p: 4 }}>
<Typography color="error.main">
{getErrorMessage(fetchError)}
</Typography>
</Box>
) : (
<Box
sx={{
px: { xs: 2, sm: 3, md: 4 },
py: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
}}
>
{getErrorMessage(saveError) && (
<Typography color="error.main" variant="body2" mb={2}>
{getErrorMessage(saveError)}
</Typography>
)}
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', sm: 'row' },
gap: 4,
mt: 2,
}}
>
<Box sx={{ flex: 1 }}>
<Typography variant="caption" color="text.secondary">
{t('settings.theme')}
</Typography>
{isEditing ? (
<ThemeToggleButton
value={draftSettings.theme}
onChange={(newTheme) => {
setDraftSettings((prev) => ({
...prev,
theme: newTheme,
}));
}}
/>
) : (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Icon
Component={savedSettings.theme === 'light' ? Sun1 : Moon}
size="medium"
variant="Bold"
/>
<Typography variant="body1">
{t(`settings.${savedSettings.theme}`)}
</Typography>
</Box>
)}
</Box>
<Box sx={{ flex: 1 }}>
<Typography variant="caption" color="text.secondary">
{t('settings.language')}
</Typography>
{isEditing ? (
<Autocomplete
options={languageOptions}
getOptionLabel={(o) => o.label}
value={
languageOptions.find(
(o) => o.code === draftSettings.language,
) // ✅ FIX: Removed '|| null'
}
onChange={(_, v) =>
v &&
setDraftSettings((prev) => ({
...prev,
language: v.code,
}))
}
renderInput={(p) => <TextField {...p} />}
size="small"
fullWidth
disableClearable
/>
) : (
<Typography variant="body1">
{
languageOptions.find(
(o) => o.code === savedSettings.language,
)?.label
}
</Typography>
)}
</Box>
</Box>
<Box sx={{ mt: 2, width: { xs: '100%', sm: 'calc(50% - 16px)' } }}>
<Typography variant="caption" color="text.secondary">
{t('settings.calendar')}
</Typography>
{isEditing ? (
<Autocomplete
options={calendarOptions.map((c) => c.key)}
getOptionLabel={(key) => t(`settings.${key}`)}
value={draftSettings.calendar}
onChange={(_, v) =>
v && setDraftSettings((prev) => ({ ...prev, calendar: v }))
}
renderInput={(params) => <TextField {...params} />}
size="small"
fullWidth
disableClearable
/>
) : (
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
<Icon Component={Calendar1} size="medium" variant="Bold" />
<Typography variant="body1">
{t(`settings.${savedSettings.calendar}`)}
</Typography>
</Box>
)}
</Box>
</Box>
)}
</CardContainer>
</PageWrapper>
);
}

View File

@@ -6,7 +6,7 @@ import { ProfileImage } from './personalInformation/ProfileImage';
import { InfoRowDisplay } from './personalInformation/InfoRowDisplay';
import { InfoRowEdit } from './personalInformation/InfoRowEdit';
import { PageWrapper } from '../PageWrapper';
import { useManualApi } from '@/hooks/useApi';
import { useApi } from '@/hooks/useApi';
import { Gender, type InfoRowData } from '../../types/settingsType';
import { fetchProfile, saveProfile } from '../../api/settingsApi';
@@ -27,19 +27,14 @@ export function PersonalInformation() {
data: profileData,
loading: isLoadingProfile,
error: fetchProfileError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
} = useApi(fetchProfile, { immediate: true });
const {
data: saveData,
loading: isSavingProfile,
error: saveProfileError,
execute: executeSaveProfile,
} = useManualApi(saveProfile);
useEffect(() => {
executeFetchProfile();
}, []);
} = useApi(saveProfile);
useEffect(() => {
if (profileData?.success) {

View File

@@ -8,7 +8,7 @@ import PhoneEditForm from './phoneNumber/PhoneEditForm';
import PhoneActionButtons from './phoneNumber/PhoneActionButtons';
import { CircularProgress, Box, Typography } from '@mui/material';
import { toLocaleDigits } from '@/utils/persianDigit';
import { useManualApi } from '@/hooks/useApi';
import { useApi } from '@/hooks/useApi';
import {
fetchProfile,
sendVerificationCode,
@@ -39,35 +39,28 @@ export function PhoneNumber() {
data: profileData,
loading: isLoading,
error: fetchError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
} = useApi(fetchProfile, { immediate: true });
const {
data: sendCodeData,
loading: isSendingCode,
error: sendCodeError,
execute: executeSendCode,
} = useManualApi(sendVerificationCode);
} = useApi(sendVerificationCode);
const {
data: confirmData,
loading: isVerifying,
error: confirmError,
execute: executeConfirmCode,
} = useManualApi(confirmPhoneNumberCode);
} = useApi(confirmPhoneNumberCode);
const {
data: changePhoneData,
loading: isChangingPhone,
error: changePhoneError,
execute: executeChangePhone,
} = useManualApi(changePhoneNumber);
useEffect(() => {
if (!isEditing) {
executeFetchProfile();
}
}, [isEditing]);
} = useApi(changePhoneNumber);
useEffect(() => {
if (profileData?.success && profileData.phoneNumber) {

View File

@@ -8,7 +8,7 @@ import SocialMediaDialog from './socialMedia/SocialMediaDialog';
import useMediaQuery from '@mui/material/useMediaQuery';
import type { Theme } from '@mui/material/styles';
import { Box, CircularProgress, Typography } from '@mui/material';
import { useManualApi } from '@/hooks/useApi';
import { useApi } from '@/hooks/useApi';
import {
fetchProfile,
sendEmailCode,
@@ -33,29 +33,28 @@ export function SocialMedia() {
data: profileData,
loading: isFetching,
error: fetchError,
execute: executeFetchProfile,
} = useManualApi(fetchProfile);
} = useApi(fetchProfile, { immediate: true });
const {
data: sendCodeData,
loading: isSendingCode,
error: sendCodeError,
execute: executeSendCode,
} = useManualApi(sendEmailCode);
} = useApi(sendEmailCode);
const {
data: confirmData,
loading: isConfirming,
error: confirmError,
execute: executeConfirmCode,
} = useManualApi(confirmEmailCode);
} = useApi(confirmEmailCode);
const {
data: changeEmailData,
loading: isChangingEmail,
error: changeEmailError,
execute: executeChangeEmail,
} = useManualApi(changeEmail);
} = useApi(changeEmail);
const fullScreen = useMediaQuery((theme: Theme) =>
theme.breakpoints.down('sm'),
@@ -68,10 +67,6 @@ export function SocialMedia() {
| 'lg'
| 'xl';
useEffect(() => {
executeFetchProfile();
}, []);
useEffect(() => {
if (profileData?.success && profileData.email) {
const { email } = profileData;

View File

@@ -1,9 +1,9 @@
import { Box, Typography, Avatar } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { DisplayField } from './DisplayField';
import { CountryFlag } from '@/components/CountryFlag';
import { Gender } from '@/features/profile/types/settingsType';
import { type InfoRowDisplayProps } from '@/features/profile/types/settingsType';
import ReactCountryFlag from 'react-country-flag';
export function InfoRowDisplay({
data,
@@ -72,7 +72,17 @@ export function InfoRowDisplay({
</Typography>
<Box sx={{ mt: 0.5 }}>
{data.country ? (
<CountryFlag code={data.country} />
<ReactCountryFlag
countryCode={data.country}
svg
style={{
height: '1.5rem',
width: '1.5rem',
// TODO: Check alignment for better styling definition
marginTop: '-2px',
marginRight: '4px',
}}
/>
) : (
<Typography variant="body1" color="text.primary">
{t('settingForm.notDetermined')}

View File

@@ -8,10 +8,10 @@ import {
Autocomplete,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { countries } from '@/features/profile/data/countries';
import { CountryFlag } from '@/components/CountryFlag';
import { countries } from '@/data/countries';
import { Gender } from '@/features/profile/types/settingsType';
import { type InfoRowEditProps } from '@/features/profile/types/settingsType';
import ReactCountryFlag from 'react-country-flag';
export function InfoRowEdit({ data, setData }: InfoRowEditProps) {
const { t } = useTranslation(['countries', 'setting']);
@@ -101,7 +101,17 @@ export function InfoRowEdit({ data, setData }: InfoRowEditProps) {
}
renderOption={(props, option) => (
<Box component="li" {...props} key={option.code}>
<CountryFlag code={option.code} />
<ReactCountryFlag
countryCode={option.code}
svg
style={{
height: '1.5rem',
width: '1.5rem',
// TODO: Check alignment for better styling definition
marginTop: '-2px',
marginRight: '4px',
}}
/>
{option.label}
</Box>
)}