import { Input, Select, Upload } from '@/components/ui' import Button from '@/components/ui/Button' import { FormContainer, FormItem } from '@/components/ui/Form' import Notification from '@/components/ui/Notification' import toast from '@/components/ui/toast' import { AVATAR_URL } from '@/constants/app.constant' import { useStoreActions, useStoreState } from '@/store' import { useLocalization } from '@/utils/hooks/useLocalization' import dayjs from 'dayjs' import { Field, Form, Formik } from 'formik' import { useEffect, useRef, useState } from 'react' import { CircleStencil, Cropper, CropperPreview, CropperPreviewRef, CropperRef, } from 'react-advanced-cropper' import 'react-advanced-cropper/dist/style.css' import { FaFacebookMessenger, FaEnvelope, FaTrashAlt, FaUserCircle, FaPhone, FaPlus, FaHome, FaUniversity, } from 'react-icons/fa' import * as Yup from 'yup' import isEmpty from 'lodash/isEmpty' import { ProfileDto, UpdateProfileDto } from '@/proxy/account/models' import { getProfile, updateProfile } from '@/services/account.service' import { CountryDto, getCountry } from '@/services/home.service' import { SelectBoxOption } from '@/types/shared' import { useSetting } from '@/utils/hooks/useSetting' const schema = Yup.object().shape({ name: Yup.string().min(3).max(50).required(), surname: Yup.string().min(3).max(50).required(), }) const General = () => { const [loading, setLoading] = useState(true) const [profileData, setProfileData] = useState() const [formData, setFormData] = useState() const [image, setImage] = useState() const [countries, setCountries] = useState([]) const auth = useStoreState((state) => state.auth) const { setUser } = useStoreActions((actions) => actions.auth.user) const { setting } = useSetting() const isEmailUpdateEnabled = setting('Abp.Identity.User.IsEmailUpdateEnabled') const { translate } = useLocalization() const cropperRef = useRef(null) const previewRef = useRef(null) const fetchData = async () => { setLoading(true) const [response, countryResponse] = await Promise.all([getProfile(), getCountry()]) setProfileData(response.data) setCountries(countryResponse.data) setImage(auth.user.avatar) setFormData({ name: response.data.name, surname: response.data.surname, }) setLoading(false) } useEffect(() => { if (isEmpty(profileData)) { fetchData() } }, []) const onChooseImage = async (file: File[]) => { if (file[0]) { setImage(URL.createObjectURL(file[0])) } else { setImage(undefined) } } const beforeUpload = (files: FileList | null, fileList: File[]) => { let valid: string | boolean = true const allowedFileType = ['image/jpeg', 'image/png', 'image/gif'] const maxFileSize = 2000000 if (fileList.length >= 1) { return `Sadece bir dosya seçebilirsiniz` } if (files) { for (const f of files) { if (!allowedFileType.includes(f.type)) { valid = '.jpg, .jpeg, .gif veya .png yükleyebilirsiniz' } else if (f.size >= maxFileSize) { valid = 'En fazla 2mb dosya yükleyebilirsiniz' } } } return valid } const onFormSubmit = async ( values: UpdateProfileDto, setSubmitting: (isSubmitting: boolean) => void, ) => { const avatar = await getCroppedAvatar() const resp = await updateProfile({ name: values.name, surname: values.surname, avatar: avatar ? new File([avatar], 'avatar') : undefined, }) if (resp.status === 200) { setUser({ ...auth.user, name: `${resp.data.name} ${resp.data.surname}`.trim(), avatar: AVATAR_URL(auth.user.id, auth.tenant.tenantId) + `?${dayjs().unix()}`, }) toast.push(, { placement: 'top-end', }) } else { toast.push(, { placement: 'top-end', }) } setSubmitting(false) } const getCroppedAvatar = () => new Promise((resolve, reject) => { const canvas = cropperRef.current?.getCanvas({ minHeight: 100, minWidth: 100, maxHeight: 300, maxWidth: 300, }) if (canvas) { canvas.toBlob((blob) => { if (blob) { resolve(blob) } else { reject() } }, 'image/jpeg') } else { resolve(null) } }) const getProfileExtraValue = (key: string) => { const extraProperties = profileData?.extraProperties const value = extraProperties?.[key] ?? extraProperties?.[`${key.charAt(0).toLowerCase()}${key.slice(1)}`] return typeof value === 'string' || typeof value === 'number' ? String(value) : undefined } const getSelectValue = (options: SelectBoxOption[], value?: string) => { if (!value) { return null } return options.find((option) => option.value === value) ?? { value, label: value } } const nationalityOptions: SelectBoxOption[] = countries.map((country) => ({ value: country.name, label: country.name, })) const educationOptions: SelectBoxOption[] = [ { value: 'İlkokul', label: translate('::App.EducationLevel.Primary') || 'İlkokul', }, { value: 'Ortaokul', label: translate('::App.EducationLevel.MiddleSchool') || 'Ortaokul', }, { value: 'Lise', label: translate('::App.EducationLevel.HighSchool') || 'Lise', }, { value: 'Ön Lisans', label: translate('::App.EducationLevel.Associate') || 'Ön Lisans', }, { value: 'Lisans', label: translate('::App.EducationLevel.Bachelor') || 'Lisans', }, { value: 'Yüksek Lisans', label: translate('::App.EducationLevel.Master') || 'Yüksek Lisans', }, { value: 'Doktora', label: translate('::App.EducationLevel.PhD') || 'Doktora', }, ] const bloodTypeOptions: SelectBoxOption[] = [ { value: 'A Rh+', label: 'A Rh+' }, { value: 'A Rh-', label: 'A Rh-' }, { value: 'B Rh+', label: 'B Rh+' }, { value: 'B Rh-', label: 'B Rh-' }, { value: 'AB Rh+', label: 'AB Rh+' }, { value: 'AB Rh-', label: 'AB Rh-' }, { value: '0 Rh+', label: '0 Rh+' }, { value: '0 Rh-', label: '0 Rh-' }, ] if (loading) { return <> } return ( { setSubmitting(true) onFormSubmit(values, setSubmitting) }} > {({ touched, errors, isSubmitting, resetForm }) => { return (
{translate('::Abp.Identity.User.UserInformation.ContactInformation')}
} value={profileData?.email} > } /> } /> } value={profileData?.phoneNumber} > } value={profileData?.extraProperties?.['RocketUsername'] as string | undefined} >
{translate('::Abp.Identity.User.UserInformation.AdditionalInformation')}
} value={getProfileExtraValue('HomeAddress')} > isDisabled options={nationalityOptions} value={getSelectValue( nationalityOptions, getProfileExtraValue('Nationality'), )} /> isDisabled options={educationOptions} value={getSelectValue( educationOptions, getProfileExtraValue('EducationLevel'), )} /> } value={getProfileExtraValue('GraduationSchool')} > isDisabled options={bloodTypeOptions} value={getSelectValue(bloodTypeOptions, getProfileExtraValue('BloodType'))} />
Avatar
{image ? ( { setTimeout(() => { previewRef.current?.update(cropper) }, 100) }} className="cropper max-h-[300px] max-w-[300px]" stencilComponent={CircleStencil} minHeight={100} minWidth={100} /> ) : ( )}
{image && ( )}
) }}
) } export default General