sozsoft-platform/ui/src/components/shared/TenantSelector.tsx

149 lines
4.2 KiB
TypeScript
Raw Normal View History

import Input from '@/components/ui/Input'
import { getTenantByNameDetail } from '@/services/tenant.service'
import { useStoreActions, useStoreState } from '@/store'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { defaultDomain, getSubdomain } from '@/utils/subdomain'
import type { CSSProperties } from 'react'
import { useCallback, useEffect, useRef } from 'react'
const hiddenTenantStyle: CSSProperties = {
opacity: 0,
position: 'absolute',
pointerEvents: 'none',
height: 0,
margin: 0,
padding: 0,
border: 'none',
}
const TenantSelector = () => {
const { translate } = useLocalization()
const isMultiTenant = useStoreState((state) => state.abpConfig.config?.multiTenancy.isEnabled)
const tenantName = useStoreState((state) => state.locale.currentTenantName)
const { setTenantName } = useStoreActions((actions) => actions.locale)
const { setTenant } = useStoreActions((actions) => actions.auth.tenant)
const { setWarning } = useStoreActions((actions) => actions.base.messages)
const requestIdRef = useRef(0)
const lastRequestedTenantNameRef = useRef<string>()
const subDomainName = getSubdomain()
const isSubdomainTenant = !!subDomainName && subDomainName !== defaultDomain
const tenantStyle = isSubdomainTenant ? hiddenTenantStyle : undefined
const setWarningTimeout = useCallback(
(message: string) => {
setTimeout(() => {
setWarning(message)
}, 100)
},
[setWarning],
)
const redirectToMainDomain = useCallback(
(name: string) => {
setTenantName(undefined)
const parts = window.location.hostname.split('.')
const mainDomain = parts.length >= 3 ? parts.slice(1).join('.') : window.location.hostname
setWarningTimeout(
`"${name}" kurumuna ait kayıt bulunamadı.\nAna sayfaya yönlendiriliyorsunuz...`,
)
setTimeout(() => {
window.location.href = `${window.location.protocol}//${mainDomain}`
}, 3000)
},
[setTenantName, setWarningTimeout],
)
const fetchDataByName = useCallback(
async (name: string, isSubdomain = false) => {
if (!isSubdomain && name === lastRequestedTenantNameRef.current) {
return
}
lastRequestedTenantNameRef.current = name
const requestId = requestIdRef.current + 1
requestIdRef.current = requestId
if (name) {
try {
const response = await getTenantByNameDetail(name)
if (requestId !== requestIdRef.current) {
return
}
if (response.data) {
setTenant({
tenantId: response.data.id,
tenantName: response.data.name,
menuGroup: response.data.menuGroup,
})
} else {
setTenant(undefined)
if (isSubdomain) redirectToMainDomain(name)
}
} catch {
if (requestId !== requestIdRef.current) {
return
}
setTenant(undefined)
if (isSubdomain) redirectToMainDomain(name)
}
} else {
setTenant(undefined)
}
},
[redirectToMainDomain, setTenant],
)
const handleTenantNameChange = (value: string) => {
setTenantName(value)
}
const handleTenantNameBlur = () => {
if (subDomainName) {
return
}
fetchDataByName(tenantName || '')
}
useEffect(() => {
if (!isMultiTenant) {
setTenant(undefined)
return
}
if (subDomainName) {
setTenantName(subDomainName)
fetchDataByName(subDomainName, true)
}
}, [fetchDataByName, isMultiTenant, setTenant, setTenantName, subDomainName])
if (!isMultiTenant) {
return null
}
return (
<>
<label className="form-label mb-2" style={tenantStyle}>
{translate('::Organization')}
</label>
<div className="mb-4">
<Input
placeholder={translate('::Organization')}
value={tenantName ?? ''}
onChange={(event) => handleTenantNameChange(event.target.value)}
onBlur={handleTenantNameBlur}
style={tenantStyle}
aria-hidden={isSubdomainTenant ? 'true' : 'false'}
autoFocus={!isSubdomainTenant}
/>
</div>
</>
)
}
export default TenantSelector