feat(frontend): 09_UI_DESIGN 디자인 시스템 전체 적용
테마 / 폰트 / 아이콘: - ConfigProvider theme 토큰 30+ 추가 (브랜드 컬러, 폰트, 라운딩, 메뉴/테이블/버튼) - Pretendard 폰트 link + index.css fontFamily 적용 - @tabler/icons-react 추가, MainLayout 에 적용 레이아웃: - styles/variables.css 신규 (--ga-* 변수 30+) - MainLayout: Header 48px 흰색 + bottom border, Sider 220px + 토글, Content 1400px 중앙 정렬, 정산월 MonthPicker, 햄버거 토글 공통 컴포넌트: - CodeBadge: 4단계 색상 매핑 (success/info/warning/danger), 누락 코드 보강 - MoneyText: 양수 #0F6E56, 음수 #E24B4A, 0 #888 (CSS 변수 사용) - SearchForm: 배경 #fafafa, borderRadius 8, padding 12px 16px - DataGrid: rowHeight 36, headerHeight 38, AG_GRID_LOCALE_KO, 합계행 getRowStyle 회색 배경 + 굵게 페이지 페이지네이션 통일: - utils/tablePagination.ts 신규 (showTotal '총 N건', pageSizeOptions [20/50/100]) - 7개 페이지 (Agent/Contract/Recruit/Exception/Settle/Payment/User) 적용 검증: tsc -b 통과 / vite build 성공 (10s) / 백엔드 단위테스트 76건 영향 없음 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,14 @@
|
||||
import { Layout, Menu, Dropdown, Badge, Space, Avatar, Button } from 'antd';
|
||||
import { useNavigate, Outlet } from 'react-router-dom';
|
||||
import { useState } from 'react';
|
||||
import { Layout, Menu, Dropdown, Badge, Space, Avatar, Button, DatePicker } from 'antd';
|
||||
import { useNavigate, Outlet, useLocation } from 'react-router-dom';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { BellOutlined, UserOutlined, LogoutOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
IconMenu2,
|
||||
IconBell,
|
||||
IconUser,
|
||||
IconLogout,
|
||||
} from '@tabler/icons-react';
|
||||
import dayjs from 'dayjs';
|
||||
import { menuApi, MenuResp } from '@/api/menu';
|
||||
import { authApi } from '@/api/auth';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
@@ -18,7 +25,10 @@ function toMenuItems(menus: MenuResp[]): any[] {
|
||||
|
||||
export default function MainLayout() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const auth = useAuthStore();
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [settleMonth, setSettleMonth] = useState(dayjs());
|
||||
|
||||
const { data: menus = [] } = useQuery({
|
||||
queryKey: ['menu', 'my'],
|
||||
@@ -35,36 +45,80 @@ export default function MainLayout() {
|
||||
|
||||
return (
|
||||
<Layout style={{ minHeight: '100vh' }}>
|
||||
<Header style={{ display: 'flex', justifyContent: 'space-between',
|
||||
background: '#001529', color: '#fff' }}>
|
||||
<div style={{ fontSize: 18, fontWeight: 600 }}>GA 수수료 정산 솔루션</div>
|
||||
<Space>
|
||||
<Badge count={0}>
|
||||
<Button type="text" icon={<BellOutlined style={{ color: '#fff' }} />} />
|
||||
<Header
|
||||
style={{
|
||||
height: 48,
|
||||
lineHeight: '48px',
|
||||
background: '#ffffff',
|
||||
borderBottom: '1px solid #f0f0f0',
|
||||
padding: '0 16px',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
boxShadow: 'var(--ga-shadow-card)',
|
||||
}}
|
||||
>
|
||||
<Space size={12}>
|
||||
<Button
|
||||
type="text"
|
||||
icon={<IconMenu2 size={18} />}
|
||||
onClick={() => setCollapsed((c) => !c)}
|
||||
/>
|
||||
<span style={{ fontSize: 15, fontWeight: 600, color: '#185FA5' }}>
|
||||
GA 정산시스템
|
||||
</span>
|
||||
</Space>
|
||||
<Space size={12}>
|
||||
<DatePicker
|
||||
picker="month"
|
||||
value={settleMonth}
|
||||
onChange={(d) => d && setSettleMonth(d)}
|
||||
allowClear={false}
|
||||
format="YYYY-MM"
|
||||
size="small"
|
||||
/>
|
||||
<Badge count={0} size="small">
|
||||
<Button type="text" icon={<IconBell size={18} />} />
|
||||
</Badge>
|
||||
<Dropdown menu={{
|
||||
items: [
|
||||
{ key: 'logout', label: '로그아웃', icon: <LogoutOutlined />, onClick: handleLogout },
|
||||
],
|
||||
}}>
|
||||
<Space style={{ color: '#fff', cursor: 'pointer' }}>
|
||||
<Avatar size="small" icon={<UserOutlined />} />
|
||||
{auth.userName ?? auth.loginId}
|
||||
<Dropdown
|
||||
menu={{
|
||||
items: [
|
||||
{
|
||||
key: 'logout',
|
||||
label: '로그아웃',
|
||||
icon: <IconLogout size={14} />,
|
||||
onClick: handleLogout,
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<Space style={{ cursor: 'pointer' }}>
|
||||
<Avatar size="small" icon={<IconUser size={14} />} />
|
||||
<span style={{ fontSize: 13 }}>{auth.userName ?? auth.loginId}</span>
|
||||
</Space>
|
||||
</Dropdown>
|
||||
</Space>
|
||||
</Header>
|
||||
<Layout>
|
||||
<Sider width={240} theme="light">
|
||||
<Sider
|
||||
width={220}
|
||||
collapsedWidth={64}
|
||||
collapsed={collapsed}
|
||||
theme="light"
|
||||
style={{ borderRight: '1px solid #f0f0f0' }}
|
||||
>
|
||||
<Menu
|
||||
mode="inline"
|
||||
items={toMenuItems(menus)}
|
||||
selectedKeys={[location.pathname]}
|
||||
onClick={({ key }) => navigate(String(key))}
|
||||
style={{ borderRight: 0, height: '100%' }}
|
||||
style={{ borderRight: 0, height: '100%', paddingTop: 8 }}
|
||||
/>
|
||||
</Sider>
|
||||
<Content style={{ padding: 24 }}>
|
||||
<Outlet />
|
||||
<Content style={{ padding: 'var(--ga-content-padding)', overflow: 'auto' }}>
|
||||
<div className="ga-page-container">
|
||||
<Outlet />
|
||||
</div>
|
||||
</Content>
|
||||
</Layout>
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user