sozsoft-platform/ui/src/views/admin/user-management/Details.tsx

1520 lines
67 KiB
TypeScript
Raw Normal View History

2026-02-24 20:44:16 +00:00
import {
Button,
Checkbox,
DatePicker,
FormContainer,
FormItem,
Input,
Notification,
Select,
Tabs,
toast,
} 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,
2026-02-24 20:44:16 +00:00
} from '@/services/identity.service'
import { CountryDto, getCountry } from '@/services/home.service'
2026-02-24 20:44:16 +00:00
import { useLocalization } from '@/utils/hooks/useLocalization'
import dayjs from 'dayjs'
import { Field, FieldArray, FieldProps, Form, Formik, FormikHelpers } from 'formik'
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import {
FaBuilding,
FaLockOpen,
FaUser,
FaFileAlt,
FaTrashAlt,
FaCheckCircle,
FaUserAstronaut,
} from 'react-icons/fa'
2026-02-24 20:44:16 +00:00
import { useParams } from 'react-router-dom'
import * as Yup from 'yup'
import { SelectBoxOption, SelectBoxOptionWithGroup } from '@/types/shared'
2026-02-24 20:44:16 +00:00
import { ConfirmDialog, Container } from '@/components/shared'
import { AssignedClaimViewModel, UserInfoViewModel } from '@/proxy/admin/models'
import { APP_NAME } from '@/constants/app.constant'
export interface ClaimTypeDto {
claimType: string
claimValue: string
}
function UserDetails() {
const { userId } = useParams()
const { translate } = useLocalization()
const [userDetails, setUserDetails] = useState<UserInfoViewModel>()
const [loading, setLoading] = useState(true)
const [open, setOpen] = useState(false)
const [confirmDeleteClaim, setConfirmDeleteClaim] = useState<AssignedClaimViewModel | null>(null)
const [countries, setCountries] = useState<CountryDto[]>([])
2026-02-24 20:44:16 +00:00
const getUser = async () => {
const { data } = await getUserDetail(userId || '')
setUserDetails(data)
}
useEffect(() => {
getUser()
getCountry().then(({ data }) => setCountries(data))
2026-02-24 20:44:16 +00:00
}, [])
const scheme = Yup.object().shape({
claimType: Yup.string().required(),
claimValue: Yup.string().required(),
})
const handleSubmit = async (
values: ClaimTypeDto,
{ setSubmitting }: FormikHelpers<ClaimTypeDto>,
) => {
setLoading(true)
setSubmitting(true)
try {
await postClaimUser({ userId, claimType: values.claimType, claimValue: values.claimValue })
toast.push(
<Notification type="success" duration={2000}>
{translate('::Kaydet')}
</Notification>,
{
placement: 'top-end',
},
)
setOpen(false)
getUser()
} catch (error) {
toast.push(
<Notification type="danger" duration={2000}>
{'Hata'}
</Notification>,
{
placement: 'top-end',
},
)
} finally {
setLoading(false)
setSubmitting(false)
}
}
return userDetails ? (
<>
<Helmet
titleTemplate={`%s | ${APP_NAME}`}
title={userDetails.email}
defaultTitle={APP_NAME}
></Helmet>
<Container>
<Tabs defaultValue="user">
<TabList>
<TabNav value="user" icon={<FaUser />}>
{translate('::Abp.Identity.User.UserInformation')}
</TabNav>
<TabNav value="permission" icon={<FaCheckCircle />}>
{translate('::Abp.Identity.User.Permissions')}
</TabNav>
<TabNav value="work" icon={<FaBuilding />}>
{translate('::Abp.Identity.User.WorkInformation')}
</TabNav>
<TabNav value="identity" icon={<FaUserAstronaut />}>
{translate('::Abp.Identity.User.IndentityInformation')}
</TabNav>
2026-02-24 20:44:16 +00:00
<TabNav value="lockout" icon={<FaLockOpen />}>
{translate('::Abp.Identity.User.LockoutManagement')}
</TabNav>
<TabNav value="claimTypes" icon={<FaFileAlt />}>
{translate('::Abp.Identity.User.ClaimTypes')}
</TabNav>
</TabList>
<TabContent value="user">
<div className="mt-5">
<Formik
initialValues={userDetails}
onSubmit={async (values, { resetForm, setSubmitting }) => {
setSubmitting(true)
await putUserDetail({ ...values })
toast.push(
<Notification type="success" duration={2000}>
{translate('::Kaydet')}
2026-02-24 20:44:16 +00:00
</Notification>,
{
placement: 'top-end',
},
)
getUser()
setSubmitting(false)
}}
>
2026-04-26 19:05:19 +00:00
{({ isSubmitting, values }) => {
2026-02-24 20:44:16 +00:00
return (
<Form>
2026-05-25 09:14:42 +00:00
<div>
2026-02-24 20:44:16 +00:00
<FormContainer size="md">
2026-05-25 09:14:42 +00:00
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2 w-full">
2026-02-24 20:44:16 +00:00
{/* Personal Information */}
<div>
2026-05-25 09:14:42 +00:00
<h6 className="mb-4">
{translate(
'::Abp.Identity.User.UserInformation.ContactInformation',
)}
</h6>
2026-02-24 20:44:16 +00:00
<FormItem
label={translate('::Abp.Identity.User.UserInformation.Name')}
>
<Field
type="text"
name="name"
placeholder="Name"
component={Input}
/>
</FormItem>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.Surname')}
>
<Field
type="text"
name="surname"
placeholder="Surname"
component={Input}
/>
</FormItem>
2026-04-26 19:05:19 +00:00
<FormItem label={translate('::Abp.Account.EmailAddress')}>
2026-02-24 20:44:16 +00:00
<Field
type="text"
disabled
name="email"
placeholder="Email Address"
component={Input}
/>
</FormItem>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.PhoneNumber')}
>
<Field
type="text"
name="phoneNumber"
2026-04-26 19:05:19 +00:00
placeholder={translate(
'::Abp.Identity.User.UserInformation.PhoneNumber',
)}
2026-02-24 20:44:16 +00:00
component={Input}
/>
</FormItem>
2026-05-25 09:14:42 +00:00
</div>
<div>
<h6 className="mb-4">&nbsp;</h6>
<FormItem label={translate('::Abp.Account.HomeAddress')}>
<Field
type="text"
name="homeAddress"
placeholder={translate('::Abp.Account.HomeAddress')}
component={Input}
/>
</FormItem>
<FormItem size="sm" label={translate('::RocketUsername')}>
2026-02-24 20:44:16 +00:00
<Field
type="text"
name="rocketUsername"
placeholder={translate('::RocketUsername')}
component={Input}
/>
</FormItem>
</div>
<div>
<h6 className="mb-4">
{translate(
'::Abp.Identity.User.UserInformation.AdditionalInformation',
)}
</h6>
<FormItem label={translate('::Abp.Account.Nationality')}>
<Field type="text" name="nationality">
{({ field, form }: FieldProps<SelectBoxOption>) => {
const nationalityOptions: SelectBoxOption[] = countries.map(
(c) => ({ value: c.name, label: c.name }),
)
return (
<Select
field={field}
form={form}
options={nationalityOptions}
isClearable={true}
value={nationalityOptions.filter(
(o) => o.value === values.nationality,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value ?? null)
}
/>
)
}}
</Field>
</FormItem>
<FormItem label={translate('::Abp.Account.EducationLevel')}>
<Field type="text" name="educationLevel">
{({ field, form }: FieldProps<SelectBoxOption>) => {
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',
},
]
return (
<Select
field={field}
form={form}
options={educationOptions}
isClearable={true}
value={educationOptions.filter(
(o) => o.value === values.educationLevel,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value ?? null)
}
/>
)
}}
</Field>
</FormItem>
<FormItem label={translate('::Abp.Account.GraduationSchool')}>
<Field
type="text"
name="graduationSchool"
placeholder={translate('::GraduationSchool')}
component={Input}
/>
</FormItem>
<FormItem label={translate('::Abp.Account.BloodType')}>
<Field type="text" name="bloodType">
{({ field, form }: FieldProps<SelectBoxOption>) => {
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 (
<Select
field={field}
form={form}
options={bloodTypeOptions}
isClearable={true}
value={bloodTypeOptions.filter(
(o) => o.value === values.bloodType,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value ?? null)
}
/>
)
}}
</Field>
</FormItem>
</div>
2026-02-24 20:44:16 +00:00
<div>
<h6 className="mb-4">
{translate('::Abp.Identity.User.UserInformation.AccountTimestamps')}
</h6>
<FormItem
label={translate(
'::Abp.Identity.User.UserInformation.PasswordChangeTime',
)}
>
<Field name="lastPasswordChangeTime">
{({ field, form }: FieldProps) => (
<DateTimepicker
inputFormat="DD/MM/YYYY HH:mm"
2026-02-24 20:44:16 +00:00
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
placeholder="Select Date"
onChange={(date: any) => {
form.setFieldValue(
field.name,
2026-04-26 19:05:19 +00:00
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
2026-02-24 20:44:16 +00:00
)
}}
/>
)}
</Field>
</FormItem>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.CreateTime')}
>
<Field name="creationTime">
{({ field, form }: FieldProps) => (
<Input
field={field}
form={form}
value={
field.value
? dayjs(field.value).format('DD/MM/YYYY HH:mm')
: undefined
2026-02-24 20:44:16 +00:00
}
disabled
/>
)}
</Field>
</FormItem>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.UpdateTime')}
>
<Field name="lastModificationTime">
{({ field, form }: FieldProps) => (
<Input
field={field}
form={form}
value={
field.value
? dayjs(field.value).format('DD/MM/YYYY HH:mm')
: undefined
2026-02-24 20:44:16 +00:00
}
disabled
/>
)}
</Field>
</FormItem>
</div>
</div>
</FormContainer>
</div>
2026-05-25 09:14:42 +00:00
<Button variant="solid" block loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
2026-02-24 20:44:16 +00:00
</Form>
)
}}
</Formik>
</div>
</TabContent>
<TabContent value="permission">
<div className="mt-5">
<Formik
initialValues={userDetails}
onSubmit={async (values, { setSubmitting }) => {
setSubmitting(true)
await putUserPermission({ ...values })
toast.push(
<Notification type="success" duration={2000}>
{translate('::Abp.Identity.User.SavePermission')}
</Notification>,
{
placement: 'top-end',
},
)
getUser()
setSubmitting(false)
}}
>
{({ isSubmitting, values }) => {
const roles = values.roles
const branches = values.branches
return (
<Form>
2026-05-25 09:14:42 +00:00
<div>
<FormContainer size="md">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 w-full">
{/* Şube Management */}
<div>
<h6 className="mb-4">
{translate('::Abp.Identity.User.UserInformation.BranchManagement')}
</h6>
<div className="border-2 rounded-lg p-4">
<FieldArray name="branches">
{({ form, remove, push }) => (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 text-center">
{branches && branches.length > 0
? branches.map((_, index: number) => (
<div key={index} className="p-2">
<FormItem
labelClass="block text-center"
className="mb-0 justify-center"
label={branches[index].name}
>
<Field
className="mr-0"
name={`branches[${index}].isAssigned`}
component={Checkbox}
/>
</FormItem>
</div>
))
: null}
</div>
)}
</FieldArray>
</div>
</div>
{/* Role Management */}
<div>
<h6 className="mb-4">
{translate('::Abp.Identity.User.UserInformation.RoleManagement')}
</h6>
<div className="border-2 rounded-lg p-4">
<FieldArray name="roles">
{({ form, remove, push }) => (
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-2 text-center">
{roles && roles.length > 0
? roles.map((_, index: number) => (
<div key={index} className="p-2">
<FormItem
labelClass="block text-center"
className="mb-0 justify-center"
label={roles[index].name}
>
<Field
className="mr-0"
name={`roles[${index}].isAssigned`}
component={Checkbox}
/>
</FormItem>
</div>
))
: null}
</div>
)}
</FieldArray>
</div>
</div>
</div>
</FormContainer>
</div>
2026-05-25 09:14:42 +00:00
<div className="mt-4">
<Button variant="solid" block loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</div>
</Form>
)
}}
</Formik>
</div>
</TabContent>
<TabContent value="work">
<div className="mt-5">
<Formik
initialValues={userDetails}
onSubmit={async (values, { resetForm, setSubmitting }) => {
setSubmitting(true)
await putUserDetail({ ...values })
toast.push(
<Notification type="success" duration={2000}>
{translate('::Kaydet')}
</Notification>,
{
placement: 'top-end',
},
)
getUser()
setSubmitting(false)
}}
>
{({ isSubmitting, values }) => {
const departments = values.departments
const jobPositions = values.jobPositions
const departmentOptions: SelectBoxOption[] = departments.map((department) => ({
value: department.id,
label: department.name,
}))
const jobPositionOptions: SelectBoxOptionWithGroup[] = jobPositions.map(
(jobPosition) => ({
value: jobPosition.id,
label: jobPosition.name,
group: jobPosition.departmentId,
}),
)
return (
<Form>
2026-05-25 09:14:42 +00:00
<div>
<FormContainer size="md">
2026-05-25 09:14:42 +00:00
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2 w-full">
<div>
<FormItem
label={translate(
'::Abp.Identity.User.UserInformation.DepartmentId',
)}
>
<Field type="text" name="departmentId">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={departmentOptions}
isClearable={true}
value={departmentOptions.filter(
(option) => option.value === values.departmentId,
)}
onChange={(option) => {
form.setFieldValue(field.name, option?.value)
form.setFieldValue('jobPositionId', null)
}}
/>
)}
</Field>
</FormItem>
</div>
<div>
<FormItem
label={translate(
'::Abp.Identity.User.UserInformation.JobPositionId',
)}
>
<Field type="text" name="jobPositionId">
{({ field, form }: FieldProps<SelectBoxOptionWithGroup>) => (
<Select
field={field}
form={form}
options={jobPositionOptions.filter(
(option) => option.group === values.departmentId,
)}
isClearable={true}
value={jobPositionOptions.filter(
(option) => option.value === values.jobPositionId,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/>
)}
</Field>
</FormItem>
</div>
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.SskNo')}
>
<Field
type="text"
name="sskNo"
2026-05-25 09:14:42 +00:00
placeholder={translate(
'::Abp.Identity.User.UserInformation.SskNo',
)}
component={Input}
/>
</FormItem>
</div>
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.HireDate')}
>
<Field name="hireDate">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
2026-05-25 09:14:42 +00:00
placeholder={translate(
'::Abp.Identity.User.UserInformation.HireDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
/>
)}
</Field>
</FormItem>
</div>
<div>
<FormItem
2026-05-25 09:14:42 +00:00
label={translate(
'::Abp.Identity.User.UserInformation.TerminationDate',
)}
>
<Field name="terminationDate">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
2026-05-25 09:14:42 +00:00
placeholder={translate(
'::Abp.Identity.User.UserInformation.TerminationDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
/>
)}
</Field>
</FormItem>
</div>
</div>
</FormContainer>
</div>
2026-05-25 09:14:42 +00:00
<Button variant="solid" block loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</Form>
)
}}
</Formik>
</div>
</TabContent>
<TabContent value="identity">
<div className="mt-5">
<Formik
initialValues={userDetails}
onSubmit={async (values, { resetForm, setSubmitting }) => {
setSubmitting(true)
await putUserDetail({ ...values })
toast.push(
<Notification type="success" duration={2000}>
{translate('::Kaydet')}
</Notification>,
{
placement: 'top-end',
},
)
getUser()
setSubmitting(false)
}}
>
{({ isSubmitting, values }) => {
const maritalStatusOptions: SelectBoxOption[] = [
{
value: 'Bekar',
label: translate('::App.MaritalStatus.Single') || 'Bekar',
},
{
value: 'Evli',
label: translate('::App.MaritalStatus.Married') || 'Evli',
},
{
value: 'Boşanmış',
label: translate('::App.MaritalStatus.Divorced') || 'Boşanmış',
},
{
value: 'Dul',
label: translate('::App.MaritalStatus.Widowed') || 'Dul',
},
]
return (
<Form>
2026-05-25 09:14:42 +00:00
<FormContainer size="md">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2 w-full">
<div>
<FormItem
label={translate(
'::Abp.Identity.User.UserInformation.IdentityNumber',
)}
>
<Field
type="text"
name="identityNumber"
placeholder={translate(
'::Abp.Identity.User.UserInformation.IdentityNumber',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.SerialNo')}
>
<Field
type="text"
name="serialNo"
placeholder={translate(
'::Abp.Identity.User.UserInformation.SerialNo',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.Province')}
>
<Field
type="text"
name="province"
placeholder={translate(
'::Abp.Identity.User.UserInformation.Province',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.District')}
>
<Field
type="text"
name="district"
placeholder={translate(
'::Abp.Identity.User.UserInformation.District',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.Village')}
>
<Field
type="text"
name="village"
placeholder={translate(
'::Abp.Identity.User.UserInformation.Village',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.VolumeNo')}
>
<Field
type="text"
name="volumeNo"
placeholder={translate(
'::Abp.Identity.User.UserInformation.VolumeNo',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate(
'::Abp.Identity.User.UserInformation.FamilySequenceNo',
)}
>
<Field
type="text"
name="familySequenceNo"
placeholder={translate(
'::Abp.Identity.User.UserInformation.FamilySequenceNo',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.SequenceNo')}
>
<Field
type="text"
name="sequenceNo"
placeholder={translate(
'::Abp.Identity.User.UserInformation.SequenceNo',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.IssuedPlace')}
>
<Field
type="text"
name="issuedPlace"
placeholder={translate(
'::Abp.Identity.User.UserInformation.IssuedPlace',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.IssuedDate')}
>
<Field name="issuedDate">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
placeholder={translate(
'::Abp.Identity.User.UserInformation.IssuedDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
/>
)}
</Field>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.BirthPlace')}
>
<Field
type="text"
name="birthPlace"
placeholder={translate(
'::Abp.Identity.User.UserInformation.BirthPlace',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.BirthDate')}
>
<Field name="birthDate">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
placeholder={translate(
'::Abp.Identity.User.UserInformation.BirthDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
/>
)}
</Field>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.FatherName')}
>
<Field
type="text"
name="fatherName"
placeholder={translate(
'::Abp.Identity.User.UserInformation.FatherName',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.MotherName')}
>
<Field
type="text"
name="motherName"
placeholder={translate(
'::Abp.Identity.User.UserInformation.MotherName',
)}
component={Input}
/>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.MaritalStatus')}
>
<Field type="text" name="maritalStatus">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={maritalStatusOptions}
isClearable={true}
value={maritalStatusOptions.filter(
(o) => o.value === values.maritalStatus,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value ?? null)
}
/>
)}
</Field>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
<div>
<FormItem
label={translate('::Abp.Identity.User.UserInformation.MarriageDate')}
>
<Field name="marriageDate">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
placeholder={translate(
'::Abp.Identity.User.UserInformation.MarriageDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
/>
)}
</Field>
</FormItem>
</div>
2026-05-25 09:14:42 +00:00
</div>
</FormContainer>
2026-05-25 09:14:42 +00:00
<Button variant="solid" block loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
</Form>
)
}}
</Formik>
</div>
</TabContent>
2026-02-24 20:44:16 +00:00
<TabContent value="lockout">
<div className="mt-5">
<Formik
initialValues={userDetails}
onSubmit={async (values, { setSubmitting }) => {
setSubmitting(true)
await putUserLookout({ ...values })
toast.push(
<Notification type="success" duration={2000}>
{translate('::Abp.Identity.User.SaveLockout')}
2026-02-24 20:44:16 +00:00
</Notification>,
{
placement: 'top-end',
},
)
getUser()
setSubmitting(false)
}}
>
2026-04-26 19:05:19 +00:00
{({ isSubmitting, values }) => {
const workHours = values.workHours
const workHourOptions: SelectBoxOption[] = workHours.map((workHour) => ({
value: workHour.name,
label: workHour.name,
}))
2026-02-24 20:44:16 +00:00
return (
<Form>
2026-05-25 09:14:42 +00:00
<FormContainer size="md">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-2 w-full">
{/* Account Status */}
<div>
<h6 className="mb-4">
{translate('::Abp.Identity.User.LockoutManagement.AccountStatus')}
</h6>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate('::Abp.Identity.User.LockoutManagement.Status')}
>
<Field
name="isActive"
placeholder={translate(
'::Abp.Identity.User.LockoutManagement.Status',
)}
component={Checkbox}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.AdminVerification',
)}
>
<Field
name="isVerified"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.AdminVerification',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.EmailConfirmed',
)}
>
<Field
name="emailConfirmed"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.EmailConfirmed',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.PhoneNumberConfirmed',
)}
>
<Field
name="phoneNumberConfirmed"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.PhoneNumberConfirmed',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.TwoFactorEnabled',
)}
>
<Field
name="twoFactorEnabled"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.TwoFactorEnabled',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
/>
</FormItem>
</div>
2026-02-24 20:44:16 +00:00
2026-05-25 09:14:42 +00:00
{/* Login & Lockout Settings */}
<div>
<h6 className="mb-4">
{translate(
'::Abp.Identity.User.LockoutManagement.LoginAndLockoutSettings',
)}
</h6>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.AccountLockoutEnabled',
)}
>
<Field
name="lockoutEnabled"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.AccountLockoutEnabled',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.AccountLocked',
)}
>
<Field
name="lockUser"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.AccountLocked',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
disabled={values.lockoutEnabled === false}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.AccountEndDate',
)}
>
<Field name="lockoutEnd">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
placeholder={translate(
'::Abp.Identity.User.LockoutManagement.AccountEndDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
disabled={values.lockoutEnabled === false}
/>
2026-02-24 20:44:16 +00:00
)}
2026-05-25 09:14:42 +00:00
</Field>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.ShouldChangePwOnNextLogin',
)}
>
<Field
name="shouldChangePasswordOnNextLogin"
placeholder={translate(
2026-02-24 20:44:16 +00:00
'::Abp.Identity.User.LockoutManagement.ShouldChangePwOnNextLogin',
)}
2026-05-25 09:14:42 +00:00
component={Checkbox}
/>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.AccessFailedCount',
)}
>
<Field type="number" name="accessFailedCount" component={Input} />
</FormItem>
</div>
2026-02-24 20:44:16 +00:00
2026-05-25 09:14:42 +00:00
{/* Login & Lockout Settings */}
<div>
<h6 className="mb-4">
{translate('::Abp.Identity.User.LockoutManagement.ConnectionsTimes')}
</h6>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate('::Abp.Identity.User.LockoutManagement.WorkHour')}
>
<Field type="text" name="workHour">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={workHourOptions}
isClearable={true}
value={workHourOptions.filter(
(option) => option.value === values.workHour,
)}
onChange={(option) =>
form.setFieldValue(field.name, option?.value)
}
/>
2026-02-24 20:44:16 +00:00
)}
2026-05-25 09:14:42 +00:00
</Field>
</FormItem>
<FormItem
layout="horizontal"
labelClass="!justify-start"
labelWidth="50%"
label={translate(
'::Abp.Identity.User.LockoutManagement.LoginEndDate',
)}
>
<Field name="loginEndDate">
{({ field, form }: FieldProps) => (
<DatePicker
field={field}
form={form}
value={field.value ? dayjs(field.value).toDate() : null}
placeholder={translate(
'::Abp.Identity.User.LockoutManagement.LoginEndDate',
)}
onChange={(date) => {
form.setFieldValue(
field.name,
date ? dayjs(date).format('YYYY-MM-DDTHH:mm:ss') : null,
)
}}
/>
)}
</Field>
</FormItem>
2026-02-24 20:44:16 +00:00
</div>
2026-05-25 09:14:42 +00:00
</div>
</FormContainer>
2026-02-24 20:44:16 +00:00
2026-05-25 09:14:42 +00:00
<Button variant="solid" block loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
2026-02-24 20:44:16 +00:00
</Form>
)
}}
</Formik>
</div>
</TabContent>
2026-02-24 20:44:16 +00:00
<TabContent value="claimTypes">
2026-05-25 09:14:42 +00:00
<div className="mt-5">
2026-02-24 20:44:16 +00:00
<Table compact>
<THead>
<Tr>
<Th className="text-center">
<Button
shape="circle"
variant="plain"
type="button"
size="sm"
2026-02-24 20:44:16 +00:00
title="Add"
icon={<FaFileAlt />}
onClick={async (e) => {
setOpen(true)
}}
/>
</Th>
<Th>{translate('::Abp.Identity.User.ClaimType')}</Th>
<Th>{translate('::Abp.Identity.User.ClaimValue')}</Th>
</Tr>
</THead>
<TBody>
{userDetails.claims.filter((a) => a.isAssigned === true) &&
userDetails.claims.filter((a) => a.isAssigned === true).length > 0 ? (
userDetails.claims.map((claim) => (
<Tr key={claim.id}>
<Td>
<Button
shape="circle"
variant="plain"
type="button"
size="sm"
2026-02-24 20:44:16 +00:00
title="Delete"
icon={<FaTrashAlt />}
onClick={() => setConfirmDeleteClaim(claim)}
/>
</Td>
<Td>{claim.claimType}</Td>
<Td>{claim.claimValue}</Td>
</Tr>
))
) : (
<Tr>
<Td colSpan={3} className="text-center">
{translate('::Abp.Identity.User.NoClaimsFound')}
</Td>
</Tr>
)}
</TBody>
</Table>
</div>
</TabContent>
</Tabs>
</Container>
<Dialog isOpen={open} onClose={() => setOpen(false)} onRequestClose={() => setOpen(false)}>
<Formik
initialValues={{ claimType: '', claimValue: '' }}
validationSchema={scheme}
onSubmit={handleSubmit}
>
{({ touched, errors, values, isSubmitting }) => {
const claimOptions: SelectBoxOption[] = userDetails?.claims.map((claim) => ({
value: claim.claimType,
label: claim.claimType,
}))
return (
<Form>
<FormContainer size="sm">
<FormItem
label={translate('::Abp.Identity.User.ClaimType')}
invalid={errors.claimType && touched.claimType}
errorMessage={errors.claimType}
>
<Field type="text" name="claimType">
{({ field, form }: FieldProps<SelectBoxOption>) => (
<Select
field={field}
form={form}
options={claimOptions}
isClearable={true}
value={claimOptions.filter((option) => option.value === values.claimType)}
onChange={(option) => form.setFieldValue(field.name, option?.value)}
/>
)}
</Field>
</FormItem>
<FormItem
label={translate('::Abp.Identity.User.ClaimValue')}
invalid={errors.claimValue && touched.claimValue}
errorMessage={errors.claimValue}
>
<Field type="text" autoComplete="off" name="claimValue" component={Input} />
</FormItem>
<div className="mt-6 flex flex-row justify-end gap-3">
<Button variant="solid" loading={isSubmitting} type="submit">
{isSubmitting ? translate('::SavingWithThreeDot') : translate('::Save')}
</Button>
<Button type="button" variant="plain" onClick={() => setOpen(false)}>
{translate('::Cancel')}
</Button>
</div>
</FormContainer>
</Form>
)
}}
</Formik>
</Dialog>
<ConfirmDialog
isOpen={!!confirmDeleteClaim}
type="danger"
title={translate('::DeleteConfirmation')}
confirmText={translate('::Delete')}
cancelText={translate('::Cancel')}
confirmButtonColor="red-600"
onCancel={() => setConfirmDeleteClaim(null)}
onConfirm={async () => {
if (confirmDeleteClaim) {
await deleteClaimUser(confirmDeleteClaim.id, userId)
toast.push(
<Notification type="success" duration={2000}>
{translate('::Abp.Identity.User.ClaimDeleted')}
</Notification>,
{ placement: 'top-end' },
)
setConfirmDeleteClaim(null)
getUser()
}
}}
>
<p>
<span className="font-semibold">{confirmDeleteClaim?.claimType}</span> claim silmek
istediğinize emin misiniz?
</p>
</ConfirmDialog>
</>
) : (
<></>
)
}
export default UserDetails