113 lines
3.1 KiB
TypeScript
113 lines
3.1 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Box, Avatar, Typography, Button, IconButton } from '@mui/material';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { Camera, Trash } from 'iconsax-react';
|
|
import { Icon } from '@rkheftan/harmony-ui';
|
|
|
|
const MAX_FILE_SIZE_MB = 10;
|
|
|
|
interface ProfileImageProps {
|
|
initials: string;
|
|
uploadedImageUrl: string | null;
|
|
onImageChange: (file: File) => void;
|
|
onRemoveImage?: () => void;
|
|
}
|
|
|
|
export function ProfileImage({
|
|
initials,
|
|
uploadedImageUrl,
|
|
onImageChange,
|
|
onRemoveImage,
|
|
}: ProfileImageProps) {
|
|
const { t } = useTranslation('profileSetting');
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
|
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
setError(null);
|
|
const file = e.target.files?.[0];
|
|
if (!file) return;
|
|
|
|
const fileSizeMB = file.size / (1024 * 1024);
|
|
if (fileSizeMB > MAX_FILE_SIZE_MB) {
|
|
setError(t('settingForm.fileSizeError', { size: MAX_FILE_SIZE_MB }));
|
|
return;
|
|
}
|
|
|
|
onImageChange(file);
|
|
};
|
|
|
|
return (
|
|
<Box
|
|
sx={{ display: 'flex', alignItems: 'center', gap: 2, flexWrap: 'wrap' }}
|
|
>
|
|
<Avatar
|
|
sx={{
|
|
bgcolor: 'secondary.main',
|
|
width: 88,
|
|
height: 88,
|
|
fontSize: '20px',
|
|
}}
|
|
src={uploadedImageUrl || undefined}
|
|
>
|
|
{initials}
|
|
</Avatar>
|
|
<Box>
|
|
<Typography variant="body1">
|
|
{t('settingForm.profilePicture')}
|
|
</Typography>
|
|
<Typography variant="body2" color="text.secondary">
|
|
{t('settingForm.allowedFormat')}
|
|
</Typography>
|
|
{error && (
|
|
<Typography variant="body2" color="error" mt={1}>
|
|
{error}
|
|
</Typography>
|
|
)}
|
|
|
|
<Box mt={1} sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
<Button
|
|
variant={
|
|
uploadedImageUrl && onRemoveImage ? 'outlined' : 'contained'
|
|
}
|
|
component="label"
|
|
size="small"
|
|
sx={{
|
|
borderRadius: 2,
|
|
textTransform: 'none',
|
|
}}
|
|
startIcon={
|
|
<Icon
|
|
Component={Camera}
|
|
size="small"
|
|
color={
|
|
uploadedImageUrl && onRemoveImage ? 'primary.main' : 'white'
|
|
}
|
|
/>
|
|
}
|
|
>
|
|
{uploadedImageUrl && onRemoveImage
|
|
? t('settingForm.changePicture')
|
|
: t('settingForm.uploadPicture')}
|
|
<input
|
|
hidden
|
|
accept="image/png, image/jpeg, image/gif"
|
|
type="file"
|
|
onChange={handleImageChange}
|
|
/>
|
|
</Button>
|
|
{uploadedImageUrl && onRemoveImage && (
|
|
<IconButton
|
|
size="small"
|
|
color="error"
|
|
onClick={onRemoveImage}
|
|
aria-label={t('settingForm.removePicture')}
|
|
>
|
|
<Icon Component={Trash} color="error.main" />
|
|
</IconButton>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
</Box>
|
|
);
|
|
}
|