Login ekranı üzerinden değişiklikler
This commit is contained in:
parent
f5d339c699
commit
7c5650b680
3 changed files with 117 additions and 92 deletions
|
|
@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
|
||||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||||
}, {
|
}, {
|
||||||
"url": "index.html",
|
"url": "index.html",
|
||||||
"revision": "0.6ektjtehls8"
|
"revision": "0.gf7mb80njbo"
|
||||||
}], {});
|
}], {});
|
||||||
workbox.cleanupOutdatedCaches();
|
workbox.cleanupOutdatedCaches();
|
||||||
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,135 @@
|
||||||
import { cloneElement } from 'react'
|
import { cloneElement, useMemo } from 'react'
|
||||||
import Container from '@/components/shared/Container'
|
import Container from '@/components/shared/Container'
|
||||||
import Card from '@/components/ui/Card'
|
import Card from '@/components/ui/Card'
|
||||||
import Logo from '@/components/template/Logo'
|
import Logo from '@/components/template/Logo'
|
||||||
import type { ReactNode, ReactElement } from 'react'
|
import type { ReactNode, ReactElement } from 'react'
|
||||||
import type { CommonProps } from '@/@types/common'
|
import type { CommonProps } from '@/@types/common'
|
||||||
import { HiArrowLeft } from 'react-icons/hi'
|
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'
|
||||||
|
|
||||||
interface SimpleProps extends CommonProps {
|
interface SimpleProps extends CommonProps {
|
||||||
content?: ReactNode
|
content?: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const Simple = ({ children, content, ...rest }: SimpleProps) => {
|
const Simple = ({ children, content, ...rest }: SimpleProps) => {
|
||||||
|
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">
|
||||||
|
<Avatar shape="circle" size={20} src={data.imgPath} />
|
||||||
|
</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"
|
||||||
|
size={18}
|
||||||
|
src={`/img/countries/${data.cultureName}.png`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</components.SingleValue>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
<Container className="flex flex-col flex-auto items-center justify-center min-w-0 h-full">
|
<Container className="flex flex-col flex-auto items-center justify-center min-w-0 h-full">
|
||||||
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-10">
|
<Card className="min-w-[320px] md:min-w-[450px]" bodyClass="md:p-10">
|
||||||
<a
|
<div className="flex justify-between items-center mb-4">
|
||||||
href={import.meta.env.VITE_COMPANY_URL}
|
<a
|
||||||
rel="noopener noreferrer"
|
href={import.meta.env.VITE_COMPANY_URL}
|
||||||
className="top-0 right-0 text-gray-500 hover:text-gray-700"
|
rel="noopener noreferrer"
|
||||||
>
|
className="text-gray-500 hover:text-gray-700"
|
||||||
<HiArrowLeft className="text-2xl" />
|
>
|
||||||
</a>
|
<HiArrowLeft className="text-2xl" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<div className="w-12">
|
||||||
|
<Select
|
||||||
|
className='cursor-pointer'
|
||||||
|
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>
|
||||||
|
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Logo type="streamline" imgClass="mx-auto" />
|
<Logo type="streamline" imgClass="mx-auto" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
{content}
|
{content}
|
||||||
{children
|
{children
|
||||||
|
|
|
||||||
|
|
@ -177,39 +177,6 @@ const Login = () => {
|
||||||
setSubmitting(false)
|
setSubmitting(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomSingleValue = ({ data, ...props }: any) => {
|
|
||||||
return (
|
|
||||||
<components.SingleValue {...props}>
|
|
||||||
<div className="flex items-center">
|
|
||||||
<Avatar
|
|
||||||
className="ltr:mr-2 rtl:ml-2"
|
|
||||||
shape="circle"
|
|
||||||
size={18}
|
|
||||||
src={`/img/countries/${data.cultureName}.png`}
|
|
||||||
/>
|
|
||||||
<span>{data.label}</span>
|
|
||||||
</div>
|
|
||||||
</components.SingleValue>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
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">
|
|
||||||
<Avatar shape="circle" size={20} src={data.imgPath} />
|
|
||||||
<span className="ml-2 rtl:mr-2">{label}</span>
|
|
||||||
</div>
|
|
||||||
{isSelected && <HiCheck className="text-emerald-500 text-xl" />}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const subDomainName = getSubdomain()
|
const subDomainName = getSubdomain()
|
||||||
const tenantId = useStoreState((a) => a.auth.tenantId) ?? subDomainName
|
const tenantId = useStoreState((a) => a.auth.tenantId) ?? subDomainName
|
||||||
const tenantStyle: React.CSSProperties | undefined =
|
const tenantStyle: React.CSSProperties | undefined =
|
||||||
|
|
@ -230,36 +197,6 @@ const Login = () => {
|
||||||
const currentCulture = config?.localization?.currentCulture?.cultureName
|
const currentCulture = config?.localization?.currentCulture?.cultureName
|
||||||
|
|
||||||
const languageList = config?.localization.languages
|
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isMultiTenant) return
|
if (!isMultiTenant) return
|
||||||
|
|
@ -280,10 +217,11 @@ const Login = () => {
|
||||||
animate={{ opacity: 1, x: 0 }}
|
animate={{ opacity: 1, x: 0 }}
|
||||||
transition={{ duration: 0.5, origin: 1 }}
|
transition={{ duration: 0.5, origin: 1 }}
|
||||||
>
|
>
|
||||||
<div className="mb-8 relative">
|
<div className="mb-8 relative text-center">
|
||||||
<h3 className="mb-1 pr-10">{translate('::Abp.Account.WelcomeBack')}</h3>
|
<h3 className="mb-1 m-5">{translate('::Abp.Account.WelcomeBack')}</h3>
|
||||||
<p>{translate('::Abp.Account.WelcomeBack.Message')}</p>
|
<p>{translate('::Abp.Account.WelcomeBack.Message')}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isMultiTenant && (
|
{isMultiTenant && (
|
||||||
<>
|
<>
|
||||||
<label className="form-label mb-2" style={tenantStyle}>
|
<label className="form-label mb-2" style={tenantStyle}>
|
||||||
|
|
@ -300,23 +238,6 @@ const Login = () => {
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<div>
|
|
||||||
<label className="form-label mb-2">
|
|
||||||
{translate('::Abp.Identity.Preferences.Language')}
|
|
||||||
</label>
|
|
||||||
<div className="mb-4">
|
|
||||||
<Select
|
|
||||||
options={languageOptions}
|
|
||||||
components={{
|
|
||||||
Option: CustomSelectOption,
|
|
||||||
SingleValue: CustomSingleValue,
|
|
||||||
}}
|
|
||||||
value={languageOptions.find((lang) => lang.cultureName === currentCulture)}
|
|
||||||
onChange={(option) => onLanguageSelect(option?.value)}
|
|
||||||
className="mb-4"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue