218 lines
7.7 KiB
TypeScript
218 lines
7.7 KiB
TypeScript
import Input from '@/components/Input'
|
||
import Select from '@/components/Select'
|
||
import Table from '@/components/Table'
|
||
import { ColumnType } from '@/components/types/TableTypes'
|
||
import { FC, useState } from 'react'
|
||
import { useTranslation } from 'react-i18next'
|
||
import Button from '@/components/Button'
|
||
import { TickCircle } from 'iconsax-react'
|
||
import { useForm } from 'react-hook-form'
|
||
import { AddressData, CreateAddressType } from './types/Types'
|
||
import { useGetDomains } from '../domain/hooks/useDomainData'
|
||
import { yupResolver } from "@hookform/resolvers/yup"
|
||
import * as yup from "yup"
|
||
import { useCreateAddress, useGetAddress } from './hooks/useAddressData'
|
||
import { toast } from '@/components/Toast'
|
||
import { ErrorType } from '@/helpers/types'
|
||
import ProgressBarEmail from './components/ProgressBarEmail'
|
||
import ToggleStatus from './components/ToggleStatus'
|
||
|
||
|
||
|
||
const Address: FC = () => {
|
||
const { t } = useTranslation()
|
||
|
||
const schema = yup.object().shape({
|
||
title: yup.string().required(t('errors.required')),
|
||
username: yup.string().required(t('errors.required')),
|
||
password: yup.string().required(t('errors.required')),
|
||
domainId: yup.string().required(t('errors.required')),
|
||
})
|
||
|
||
const [search, setSearch] = useState<string>('')
|
||
const [status, setStatus] = useState<string>('all')
|
||
|
||
const { data: domain } = useGetDomains()
|
||
const { mutate: createAddress, isPending } = useCreateAddress()
|
||
const { data: addresses, isPending: isPendingAddress } = useGetAddress(search, status)
|
||
const { register, handleSubmit, formState: { errors },
|
||
} = useForm<CreateAddressType>({
|
||
resolver: yupResolver(schema),
|
||
defaultValues: {
|
||
domainId: domain?.data?.domain?.id || '',
|
||
}
|
||
})
|
||
|
||
const columns: ColumnType<AddressData>[] = [
|
||
{
|
||
title: t('setting.address_title'),
|
||
key: 'title',
|
||
width: '200px'
|
||
},
|
||
{
|
||
title: t('setting.email'),
|
||
key: 'email',
|
||
width: '300px',
|
||
render: (item: AddressData) => (
|
||
<div key={item.id} className='dltr flex justify-end'>
|
||
{item.emailAddress}
|
||
</div>
|
||
)
|
||
},
|
||
{
|
||
title: t('setting.quota'),
|
||
key: 'quota',
|
||
width: '300px',
|
||
render: (item: AddressData) => {
|
||
|
||
return (
|
||
<ProgressBarEmail key={item.id} item={item} />
|
||
)
|
||
}
|
||
},
|
||
{
|
||
title: t('setting.status'),
|
||
key: 'status',
|
||
width: '120px',
|
||
align: 'center',
|
||
render: (item: AddressData) => (
|
||
<div key={item.id} className='dltr flex justify-end'>
|
||
<ToggleStatus defaultStatus={item.isActive} id={item.id} />
|
||
</div>
|
||
)
|
||
}
|
||
]
|
||
|
||
const statusOptions = [
|
||
{ value: 'all', label: 'همه' },
|
||
{ value: 'active', label: t('setting.active') },
|
||
{ value: 'inactive', label: t('setting.inactive') }
|
||
]
|
||
|
||
const onSubmit = (params: CreateAddressType) => {
|
||
createAddress(params, {
|
||
onSuccess: (data) => {
|
||
toast(data?.data?.message, 'success')
|
||
},
|
||
onError: (error: ErrorType) => {
|
||
toast(error.response?.data?.error?.message[0], 'error')
|
||
}
|
||
})
|
||
}
|
||
|
||
return (
|
||
<div className='flex xl:flex-row flex-col-reverse gap-8 mt-8'>
|
||
<div className='flex-1'>
|
||
<div className='flex gap-2 justify-between'>
|
||
<div>
|
||
<Select
|
||
placeholder={t('setting.status')}
|
||
items={statusOptions}
|
||
className='w-[120px]'
|
||
onChange={(e) => setStatus(e.target.value)}
|
||
/>
|
||
</div>
|
||
|
||
<div className='flex-1'>
|
||
<Input
|
||
variant='search'
|
||
placeholder={t('setting.search')}
|
||
className='xl:w-[300px] flex-1'
|
||
onChangeSearchFinal={(e) => setSearch(e)}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<Table
|
||
isLoading={isPendingAddress}
|
||
columns={columns}
|
||
data={addresses?.data?.users}
|
||
pagination={{
|
||
currentPage: 1,
|
||
totalPages: 6,
|
||
onPageChange: (page) => console.log('Page:', page)
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
<div className='xl:w-[350px] w-full bg-white rounded-4xl p-8'>
|
||
<div>
|
||
{t('setting.add_address')}
|
||
</div>
|
||
|
||
{/* <div className='mt-8 flex items-center justify-between'>
|
||
<div>
|
||
{t('setting.status')}
|
||
</div>
|
||
<div className='dltr pt-2'>
|
||
<Switch />
|
||
</div>
|
||
</div> */}
|
||
|
||
<div className='mt-6'>
|
||
<Input
|
||
label={t('setting.domain1')}
|
||
value={domain?.data?.domain?.name}
|
||
readOnly
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<Input
|
||
label={t('setting.title1')}
|
||
{...register('title')}
|
||
error_text={errors.title?.message}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-6 relative'>
|
||
<Input
|
||
label={t('setting.username')}
|
||
className='text-left'
|
||
{...register('username')}
|
||
error_text={errors.username?.message}
|
||
/>
|
||
<div className='absolute flex items-center dltr text-xs z-10 right-[1px] top-[29px] rounded-r-2.5 h-[38px] bg-[#EBEEF5] px-3'>
|
||
@ {domain?.data?.domain?.name}
|
||
</div>
|
||
</div>
|
||
|
||
<div className='mt-6'>
|
||
<Input
|
||
label={t('setting.password')}
|
||
type='password'
|
||
{...register('password')}
|
||
error_text={errors.password?.message}
|
||
/>
|
||
</div>
|
||
|
||
<div className='mt-2 text-xs'>
|
||
<div>رمز عبور میبایست:</div>
|
||
<ul className='list-disc pr-3 mt-1 flex flex-col gap-1'>
|
||
<li>حداقل ۸ کاراکتر باشد</li>
|
||
<li>ترکیبی از حروف کوچک و بزرگ باشد</li>
|
||
<li>شامل اعداد باشد</li>
|
||
<li>شامل کاراکتر های خاص (نماد ها) باشد</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div className='mt-9 flex justify-end'>
|
||
<Button
|
||
className='w-fit px-20'
|
||
onClick={handleSubmit(onSubmit)}
|
||
loading={isPending}
|
||
>
|
||
<div className='flex gap-2'>
|
||
<TickCircle size={20} color='white' />
|
||
<div>
|
||
{t('setting.create')}
|
||
</div>
|
||
</div>
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default Address |