diff --git a/.github/workflows/deploy-eks.yml b/.github/workflows/deploy-eks.yml index 61f357c..c9519d9 100644 --- a/.github/workflows/deploy-eks.yml +++ b/.github/workflows/deploy-eks.yml @@ -2,7 +2,7 @@ name: Frontend → ArgoCD Deploy on: push: - branches: ["main"] + branches: ["feature/ats2"] workflow_dispatch: env: diff --git a/src/pages/auth/LoginPage.jsx b/src/pages/auth/LoginPage.jsx index c7d7829..f89759e 100644 --- a/src/pages/auth/LoginPage.jsx +++ b/src/pages/auth/LoginPage.jsx @@ -38,10 +38,17 @@ function LoginPage() { return (
+ + {/* 제목 */}

로그인

+ {/* 설명 문구 추가 */} +

+ 사번과 비밀번호를 입력해주세요. +

+
+
); diff --git a/src/pages/resume/ResumePage.jsx b/src/pages/resume/ResumePage.jsx index 1587e70..f539081 100644 --- a/src/pages/resume/ResumePage.jsx +++ b/src/pages/resume/ResumePage.jsx @@ -76,6 +76,14 @@ function parseAnalysisResultJson(resultJson) { } } +/** 종합 점수 막대 색 (구간별) */ +function scoreBarTierClass(score) { + if (score < 50) return 'resume-ai__score-fill--tier-bad'; + if (score < 70) return 'resume-ai__score-fill--tier-fair'; + if (score < 85) return 'resume-ai__score-fill--tier-good'; + return 'resume-ai__score-fill--tier-great'; +} + function mergeAnalyzeIntoRow(row, analyzeResult) { const a = analyzeResult?.analysis; if (!a) return row; @@ -153,14 +161,14 @@ export default function ResumePage() { useEffect(() => { if (!analyzeModalRow) return; const onKey = (e) => { - if (e.key === 'Escape') { + if (e.key === 'Escape' && analyzeBusyId !== analyzeModalRow.applicantId) { setAnalyzeModalRow(null); setAnalyzeJd(''); } }; window.addEventListener('keydown', onKey); return () => window.removeEventListener('keydown', onKey); - }, [analyzeModalRow]); + }, [analyzeModalRow, analyzeBusyId]); const kpis = useMemo(() => { const total = rows.length; @@ -573,11 +581,19 @@ export default function ResumePage() { @@ -754,7 +770,7 @@ export default function ResumePage() { aria-valuemax={100} >
@@ -851,6 +867,7 @@ export default function ResumePage() { className="resume-ai__modal-backdrop" role="presentation" onClick={(e) => { + if (analyzeBusyId === analyzeModalRow?.applicantId) return; if (e.target === e.currentTarget) closeAnalyzeModal(); }} > @@ -895,11 +912,19 @@ export default function ResumePage() { onClick={confirmAnalyze} disabled={analyzeBusyId === analyzeModalRow.applicantId} > - {analyzeBusyId === analyzeModalRow.applicantId - ? '분석 중…' - : '분석 실행'} + 분석 실행 + {analyzeBusyId === analyzeModalRow.applicantId ? ( +
+
+ ) : null} ) : null} diff --git a/src/pages/resume/resumeAi.css b/src/pages/resume/resumeAi.css index 49b311a..d93c5c9 100644 --- a/src/pages/resume/resumeAi.css +++ b/src/pages/resume/resumeAi.css @@ -359,6 +359,15 @@ box-shadow: none; } +.resume-ai__btn-accent--with-spinner { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 56px; + min-height: 36px; + vertical-align: middle; +} + /* ----- 패널(목록·상세): 전체 폭 카드 ----- */ .resume-ai .panel { @@ -523,6 +532,7 @@ } .resume-ai__modal { + position: relative; width: 100%; max-width: 520px; max-height: min(90vh, 640px); @@ -534,6 +544,51 @@ padding: 26px 28px 24px; } +.resume-ai__modal-busy { + position: absolute; + inset: 0; + z-index: 3; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 14px; + border-radius: inherit; + background: rgba(255, 255, 255, 0.88); + backdrop-filter: blur(3px); +} + +.resume-ai__spinner-donut { + box-sizing: border-box; + width: 52px; + height: 52px; + flex-shrink: 0; + border-radius: 50%; + border: 4px solid #e8edf3; + border-top-color: var(--resume-ai-accent); + border-right-color: #fb923c; + animation: resume-ai-spin 0.72s linear infinite; +} + +.resume-ai__spinner-donut--sm { + width: 20px; + height: 20px; + border-width: 2px; + animation-duration: 0.65s; +} + +.resume-ai__sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + .resume-ai__modal h3 { margin: 0 0 6px; font-size: 20px; @@ -809,7 +864,7 @@ .resume-ai__section-title { margin: 0 0 12px; - font-size: 13px; + font-size: 15px; font-weight: 800; color: var(--resume-ai-text); letter-spacing: -0.02em; @@ -946,20 +1001,20 @@ button.resume-ai__icon-btn--link { display: flex; justify-content: space-between; align-items: baseline; - margin-bottom: 8px; - font-size: 13px; + margin-bottom: 10px; + font-size: 15px; font-weight: 600; color: var(--resume-ai-muted); } .resume-ai__score-head strong { - font-size: 18px; + font-size: 22px; font-weight: 800; color: var(--resume-ai-text); } .resume-ai__score-track { - height: 10px; + height: 12px; border-radius: 999px; background: #e2e8f0; overflow: hidden; @@ -969,15 +1024,33 @@ button.resume-ai__icon-btn--link { height: 100%; border-radius: inherit; background: linear-gradient(90deg, #fb923c, #ea580c); - transition: width 0.35s ease; + transition: + width 0.35s ease, + background 0.25s ease; +} + +.resume-ai__score-fill--tier-bad { + background: linear-gradient(90deg, #fca5a5, #dc2626); +} + +.resume-ai__score-fill--tier-fair { + background: linear-gradient(90deg, #fdba74, #ea580c); +} + +.resume-ai__score-fill--tier-good { + background: linear-gradient(90deg, #bef264, #65a30d); +} + +.resume-ai__score-fill--tier-great { + background: linear-gradient(90deg, #4ade80, #15803d); } .resume-ai__summary-box { - padding: 14px 16px; - font-size: 14px; - line-height: 1.65; + padding: 18px 20px; + font-size: 16px; + line-height: 1.72; font-weight: 500; - color: #334155; + color: #1e293b; background: #fafaf9; border: 1px solid var(--resume-ai-border); border-radius: 12px; @@ -991,14 +1064,14 @@ button.resume-ai__icon-btn--link { } .resume-ai__analysis-block { - margin-top: 18px; + margin-top: 22px; } .resume-ai__analysis-block-title { - margin: 0 0 10px; - padding-bottom: 8px; + margin: 0 0 12px; + padding-bottom: 10px; border-bottom: 2px solid var(--resume-ai-accent-border); - font-size: 14px; + font-size: 18px; font-weight: 800; color: var(--resume-ai-text); letter-spacing: -0.02em; @@ -1006,15 +1079,15 @@ button.resume-ai__icon-btn--link { .resume-ai__bullet-list { margin: 0; - padding-left: 1.2rem; - font-size: 14px; - line-height: 1.65; + padding-left: 1.35rem; + font-size: 16px; + line-height: 1.72; font-weight: 500; - color: #334155; + color: #1e293b; } .resume-ai__bullet-list li { - margin-bottom: 8px; + margin-bottom: 12px; } .resume-ai__bullet-list li:last-child { diff --git a/src/styles/login.css b/src/styles/login.css index 1bdd50b..c690da7 100644 --- a/src/styles/login.css +++ b/src/styles/login.css @@ -1,87 +1,119 @@ .login-page { - width: 100%; + flex: 1; display: flex; justify-content: center; align-items: center; + + padding: 40px; + + background: linear-gradient( + 135deg, + #f8f9fc 0%, + #f3f4f6 100% + ); } -/* 로그인 박스 */ +/* 로그인 카드 */ .login-container { width: 100%; - max-width: 340px; + max-width: 420px; + + padding: 48px 40px; - padding: 40px 30px; + background-color: white; - background-color: #f5f5f5; + border-radius: 24px; - border-radius: 16px; + box-shadow: + 0 10px 30px rgba(0, 0, 0, 0.06), + 0 2px 10px rgba(0, 0, 0, 0.03); } /* 제목 */ .login-title { text-align: center; - font-size: 28px; + font-size: 36px; font-weight: 700; - margin-bottom: 30px; - color: #111; + + margin-bottom: 10px; +} + +/* 설명 */ +.login-description { + text-align: center; + + font-size: 14px; + color: #777; + + margin-bottom: 36px; } /* form */ .login-form { display: flex; flex-direction: column; - gap: 18px; + gap: 22px; } -/* input 묶음 */ +/* input 그룹 */ .input-group { display: flex; flex-direction: column; - gap: 6px; + gap: 8px; } .input-group label { - font-size: 13px; - color: #222; + font-size: 14px; + font-weight: 600; + + color: #333; } /* input */ .input-group input { - height: 40px; + height: 48px; + + border: 1px solid #e1e1e1; + border-radius: 12px; - border: 1px solid #d9d9d9; - border-radius: 8px; + padding: 0 16px; - padding: 0 12px; + font-size: 14px; - font-size: 13px; + background-color: #fafafa; + + transition: 0.2s; outline: none; - background-color: white; } .input-group input:focus { border-color: #fea954; + + background-color: white; + + box-shadow: 0 0 0 4px rgba(254, 169, 84, 0.15); } /* 버튼 */ .login-button { - margin-top: 10px; + margin-top: 8px; - height: 40px; + height: 50px; border: none; - border-radius: 8px; + border-radius: 12px; background-color: #fea954; + color: white; - font-size: 14px; - font-weight: 600; + font-size: 15px; + font-weight: 700; cursor: pointer; @@ -89,5 +121,7 @@ } .login-button:hover { - opacity: 0.9; + transform: translateY(-1px); + + box-shadow: 0 8px 20px rgba(254, 169, 84, 0.3); } \ No newline at end of file