diff --git a/src/main/java/org/sopt/poti/global/security/SecurityConfig.java b/src/main/java/org/sopt/poti/global/security/SecurityConfig.java index 47108d5..f985915 100644 --- a/src/main/java/org/sopt/poti/global/security/SecurityConfig.java +++ b/src/main/java/org/sopt/poti/global/security/SecurityConfig.java @@ -33,6 +33,7 @@ public class SecurityConfig { "/swagger-ui/**", // Swagger 문서 관련 "/v3/api-docs/**", "/favicon.ico", + "/css/**", "/dev/login", // 개발자용 자동 로그인 (토큰 발급) }; diff --git a/src/main/resources/static/css/admin.css b/src/main/resources/static/css/admin.css new file mode 100644 index 0000000..602100c --- /dev/null +++ b/src/main/resources/static/css/admin.css @@ -0,0 +1,323 @@ +/* ── Variables ── */ +:root { + --sidebar-bg: #0f172a; + --sidebar-hover: #1e293b; + --accent: #6366f1; + --accent-light: #818cf8; + --bg: #f1f5f9; + --surface: #ffffff; + --border: #e2e8f0; + --text: #0f172a; + --text-muted: #64748b; +} + +/* ── Reset ── */ +*, *::before, *::after { box-sizing: border-box; } +body { + margin: 0; + background: var(--bg); + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-size: 14px; + color: var(--text); +} + +/* ── Sidebar ── */ +.sidebar { + width: 240px; + min-height: 100vh; + background: var(--sidebar-bg); + display: flex; + flex-direction: column; + position: fixed; + top: 0; left: 0; + z-index: 100; +} +.sidebar-brand { + padding: 24px 20px 18px; + border-bottom: 1px solid #1e293b; +} +.sidebar-brand .brand-title { + color: #fff; + font-size: 1.05rem; + font-weight: 700; +} +.sidebar-brand .brand-sub { + color: #475569; + font-size: 0.7rem; + margin-top: 3px; +} +.sidebar-nav { + flex: 1; + padding: 10px 10px 0; +} +.nav-label { + color: #475569; + font-size: 0.62rem; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; + padding: 14px 8px 6px; +} +.sidebar-link { + display: flex; + align-items: center; + gap: 10px; + color: #94a3b8; + text-decoration: none; + padding: 9px 12px; + border-radius: 8px; + font-size: 0.85rem; + font-weight: 500; + transition: background 0.15s, color 0.15s; + margin-bottom: 2px; +} +.sidebar-link i { font-size: 0.95rem; } +.sidebar-link:hover { background: #1e293b; color: #e2e8f0; } +.sidebar-link.active { background: var(--accent); color: #fff; } +.sidebar-footer { + padding: 10px; + border-top: 1px solid #1e293b; +} +.sidebar-footer button { + display: flex; + align-items: center; + gap: 10px; + width: 100%; + background: none; + border: none; + color: #64748b; + font-size: 0.82rem; + font-weight: 500; + padding: 9px 12px; + border-radius: 8px; + cursor: pointer; + text-align: left; + transition: background 0.15s, color 0.15s; +} +.sidebar-footer button:hover { background: #1e293b; color: #94a3b8; } + +/* ── Main Layout ── */ +.main-wrapper { + margin-left: 240px; + min-height: 100vh; + display: flex; + flex-direction: column; +} +.topbar { + background: var(--surface); + border-bottom: 1px solid var(--border); + padding: 14px 28px; + display: flex; + align-items: center; + justify-content: space-between; + position: sticky; + top: 0; + z-index: 50; +} +.topbar-title { + font-size: 0.95rem; + font-weight: 700; + color: var(--text); +} +.topbar-badge { + background: var(--bg); + color: var(--text-muted); + font-size: 0.72rem; + padding: 3px 10px; + border-radius: 20px; + font-weight: 500; +} +.main-content { padding: 24px 28px; flex: 1; } + +/* ── Flash Alert ── */ +.alert-flash { + border: none; + border-radius: 10px; + font-size: 0.85rem; + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 20px; + padding: 12px 16px; +} + +/* ── Stat Cards (Dashboard) ── */ +.stat-card { + background: var(--surface); + border-radius: 14px; + border: none; + overflow: hidden; + box-shadow: 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04); +} +.stat-card .card-body { padding: 20px 22px; } +.stat-label { + font-size: 0.75rem; + font-weight: 600; + color: var(--text-muted); + margin-bottom: 10px; +} +.stat-icon { + width: 38px; height: 38px; + border-radius: 10px; + display: flex; + align-items: center; + justify-content: center; + font-size: 1rem; +} +.stat-value { + font-size: 1.8rem; + font-weight: 700; + color: var(--text); + line-height: 1; + margin-top: 2px; +} +.stat-desc { + font-size: 0.72rem; + color: var(--text-muted); + margin-top: 6px; +} +.stat-bar { height: 3px; } + +/* ── Quick Links ── */ +.quick-card { + background: var(--surface); + border-radius: 14px; + border: none; + box-shadow: 0 1px 3px rgba(0,0,0,.06); + padding: 20px 22px; +} +.quick-card .section-title { + font-size: 0.8rem; + font-weight: 600; + color: var(--text-muted); + margin-bottom: 12px; +} +.quick-link { + display: inline-flex; + align-items: center; + gap: 7px; + background: var(--bg); + border: 1px solid var(--border); + color: var(--text); + border-radius: 8px; + padding: 7px 14px; + font-size: 0.82rem; + font-weight: 500; + text-decoration: none; + transition: border-color 0.15s, background 0.15s; +} +.quick-link:hover { border-color: var(--accent); color: var(--accent); background: #eef2ff; } + +/* ── Table Card ── */ +.table-card { + background: var(--surface); + border-radius: 14px; + border: none; + overflow: hidden; + box-shadow: 0 1px 3px rgba(0,0,0,.06), 0 1px 2px rgba(0,0,0,.04); +} +.admin-table { margin: 0; } +.admin-table thead th { + font-size: 0.7rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + color: var(--text-muted); + background: #f8fafc; + border-bottom: 1px solid var(--border); + padding: 11px 16px; + white-space: nowrap; +} +.admin-table tbody td { + padding: 13px 16px; + font-size: 0.85rem; + color: var(--text); + vertical-align: middle; + border-bottom: 1px solid #f1f5f9; +} +.admin-table tbody tr:hover td { background: #f8fafc; } +.admin-table tbody tr:last-child td { border-bottom: none; } +.cell-id { font-size: 0.75rem; color: var(--text-muted); } +.cell-sub { font-size: 0.78rem; color: var(--text-muted); } + +/* ── Badges ── */ +.badge-pill { + display: inline-block; + font-size: 0.68rem; + font-weight: 700; + padding: 3px 9px; + border-radius: 20px; + letter-spacing: 0.01em; +} +.badge-active { background: #dcfce7; color: #15803d; } +.badge-suspended { background: #fee2e2; color: #b91c1c; } +.badge-withdrawn { background: #f1f5f9; color: #94a3b8; } +.badge-kakao { background: #fef9c3; color: #854d0e; } + +.status-recruiting { background: #dbeafe; color: #1d4ed8; } +.status-closed { background: #fef9c3; color: #854d0e; } +.status-payment_done { background: #dcfce7; color: #15803d; } +.status-shipping { background: #ede9fe; color: #6d28d9; } +.status-delivered { background: #f1f5f9; color: #475569; } + +/* ── Action Buttons ── */ +.btn-action { + display: inline-block; + font-size: 0.75rem; + font-weight: 600; + padding: 4px 11px; + border-radius: 7px; + border: none; + cursor: pointer; + transition: filter 0.15s; + white-space: nowrap; + line-height: 1.6; +} +.btn-action:hover { filter: brightness(0.93); } +.btn-suspend { background: #fee2e2; color: #b91c1c; } +.btn-release { background: #dcfce7; color: #15803d; } +.btn-withdraw { background: #f1f5f9; color: #64748b; } +.btn-delete { background: #fee2e2; color: #b91c1c; } + +/* ── Filter Tabs ── */ +.filter-tabs { + display: flex; + gap: 7px; + flex-wrap: wrap; + margin-bottom: 16px; +} +.filter-tab { + font-size: 0.78rem; + font-weight: 600; + padding: 5px 13px; + border-radius: 20px; + border: 1.5px solid var(--border); + background: var(--surface); + color: var(--text-muted); + text-decoration: none; + transition: all 0.15s; +} +.filter-tab:hover { border-color: var(--accent); color: var(--accent); } +.filter-tab.is-active { background: var(--accent); border-color: var(--accent); color: #fff; } + +/* ── Empty State ── */ +.empty-state { + padding: 52px 0; + text-align: center; + color: var(--text-muted); +} +.empty-state i { font-size: 2.2rem; display: block; margin-bottom: 10px; opacity: 0.4; } +.empty-state p { font-size: 0.85rem; margin: 0; } + +/* ── Pagination ── */ +.pagination { gap: 3px; } +.page-link { + font-size: 0.78rem; + color: var(--accent); + border-color: var(--border); + border-radius: 7px !important; + padding: 5px 10px; +} +.page-link:hover { background: #eef2ff; border-color: var(--accent); color: var(--accent); } +.page-item.active .page-link { background: var(--accent); border-color: var(--accent); } +.page-item.disabled .page-link { pointer-events: none; opacity: 0.4; } diff --git a/src/main/resources/templates/admin/dashboard.html b/src/main/resources/templates/admin/dashboard.html index 80ade45..241c93e 100644 --- a/src/main/resources/templates/admin/dashboard.html +++ b/src/main/resources/templates/admin/dashboard.html @@ -3,78 +3,67 @@ th:replace="~{admin/layout :: layout(~{::section}, 'dashboard')}">
-
- +
-
-
-
- 총 유저 수 -
- +
+
+
+ 총 유저 수 +
+
-
0
-
가입된 전체 유저
+
0
+
가입된 전체 유저
-
+
-
-
-
- 분철글 수 -
- +
+
+
+ 분철글 수 +
+
-
0
-
등록된 전체 분철글
+
0
+
등록된 전체 분철글
-
+
-
-
-
- 총 주문 수 -
- +
+
+
+ 총 주문 수 +
+
-
0
-
전체 주문 건수
+
0
+
전체 주문 건수
-
+
- -
-
-
빠른 이동
-
- - 유저 관리 - - - 분철글 관리 - -
+
+
빠른 이동
+
+ + 유저 관리 + + + 분철글 관리 +
diff --git a/src/main/resources/templates/admin/layout.html b/src/main/resources/templates/admin/layout.html index 17d3ee6..bfeb684 100644 --- a/src/main/resources/templates/admin/layout.html +++ b/src/main/resources/templates/admin/layout.html @@ -6,152 +6,19 @@ POTI 어드민 - +
+
🍵 POTI Admin
관리자 패널
-
메뉴
분철글 관리
-