[feat]: Shadcn UI 모달 Select 레이아웃 시프트 방지 및 코드 정리

주요 변경사항:
- 테마/언어 선택을 모달 스타일로 변경 (native={false})
  - LoginPage, SignupPage, DashboardLayout 적용
- CSS 2줄로 레이아웃 시프트 완전 제거
  - body { overflow: visible !important }
  - body[data-scroll-locked] { margin-right: 0 !important }
- 미사용 business 컴포넌트 대량 삭제 (코드 정리)
- CEODashboard → MainDashboard 이름 변경
- 구현 문서 작성: [IMPL-2025-11-12] modal-select-layout-shift-fix.md

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-11-12 18:09:12 +09:00
parent a68a25b737
commit 46aff1a6a2
57 changed files with 307 additions and 37120 deletions

View File

@@ -33,14 +33,17 @@ export function LoginPage() {
useEffect(() => {
const checkAuth = async () => {
try {
// 🔵 Next.js 내부 API - 쿠키에서 토큰 확인 (PHP 호출 X, 성능 최적화)
const response = await fetch('/api/auth/check');
if (response.ok) {
// 이미 로그인됨 → 대시보드로 리다이렉트 (replace로 히스토리에서 제거)
router.replace('/dashboard');
return;
}
// 인증 안됨 (401) → 현재 페이지 유지
} catch {
// 인증 안됨 → 현재 페이지 유지
// API 호출 실패 → 현재 페이지 유지
} finally {
setIsChecking(false);
}
@@ -59,8 +62,7 @@ export function LoginPage() {
}
try {
// ✅ HttpOnly Cookie 방식: Next.js API Route로 프록시
// 토큰은 JavaScript에서 접근 불가능한 HttpOnly 쿠키로 저장됨
// 🔵 Next.js 프록시 → PHP /api/v1/login (토큰을 HttpOnly 쿠키로 저장)
const response = await fetch('/api/auth/login', {
method: 'POST',
headers: {
@@ -156,8 +158,8 @@ export function LoginPage() {
</div>
</button>
<div className="flex items-center gap-3">
<ThemeSelect />
<LanguageSelect />
<ThemeSelect native={false} />
<LanguageSelect native={false} />
<Button variant="ghost" onClick={() => router.push("/signup")} className="rounded-xl">
{t('signUp')}
</Button>

View File

@@ -127,14 +127,17 @@ export function SignupPage() {
useEffect(() => {
const checkAuth = async () => {
try {
// 🔵 Next.js 내부 API - 쿠키에서 토큰 확인 (PHP 호출 X, 성능 최적화)
const response = await fetch('/api/auth/check');
if (response.ok) {
// 이미 로그인됨 → 대시보드로 리다이렉트 (replace로 히스토리에서 제거)
router.replace('/dashboard');
return;
}
// 인증 안됨 (401) → 현재 페이지 유지
} catch {
// 인증 안됨 → 현재 페이지 유지
// API 호출 실패 → 현재 페이지 유지
} finally {
setIsChecking(false);
}
@@ -163,6 +166,7 @@ export function SignupPage() {
industry: formData.industry,
};
// 🔵 Next.js 프록시 → PHP /api/v1/register (회원가입 처리)
const response = await fetch('/api/auth/signup', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -282,8 +286,8 @@ export function SignupPage() {
</div>
</button>
<div className="flex items-center gap-3">
<ThemeSelect />
<LanguageSelect />
<ThemeSelect native={false} />
<LanguageSelect native={false} />
<Button variant="ghost" onClick={() => router.push("/login")} className="rounded-xl">
{t("login")}
</Button>