2025-06-16 09:06:54 +00:00
|
|
|
import { cloneElement, useMemo } from 'react'
|
2025-05-06 06:45:49 +00:00
|
|
|
import Container from '@/components/shared/Container'
|
|
|
|
|
import Card from '@/components/ui/Card'
|
|
|
|
|
import Logo from '@/components/template/Logo'
|
|
|
|
|
import type { ReactNode, ReactElement } from 'react'
|
|
|
|
|
import type { CommonProps } from '@/@types/common'
|
2025-06-16 09:06:54 +00:00
|
|
|
import { HiArrowLeft, HiCheck } from 'react-icons/hi'
|
|
|
|
|
import { Avatar, Select } from '@/components/ui'
|
|
|
|
|
import i18n, { dateLocales } from '@/locales'
|
|
|
|
|
import { useStoreActions, useStoreState } from '@/store'
|
|
|
|
|
import appConfig from '@/configs/app.config'
|
|
|
|
|
import dayjs from 'dayjs'
|
|
|
|
|
import { components } from 'react-select'
|
2025-08-11 06:34:44 +00:00
|
|
|
import { ROUTES_ENUM } from '@/routes/route.constant'
|
2025-08-11 14:52:19 +00:00
|
|
|
import { hasSubdomain } from '@/utils/subdomain'
|
2025-05-06 06:45:49 +00:00
|
|
|
|
|
|
|
|
interface SimpleProps extends CommonProps {
|
2025-05-30 08:33:33 +00:00
|
|
|
content?: ReactNode
|
2025-05-06 06:45:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const Simple = ({ children, content, ...rest }: SimpleProps) => {
|
2025-06-16 09:06:54 +00:00
|
|
|
const { config } = useStoreState((state) => state.abpConfig)
|
|
|
|
|
const { setLang } = useStoreActions((actions) => actions.locale)
|
|
|
|
|
const currentCulture = config?.localization?.currentCulture?.cultureName
|
|
|
|
|
|
|
|
|
|
const languageList = config?.localization.languages
|
|
|
|
|
|
|
|
|
|
const languageOptions = useMemo(() => {
|
|
|
|
|
return (
|
|
|
|
|
languageList?.map((lang) => ({
|
|
|
|
|
label: lang.displayName,
|
|
|
|
|
value: lang.cultureName,
|
|
|
|
|
cultureName: lang.cultureName,
|
|
|
|
|
imgPath: `/img/countries/${lang.cultureName}.png`,
|
|
|
|
|
})) || []
|
|
|
|
|
)
|
|
|
|
|
}, [languageList])
|
|
|
|
|
|
|
|
|
|
const onLanguageSelect = (cultureName = appConfig.locale) => {
|
|
|
|
|
const dispatchLang = () => {
|
|
|
|
|
i18n.changeLanguage(cultureName)
|
|
|
|
|
setLang(cultureName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dateLocales[cultureName]) {
|
|
|
|
|
dateLocales[cultureName]()
|
|
|
|
|
.then(() => {
|
|
|
|
|
dayjs.locale(cultureName)
|
|
|
|
|
dispatchLang()
|
|
|
|
|
})
|
|
|
|
|
.catch(() => {
|
|
|
|
|
dispatchLang()
|
|
|
|
|
})
|
|
|
|
|
} else {
|
|
|
|
|
dispatchLang()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const CustomSelectOption = ({ innerProps, label, data, isSelected }: any) => {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={`flex items-center justify-between p-2 ${
|
|
|
|
|
isSelected ? 'bg-gray-100 dark:bg-gray-500' : 'hover:bg-gray-50 dark:hover:bg-gray-600'
|
|
|
|
|
}`}
|
|
|
|
|
{...innerProps}
|
|
|
|
|
>
|
|
|
|
|
<div className="flex items-center">
|
2025-06-19 07:15:26 +00:00
|
|
|
<Avatar shape="circle" size={24} src={data.imgPath} title={data.label} />
|
2025-06-16 09:06:54 +00:00
|
|
|
</div>
|
|
|
|
|
{isSelected && <HiCheck className="text-emerald-500 text-xl" />}
|
|
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const CustomSingleValue = ({ data, ...props }: any) => {
|
|
|
|
|
return (
|
|
|
|
|
<components.SingleValue {...props}>
|
|
|
|
|
<div className="flex items-center">
|
|
|
|
|
<Avatar
|
|
|
|
|
className="ltr:mr-2 rtl:ml-2"
|
|
|
|
|
shape="circle"
|
2025-06-19 07:15:26 +00:00
|
|
|
size={24}
|
2025-06-16 09:06:54 +00:00
|
|
|
src={`/img/countries/${data.cultureName}.png`}
|
2025-06-19 07:15:26 +00:00
|
|
|
title={data.label}
|
2025-06-16 09:06:54 +00:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</components.SingleValue>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-30 08:33:33 +00:00
|
|
|
return (
|
|
|
|
|
<div className="h-full">
|
|
|
|
|
<Container className="flex flex-col flex-auto items-center justify-center min-w-0 h-full">
|
2025-08-11 06:34:44 +00:00
|
|
|
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-10">
|
2025-06-16 09:06:54 +00:00
|
|
|
<div className="flex justify-between items-center mb-4">
|
2025-08-11 14:52:19 +00:00
|
|
|
{!hasSubdomain() && (
|
|
|
|
|
<a
|
|
|
|
|
href={ROUTES_ENUM.public.home}
|
|
|
|
|
rel="noopener noreferrer"
|
|
|
|
|
className="text-gray-500 hover:text-gray-700"
|
|
|
|
|
>
|
|
|
|
|
<HiArrowLeft className="text-2xl" />
|
|
|
|
|
</a>
|
|
|
|
|
)}
|
2025-06-16 09:06:54 +00:00
|
|
|
|
|
|
|
|
<div className="w-12">
|
|
|
|
|
<Select
|
2025-08-11 14:52:19 +00:00
|
|
|
className="cursor-pointer"
|
2025-06-16 09:06:54 +00:00
|
|
|
options={languageOptions}
|
|
|
|
|
components={{
|
|
|
|
|
Option: CustomSelectOption,
|
|
|
|
|
SingleValue: CustomSingleValue,
|
|
|
|
|
}}
|
|
|
|
|
value={languageOptions.find((lang) => lang.cultureName === currentCulture)}
|
|
|
|
|
onChange={(option) => onLanguageSelect(option?.value)}
|
|
|
|
|
styles={{
|
|
|
|
|
control: (base) => ({
|
|
|
|
|
...base,
|
|
|
|
|
minHeight: 'auto',
|
|
|
|
|
border: 'none',
|
|
|
|
|
boxShadow: 'none',
|
|
|
|
|
backgroundColor: 'transparent',
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
}),
|
|
|
|
|
indicatorsContainer: (base) => ({
|
|
|
|
|
...base,
|
|
|
|
|
display: 'none',
|
|
|
|
|
}),
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-05-30 08:33:33 +00:00
|
|
|
|
|
|
|
|
<div className="text-center">
|
|
|
|
|
<Logo type="streamline" imgClass="mx-auto" />
|
|
|
|
|
</div>
|
2025-06-16 09:06:54 +00:00
|
|
|
|
2025-05-30 08:33:33 +00:00
|
|
|
<div className="text-center">
|
|
|
|
|
{content}
|
|
|
|
|
{children
|
|
|
|
|
? cloneElement(children as ReactElement, {
|
|
|
|
|
contentClassName: 'text-center',
|
|
|
|
|
...rest,
|
|
|
|
|
})
|
|
|
|
|
: null}
|
|
|
|
|
</div>
|
|
|
|
|
</Card>
|
|
|
|
|
</Container>
|
|
|
|
|
</div>
|
|
|
|
|
)
|
2025-05-06 06:45:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default Simple
|