라이트 모드 버튼 스타일 수정

This commit is contained in:
Macbook
2026-07-12 19:31:20 +09:00
parent 5a0472b6bc
commit 430de96ac0
8 changed files with 96 additions and 7 deletions
+9 -1
View File
@@ -1,9 +1,17 @@
<!doctype html> <!doctype html>
<html lang="ko"> <html lang="ko" class="theme-dark">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>BizCare</title> <title>BizCare</title>
<script>
try {
var t = localStorage.getItem('bizcare_ui_theme')
if (t === 'light' || t === 'dark' || t === 'blue') {
document.documentElement.className = 'theme-' + t
}
} catch (e) {}
</script>
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+2
View File
@@ -18,7 +18,9 @@ client.interceptors.response.use(
(res) => res, (res) => res,
(err) => { (err) => {
if (err.response?.status === 401) { if (err.response?.status === 401) {
const theme = localStorage.getItem('bizcare_ui_theme')
localStorage.clear() localStorage.clear()
if (theme) localStorage.setItem('bizcare_ui_theme', theme)
if (!window.location.pathname.includes('/login')) window.location.href = '/login' if (!window.location.pathname.includes('/login')) window.location.href = '/login'
} }
const msg = err.response?.data?.msg const msg = err.response?.data?.msg
+2
View File
@@ -129,7 +129,9 @@ export default function AgentShell({ shop = false }: Props) {
}, []) }, [])
const logout = () => { const logout = () => {
const theme = localStorage.getItem('bizcare_ui_theme')
localStorage.clear() localStorage.clear()
if (theme) localStorage.setItem('bizcare_ui_theme', theme)
navigate('/login') navigate('/login')
} }
+4 -2
View File
@@ -2,12 +2,14 @@ import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { applyTheme, loadTheme } from './theme' import { applyTheme, loadTheme, saveTheme } from './theme'
import { ThemeProvider } from './themeContext' import { ThemeProvider } from './themeContext'
import './index.css' import './index.css'
import App from './App.tsx' import App from './App.tsx'
applyTheme(loadTheme()) const initialTheme = loadTheme()
applyTheme(initialTheme)
saveTheme(initialTheme)
const queryClient = new QueryClient({ const queryClient = new QueryClient({
defaultOptions: { defaultOptions: {
+1 -1
View File
@@ -230,7 +230,7 @@ export default function ProductHomePage() {
<p>홈렌탈상품을 등록 및 관리하실 수 있습니다.</p> <p>홈렌탈상품을 등록 및 관리하실 수 있습니다.</p>
</div> </div>
<Space> <Space>
<Button icon={<SyncOutlined />} loading={sync.isPending} onClick={() => sync.mutate()}> <Button type="primary" icon={<SyncOutlined />} loading={sync.isPending} onClick={() => sync.mutate()}>
기본상품 동기화 기본상품 동기화
</Button> </Button>
<Button type="primary" icon={<PlusSquareOutlined />} onClick={openCreate}> <Button type="primary" icon={<PlusSquareOutlined />} onClick={openCreate}>
@@ -227,6 +227,7 @@ export default function ProductInternetPage() {
</div> </div>
<Space> <Space>
<Button <Button
type="primary"
icon={<SyncOutlined />} icon={<SyncOutlined />}
loading={sync.isPending} loading={sync.isPending}
onClick={() => sync.mutate()} onClick={() => sync.mutate()}
+55
View File
@@ -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 { html.theme-light .ant-table-bordered .ant-table-tbody > tr > td {
border-color: #d9dee5 !important; 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;
}
+22 -3
View File
@@ -6,17 +6,36 @@ export const THEMES: { value: Theme; label: string }[] = [
{ value: 'blue', label: '블루' }, { 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'] 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 { export function loadTheme(): Theme {
try { try {
const raw = localStorage.getItem(STORAGE_KEY) 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 { } catch {
/* private mode */ /* private mode */
} }
return 'dark' return DEFAULT_THEME
} }
export function applyTheme(theme: Theme): void { export function applyTheme(theme: Theme): void {