o2o-negosium-original/frontend/src/features/auth/hooks/usePreLoginBranding.ts

63 lines
2.3 KiB
TypeScript

import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router'
import { authApi } from '@/apis'
import type { Branding } from '@/apis/auth/auth.type'
// 로그인 전 화면의 회사 브랜딩을 담아 두는 곳. 로그아웃/토큰 만료와 무관하게 남겨
// 뒤로가기·재진입으로 session_id 가 없어져도 같은 회사 화면을 유지한다(회사 식별 정보만 담는다).
const BRANDING_KEY = 'negosium.preLoginBranding'
function readCached(): Branding | null {
try {
const raw = localStorage.getItem(BRANDING_KEY)
return raw ? (JSON.parse(raw) as Branding) : null
} catch {
return null // 손상된 값은 없는 것으로 본다
}
}
function writeCached(branding: Branding): void {
try {
localStorage.setItem(BRANDING_KEY, JSON.stringify(branding))
} catch {
// 저장 불가(프라이빗 모드 등)면 이번 방문에만 적용된다
}
}
// 로그인 전 화면(로그인 페이지)의 회사 브랜딩.
// 협력사는 초청 메일의 /chat?session_id=... 로 들어오므로, 그 session_id 로 인증 없이 브랜딩만 조회한다.
// session_id 가 없으면 마지막으로 확인된 회사 브랜딩을 쓰고, 그것도 없으면 기본 브랜드(Negosium).
export function usePreLoginBranding(): Branding | null {
const [searchParams] = useSearchParams()
const [branding, setBranding] = useState<Branding | null>(readCached)
const sessionId = searchParams.get('session_id') ?? ''
useEffect(() => {
if (!sessionId) return
let alive = true
void authApi
.sessionBranding(sessionId)
.then((res) => {
if (!alive || res.result?.success === false) return
const next: Branding = {
service_name: res.service_name || undefined,
logo_url: res.logo_url || undefined,
primary_color: res.primary_color || undefined,
helpdesk: res.helpdesk?.length ? res.helpdesk : undefined,
}
if (!next.service_name && !next.logo_url && !next.primary_color && !next.helpdesk) return
setBranding(next)
writeCached(next) // 다음 진입에 session_id 가 없어도 이 회사로 보이게 한다
})
.catch(() => {
// 조회 실패 시 캐시(또는 기본 브랜드)를 그대로 둔다
})
return () => {
alive = false
}
}, [sessionId])
return branding
}