import { Button, Checkbox, DatePicker, FormContainer, FormItem, Input, Notification, Select, Tabs, toast, Upload, } from '@/components/ui' import Dialog from '@/components/ui/Dialog' import DateTimepicker from '@/components/ui/DatePicker/DateTimepicker' import Table from '@/components/ui/Table' import TBody from '@/components/ui/Table/TBody' import Td from '@/components/ui/Table/Td' import Th from '@/components/ui/Table/Th' import THead from '@/components/ui/Table/THead' import Tr from '@/components/ui/Table/Tr' import TabContent from '@/components/ui/Tabs/TabContent' import TabList from '@/components/ui/Tabs/TabList' import TabNav from '@/components/ui/Tabs/TabNav' import { deleteClaimUser, getUserDetail, postClaimUser, putUserDetail, putUserLookout, putUserPermission, } from '@/services/identity.service' import { updateProfile } from '@/services/account.service' import { CountryDto, getCountry } from '@/services/home.service' import { useLocalization } from '@/utils/hooks/useLocalization' import dayjs from 'dayjs' import { Field, FieldArray, FieldProps, Form, Formik, FormikHelpers } from 'formik' import { useEffect, useRef, useState } from 'react' import { Helmet } from 'react-helmet' import { FaBuilding, FaLockOpen, FaUser, FaFileAlt, FaTrashAlt, FaCheckCircle, FaUserAstronaut, FaEnvelope, FaPhone, FaUserCircle, FaFacebookMessenger, FaHome, FaUniversity, FaCalendarAlt, FaBriefcase, FaIdCard, FaMapMarkerAlt, FaCity, FaBook, FaHashtag, FaMapPin, FaUserTie, FaFemale, FaHeart, FaExclamationTriangle, FaUsers, FaPlus, } from 'react-icons/fa' import { CircleStencil, Cropper, CropperPreview, CropperPreviewRef, CropperRef, } from 'react-advanced-cropper' import 'react-advanced-cropper/dist/style.css' import { useParams } from 'react-router-dom' import * as Yup from 'yup' import { SelectBoxOption, SelectBoxOptionWithGroup } from '@/types/shared' import { AdaptableCard, ConfirmDialog, Container } from '@/components/shared' import { AssignedClaimViewModel, UserInfoViewModel } from '@/proxy/admin/models' import { APP_NAME, AVATAR_URL } from '@/constants/app.constant' import { useStoreActions, useStoreState } from '@/store' import { useSetting } from '@/utils/hooks/useSetting' export interface ClaimTypeDto { claimType: string claimValue: string } function UserDetails() { const { userId } = useParams() const { translate } = useLocalization() const [userDetails, setUserDetails] = useState() const [loading, setLoading] = useState(true) const [open, setOpen] = useState(false) const [confirmDeleteClaim, setConfirmDeleteClaim] = useState(null) const [countries, setCountries] = useState([]) const [image, setImage] = useState() const cropperRef = useRef(null) const previewRef = useRef(null) const auth = useStoreState((state) => state.auth) const { setUser } = useStoreActions((actions) => actions.auth.user) const { setting } = useSetting() const isEmailUpdateEnabled = setting('Abp.Identity.User.IsEmailUpdateEnabled') const isRequireVerifiedAccount = setting('Abp.Identity.Profile.General.RequireVerifiedAccount') const isRequireConfirmedEmail = setting('Abp.Identity.SignIn.RequireConfirmedEmail') const isRequireConfirmedPhoneNumber = setting('Abp.Identity.SignIn.RequireConfirmedPhoneNumber') const isTwoFactorEnabled = setting('Abp.Account.TwoFactor.Enabled') const getUser = async (syncAvatar = true) => { const { data } = await getUserDetail(userId || '') setUserDetails(data) if (syncAvatar) { setImage(`${AVATAR_URL(data.id, data.tenantId)}?${dayjs().unix()}`) } } useEffect(() => { getUser() getCountry().then(({ data }) => setCountries(data)) }, []) const scheme = Yup.object().shape({ claimType: Yup.string().required(), claimValue: Yup.string().required(), }) 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 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 handleSubmit = async ( values: ClaimTypeDto, { setSubmitting }: FormikHelpers, ) => { setLoading(true) setSubmitting(true) try { await postClaimUser({ userId, claimType: values.claimType, claimValue: values.claimValue }) toast.push( {translate('::Kaydet')} , { placement: 'top-end', }, ) setOpen(false) getUser() } catch (error) { toast.push( {'Hata'} , { placement: 'top-end', }, ) } finally { setLoading(false) setSubmitting(false) } } return userDetails ? ( <> }> {translate('::Abp.Identity.User.UserInformation')} }> {translate('::Abp.Identity.User.Permissions')} }> {translate('::Abp.Identity.User.WorkInformation')} }> {translate('::Abp.Identity.User.IndentityInformation')} }> {translate('::Abp.Identity.User.LockoutManagement')} }> {translate('::Abp.Identity.User.ClaimTypes')}
{ setSubmitting(true) await putUserDetail({ ...values }) let keepCurrentAvatar = false 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) { const avatarUrl = AVATAR_URL(auth.user.id, auth.tenant?.tenantId) + `?${dayjs().unix()}` setUser({ ...auth.user, name: `${resp.data.name} ${resp.data.surname}`.trim(), avatar: avatarUrl, }) setImage(avatarUrl) keepCurrentAvatar = true } else { toast.push(, { placement: 'top-end', }) } toast.push( {translate('::Kaydet')} , { placement: 'top-end', }, ) getUser(!keepCurrentAvatar) setSubmitting(false) }} > {({ isSubmitting, values }) => { return (
{/* Personal Information */}
{translate( '::Abp.Identity.User.UserInformation.ContactInformation', )}
} component={Input} /> } /> } /> } component={Input} /> } />
{translate( '::Abp.Identity.User.UserInformation.AdditionalInformation', )}
} /> {({ field, form }: FieldProps) => { const nationalityOptions: SelectBoxOption[] = countries.map( (c) => ({ value: c.name, label: c.name }), ) return ( o.value === values.educationLevel, )} onChange={(option) => form.setFieldValue(field.name, option?.value ?? null) } /> ) }} } /> {({ field, form }: FieldProps) => { 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-' }, ] return ( option.value === values.departmentId, )} onChange={(option) => { form.setFieldValue(field.name, option?.value) form.setFieldValue('jobPositionId', null) }} /> )}
{({ field, form }: FieldProps) => ( o.value === values.maritalStatus, )} onChange={(option) => form.setFieldValue(field.name, option?.value ?? null) } /> )}
{({ field, form }: FieldProps) => ( } onChange={(date) => { form.setFieldValue( field.name, date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null, ) }} /> )}
) }}
{ setSubmitting(true) await putUserLookout({ ...values }) toast.push( {translate('::Abp.Identity.User.SaveLockout')} , { placement: 'top-end', }, ) getUser() setSubmitting(false) }} > {({ isSubmitting, values }) => { const workHours = values.workHours const workHourOptions: SelectBoxOption[] = workHours.map((workHour) => ({ value: workHour.name, label: workHour.name, })) return (
{/* Account Status */}
{translate('::Abp.Identity.User.LockoutManagement.AccountStatus')}
{isRequireConfirmedEmail?.toLowerCase() === 'true' && ( )} {isRequireConfirmedPhoneNumber?.toLowerCase() === 'true' && ( )} {isTwoFactorEnabled?.toLowerCase() === 'true' && ( )}
{/* Login & Lockout Settings */}
{translate( '::Abp.Identity.User.LockoutManagement.LoginAndLockoutSettings', )}
{({ field, form }: FieldProps) => ( } onChange={(date) => { form.setFieldValue( field.name, date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null, ) }} disabled={values.lockoutEnabled === false} /> )} } />
{/* Login & Lockout Settings */}
{translate('::Abp.Identity.User.LockoutManagement.ConnectionsTimes')}
{({ field, form }: FieldProps) => ( } /> )} {({ field, form }: FieldProps) => ( } /> )}
) }}
{userDetails.claims.filter((a) => a.isAssigned === true) && userDetails.claims.filter((a) => a.isAssigned === true).length > 0 ? ( userDetails.claims.map((claim) => ( )) ) : ( )}
{translate('::Abp.Identity.User.ClaimType')} {translate('::Abp.Identity.User.ClaimValue')}
{claim.claimType} {claim.claimValue}
{translate('::Abp.Identity.User.NoClaimsFound')}
setOpen(false)} onRequestClose={() => setOpen(false)}> {({ touched, errors, values, isSubmitting }) => { const claimOptions: SelectBoxOption[] = userDetails?.claims.map((claim) => ({ value: claim.claimType, label: claim.claimType, })) return (
{({ field, form }: FieldProps) => (