50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
import { useEffect, useState, type ImgHTMLAttributes } from 'react'
|
|
|
|
type BrandingSettings = {
|
|
siteLogo?: string | null
|
|
siteLogoDark?: string | null
|
|
siteName?: string | null
|
|
}
|
|
|
|
const fallbackLogo = '/default-favicon.ico'
|
|
|
|
export const Logo = ({
|
|
className = 'w-auto h-5',
|
|
...props
|
|
}: Omit<ImgHTMLAttributes<HTMLImageElement>, 'alt' | 'src'>) => {
|
|
const [branding, setBranding] = useState<BrandingSettings>({})
|
|
|
|
useEffect(() => {
|
|
const controller = new AbortController()
|
|
|
|
fetch('/api/site-settings?scope=branding', {
|
|
credentials: 'same-origin',
|
|
signal: controller.signal,
|
|
})
|
|
.then((response) => (response.ok ? response.json() : null))
|
|
.then((settings: BrandingSettings | null) => {
|
|
if (settings) setBranding(settings)
|
|
})
|
|
.catch(() => undefined)
|
|
|
|
return () => controller.abort()
|
|
}, [])
|
|
|
|
const logo = branding.siteLogoDark || branding.siteLogo || fallbackLogo
|
|
const siteName = branding.siteName?.trim() || 'HiCAD'
|
|
|
|
return (
|
|
<img
|
|
{...props}
|
|
alt={siteName}
|
|
className={`${className} object-contain`}
|
|
onError={(event) => {
|
|
if (!event.currentTarget.src.endsWith(fallbackLogo)) {
|
|
event.currentTarget.src = fallbackLogo
|
|
}
|
|
}}
|
|
src={logo}
|
|
/>
|
|
)
|
|
}
|