sozsoft-platform/ui/src/components/shared/TenantSelector.tsx
2026-06-02 21:47:01 +03:00

148 lines
4.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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