diff --git a/frontend/index.html b/frontend/index.html
index c3b74cd..d1cd915 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -1,9 +1,17 @@
-
+
BizCare
+
diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts
index c5f83bf..910d7a4 100644
--- a/frontend/src/api/client.ts
+++ b/frontend/src/api/client.ts
@@ -18,7 +18,9 @@ client.interceptors.response.use(
(res) => res,
(err) => {
if (err.response?.status === 401) {
+ const theme = localStorage.getItem('bizcare_ui_theme')
localStorage.clear()
+ if (theme) localStorage.setItem('bizcare_ui_theme', theme)
if (!window.location.pathname.includes('/login')) window.location.href = '/login'
}
const msg = err.response?.data?.msg
diff --git a/frontend/src/components/AgentShell.tsx b/frontend/src/components/AgentShell.tsx
index d59a9d9..72a7f24 100644
--- a/frontend/src/components/AgentShell.tsx
+++ b/frontend/src/components/AgentShell.tsx
@@ -129,7 +129,9 @@ export default function AgentShell({ shop = false }: Props) {
}, [])
const logout = () => {
+ const theme = localStorage.getItem('bizcare_ui_theme')
localStorage.clear()
+ if (theme) localStorage.setItem('bizcare_ui_theme', theme)
navigate('/login')
}
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index ffb9cd9..8eb1955 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -2,12 +2,14 @@ import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
-import { applyTheme, loadTheme } from './theme'
+import { applyTheme, loadTheme, saveTheme } from './theme'
import { ThemeProvider } from './themeContext'
import './index.css'
import App from './App.tsx'
-applyTheme(loadTheme())
+const initialTheme = loadTheme()
+applyTheme(initialTheme)
+saveTheme(initialTheme)
const queryClient = new QueryClient({
defaultOptions: {
diff --git a/frontend/src/pages/care/ProductHomePage.tsx b/frontend/src/pages/care/ProductHomePage.tsx
index 1766988..e0a66eb 100644
--- a/frontend/src/pages/care/ProductHomePage.tsx
+++ b/frontend/src/pages/care/ProductHomePage.tsx
@@ -230,7 +230,7 @@ export default function ProductHomePage() {
홈렌탈상품을 등록 및 관리하실 수 있습니다.
- } loading={sync.isPending} onClick={() => sync.mutate()}>
+ } loading={sync.isPending} onClick={() => sync.mutate()}>
기본상품 동기화
} onClick={openCreate}>
diff --git a/frontend/src/pages/care/ProductInternetPage.tsx b/frontend/src/pages/care/ProductInternetPage.tsx
index 99ea58b..755af4c 100644
--- a/frontend/src/pages/care/ProductInternetPage.tsx
+++ b/frontend/src/pages/care/ProductInternetPage.tsx
@@ -227,6 +227,7 @@ export default function ProductInternetPage() {
}
loading={sync.isPending}
onClick={() => sync.mutate()}
diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css
index a90774d..4dc67bf 100644
--- a/frontend/src/styles/app.css
+++ b/frontend/src/styles/app.css
@@ -4994,3 +4994,58 @@ html.theme-light .ant-table-bordered .ant-table-thead > tr > th,
html.theme-light .ant-table-bordered .ant-table-tbody > tr > td {
border-color: #d9dee5 !important;
}
+
+/* 라이트 모드: 액션 버튼 = 파란 배경 + 흰 텍스트로 통일 (primary와 동일) */
+html.theme-light .ant-btn.ant-btn-default:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled),
+html.theme-light .ant-btn.ant-btn-dashed:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled) {
+ background: var(--primary) !important;
+ border-color: var(--primary) !important;
+ color: #fff !important;
+ box-shadow: none !important;
+ text-shadow: none !important;
+}
+html.theme-light .ant-btn.ant-btn-default:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled):hover,
+html.theme-light .ant-btn.ant-btn-default:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled):focus,
+html.theme-light .ant-btn.ant-btn-default:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled):active,
+html.theme-light .ant-btn.ant-btn-dashed:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled):hover,
+html.theme-light .ant-btn.ant-btn-dashed:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled):focus,
+html.theme-light .ant-btn.ant-btn-dashed:not(.ant-btn-dangerous):not(.ant-btn-disabled):not(:disabled):active {
+ background: var(--primary-dark) !important;
+ border-color: var(--primary-dark) !important;
+ color: #fff !important;
+}
+html.theme-light .ant-btn.ant-btn-default:not(.ant-btn-dangerous) .anticon,
+html.theme-light .ant-btn.ant-btn-dashed:not(.ant-btn-dangerous) .anticon {
+ color: inherit !important;
+}
+
+/* 페이지별 회색/면 버튼도 라이트에서는 동일 스타일 */
+html.theme-light .sms-send-footer .ant-btn-default,
+html.theme-light .sms-contact-footer-right .ant-btn-default,
+html.theme-light .abook-create-footer .ant-btn-default,
+html.theme-light .homes-pref-page .pref-table td .ant-btn-default,
+html.theme-light .homes-pref-page .pref-table td .ant-btn-default:hover,
+html.theme-light .turnover-mode .ant-btn-default,
+html.theme-light .recovery-actions .ant-btn,
+html.theme-light .sheet-presets .ant-btn,
+html.theme-light .sheet-clear,
+html.theme-light .farebox-gray-btn:not(:disabled),
+html.theme-light .calc-fullscreen-drawer-root .ant-btn-default,
+html.theme-light .calc-prepared-drawer-root .ant-btn-default {
+ background: var(--primary) !important;
+ border-color: var(--primary) !important;
+ color: #fff !important;
+}
+html.theme-light .sms-send-footer .ant-btn-default:hover,
+html.theme-light .sms-contact-footer-right .ant-btn-default:hover,
+html.theme-light .abook-create-footer .ant-btn-default:hover,
+html.theme-light .turnover-mode .ant-btn-default:hover,
+html.theme-light .recovery-actions .ant-btn:hover,
+html.theme-light .sheet-presets .ant-btn:hover,
+html.theme-light .sheet-clear:hover,
+html.theme-light .farebox-gray-btn:not(:disabled):hover {
+ background: var(--primary-dark) !important;
+ border-color: var(--primary-dark) !important;
+ color: #fff !important;
+}
+
diff --git a/frontend/src/theme.ts b/frontend/src/theme.ts
index bbe9a29..414ac19 100644
--- a/frontend/src/theme.ts
+++ b/frontend/src/theme.ts
@@ -6,17 +6,36 @@ export const THEMES: { value: Theme; label: string }[] = [
{ value: 'blue', label: '블루' },
]
-const STORAGE_KEY = 'bizcare_theme'
+/** 기본 테마 — 최초 실행 / 저장값 없음 */
+export const DEFAULT_THEME: Theme = 'dark'
+
+/** v2: 이전 기본값(light)이 localStorage에 남아 다크 기본이 무시되던 문제 해소 */
+const STORAGE_KEY = 'bizcare_ui_theme'
+const LEGACY_KEYS = ['bizcare_theme', 'billcare_theme']
const VALID: Theme[] = ['light', 'dark', 'blue']
+function isTheme(value: string | null): value is Theme {
+ return !!value && (VALID as string[]).includes(value)
+}
+
export function loadTheme(): Theme {
try {
const raw = localStorage.getItem(STORAGE_KEY)
- if (raw && (VALID as string[]).includes(raw)) return raw as Theme
+ if (isTheme(raw)) return raw
+
+ // 예전 키: 사용자가 다크/블루를 고른 경우만 이관. light(구 기본값)는 무시 → 다크
+ for (const key of LEGACY_KEYS) {
+ const legacy = localStorage.getItem(key)
+ if (!isTheme(legacy)) continue
+ localStorage.removeItem(key)
+ if (legacy === 'light') continue
+ localStorage.setItem(STORAGE_KEY, legacy)
+ return legacy
+ }
} catch {
/* private mode */
}
- return 'dark'
+ return DEFAULT_THEME
}
export function applyTheme(theme: Theme): void {