[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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user