guardia-cms/frontend/src/components/Header.tsx
zio 106d70c054 chore(deploy): CMS 클린 재동기화 + Claude provider flip
- workspace/guardia-cms 정본을 repos에 클린 재동기화(부분 auto-sync 발산 해소, 컴파일 가능 상태 회복)
- AI provider flip: db/105_ai_provider_claude.sql (cms_setting UPSERT ai.provider=claude, 멱등)
- application.yml schema-locations 에 105 등재 (104 시드 이후 실행)
- stale 프론트 번들 2종 정리(빌드 재생성분)
- Claude 키 미설정/실패 시 AiTextRouter Ollama 자동 폴백(무중단·무회귀)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-11 10:38:40 +09:00

44 lines
1.8 KiB
TypeScript

import { useEffect, useState } from 'react'
import { useNavigate, Link } from 'react-router-dom'
import { LogOut, UserCircle } from 'lucide-react'
import { getAiStatus } from '../api/client'
export default function Header() {
const nav = useNavigate()
const user = localStorage.getItem('cms_user') || 'admin'
const role = localStorage.getItem('cms_role') || ''
const [ollama, setOllama] = useState<boolean | null>(null)
useEffect(() => {
getAiStatus().then(d => setOllama(!!d?.ollamaAvailable)).catch(() => setOllama(false))
}, [])
const logout = () => {
localStorage.removeItem('cms_token')
localStorage.removeItem('cms_role')
localStorage.removeItem('cms_user')
nav('/login')
}
return (
<header className="h-16 bg-panel border-b border-edge flex items-center justify-between px-6">
<div className="text-sm text-slate-400">AI · CMS · Ollama </div>
<div className="flex items-center gap-4">
<span className={`flex items-center gap-1.5 text-xs px-2 py-1 rounded-md border ${
ollama ? 'text-accent border-accent/30 bg-accent/10' : 'text-slate-400 border-edge bg-card'
}`}>
<span className={`w-1.5 h-1.5 rounded-full ${ollama ? 'bg-accent' : 'bg-slate-500'}`} />
AI {ollama === null ? '확인 중' : ollama ? '온라인' : '폴백'}
</span>
<Link to="/mypage" className="flex items-center gap-1.5 text-sm text-slate-300 hover:text-brand" title="마이페이지">
<UserCircle size={18} /> {user}
{role && <span className="text-[11px] text-slate-500">({role})</span>}
</Link>
<button onClick={logout} className="flex items-center gap-1.5 text-sm text-slate-400 hover:text-brand">
<LogOut size={16} />
</button>
</div>
</header>
)
}