From 95291e69225134eccd8617266120065033aeb99d Mon Sep 17 00:00:00 2001 From: "jihoon87.lee" Date: Wed, 11 Feb 2026 14:06:06 +0900 Subject: [PATCH] =?UTF-8?q?=ED=85=8C=EB=A7=88=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/(auth)/forgot-password/page.tsx | 13 +- app/(auth)/layout.tsx | 11 +- app/(auth)/login/page.tsx | 23 +- app/(auth)/reset-password/page.tsx | 7 +- app/(auth)/signup/page.tsx | 14 +- app/(home)/page.tsx | 375 +++++++++++++----- app/(main)/layout.tsx | 2 +- app/globals.css | 101 +++-- app/layout.tsx | 5 +- components/theme-toggle.tsx | 79 ++-- features/auth/components/login-form.tsx | 23 +- .../auth/components/reset-password-form.tsx | 10 +- features/auth/components/signup-form.tsx | 12 +- .../components/DashboardContainer.tsx | 203 +++++++--- .../dashboard/components/auth/KisAuthForm.tsx | 34 +- .../components/chart/StockLineChart.tsx | 202 ++++++++-- .../components/details/StockOverviewCard.tsx | 2 +- .../components/details/StockPriceBadge.tsx | 2 +- .../components/header/StockHeader.tsx | 30 +- .../components/layout/DashboardLayout.tsx | 10 +- .../dashboard/components/order/OrderForm.tsx | 104 ++--- .../components/orderbook/AnimatedQuantity.tsx | 4 +- .../components/orderbook/OrderBook.tsx | 64 +-- .../components/search/StockSearchForm.tsx | 23 +- .../components/search/StockSearchHistory.tsx | 88 ++++ features/dashboard/hooks/useStockSearch.ts | 146 +++++-- features/dashboard/types/dashboard.types.ts | 9 + features/layout/components/header.tsx | 2 +- features/layout/components/sidebar.tsx | 83 +++- lib/kis/domestic.ts | 24 +- 30 files changed, 1209 insertions(+), 496 deletions(-) create mode 100644 features/dashboard/components/search/StockSearchHistory.tsx diff --git a/app/(auth)/forgot-password/page.tsx b/app/(auth)/forgot-password/page.tsx index cb91677..13b17d3 100644 --- a/app/(auth)/forgot-password/page.tsx +++ b/app/(auth)/forgot-password/page.tsx @@ -12,6 +12,7 @@ import { } from "@/components/ui/card"; import Link from "next/link"; import { AUTH_ROUTES } from "@/features/auth/constants"; +import { Mail } from "lucide-react"; /** * [비밀번호 찾기 페이지] @@ -31,10 +32,10 @@ export default async function ForgotPasswordPage({
{message && } - + -
- MAIL +
+
비밀번호 재설정 @@ -59,13 +60,13 @@ export default async function ForgotPasswordPage({ placeholder="name@example.com" autoComplete="email" required - className="h-11 transition-all duration-200" + className="h-11 transition-all duration-200 focus-visible:ring-brand-500" />
@@ -74,7 +75,7 @@ export default async function ForgotPasswordPage({
로그인 페이지로 돌아가기 diff --git a/app/(auth)/layout.tsx b/app/(auth)/layout.tsx index c090e33..08d34de 100644 --- a/app/(auth)/layout.tsx +++ b/app/(auth)/layout.tsx @@ -12,17 +12,18 @@ export default async function AuthLayout({ } = await supabase.auth.getUser(); return ( -
+
{/* ========== 헤더 (홈 이동용) ========== */}
{/* ========== 배경 그라디언트 레이어 ========== */} -
-
+
+
{/* ========== 애니메이션 블러 효과 ========== */} -
-
+
+
+
{/* ========== 메인 콘텐츠 영역 (중앙 정렬) ========== */}
diff --git a/app/(auth)/login/page.tsx b/app/(auth)/login/page.tsx index d2e83ec..176ff3d 100644 --- a/app/(auth)/login/page.tsx +++ b/app/(auth)/login/page.tsx @@ -7,13 +7,13 @@ import { CardTitle, } from "@/components/ui/card"; import LoginForm from "@/features/auth/components/login-form"; +import { LogIn } from "lucide-react"; /** * [로그인 페이지 컴포넌트] * - * Modern UI with glassmorphism effect (유리 형태 디자인) - * - 투명 배경 + 블러 효과로 깊이감 표현 - * - 그라디언트 배경으로 생동감 추가 + * 브랜드 컬러 기반 글래스모피즘 카드 디자인 + * - 보라색 그라디언트 아이콘 배지 * - shadcn/ui 컴포넌트로 일관된 디자인 시스템 유지 * * @param searchParams - URL 쿼리 파라미터 (에러 메시지 전달용) @@ -23,36 +23,25 @@ export default async function LoginPage({ }: { searchParams: Promise<{ message: string }>; }) { - // URL에서 메시지 파라미터 추출 (로그인 실패 시 에러 메시지 표시) const { message } = await searchParams; return (
- {/* 에러/성공 메시지 표시 영역 */} - {/* URL 파라미터에 message가 있으면 표시됨 */} - {/* ========== 로그인 카드 (Glassmorphism) ========== */} - {/* bg-white/70: 70% 투명도의 흰색 배경 */} - {/* backdrop-blur-xl: 배경 블러 효과 (유리 느낌) */} - - {/* ========== 카드 헤더 영역 ========== */} + - {/* 아이콘 배경: 그라디언트 원형 */} -
- 👋 +
+
- {/* 페이지 제목 */} 환영합니다! - {/* 페이지 설명 */} 서비스 이용을 위해 로그인해 주세요. - {/* ========== 카드 콘텐츠 영역 (폼) ========== */} diff --git a/app/(auth)/reset-password/page.tsx b/app/(auth)/reset-password/page.tsx index bc04848..25b6589 100644 --- a/app/(auth)/reset-password/page.tsx +++ b/app/(auth)/reset-password/page.tsx @@ -9,6 +9,7 @@ import { } from "@/components/ui/card"; import { createClient } from "@/utils/supabase/server"; import { redirect } from "next/navigation"; +import { KeyRound } from "lucide-react"; /** * [비밀번호 재설정 페이지] @@ -39,10 +40,10 @@ export default async function ResetPasswordPage({
{message && } - + -
- PW +
+
비밀번호 재설정 diff --git a/app/(auth)/signup/page.tsx b/app/(auth)/signup/page.tsx index 21a124a..9d25de3 100644 --- a/app/(auth)/signup/page.tsx +++ b/app/(auth)/signup/page.tsx @@ -9,6 +9,7 @@ import { CardHeader, CardTitle, } from "@/components/ui/card"; +import { UserPlus } from "lucide-react"; export default async function SignupPage({ searchParams, @@ -19,13 +20,12 @@ export default async function SignupPage({ return (
- {/* 메시지 알림 */} - + -
- 🚀 +
+
회원가입 @@ -35,16 +35,14 @@ export default async function SignupPage({ - {/* ========== 폼 영역 ========== */} - {/* ========== 로그인 링크 ========== */} -

+

이미 계정이 있으신가요?{" "} 로그인 하러 가기 diff --git a/app/(home)/page.tsx b/app/(home)/page.tsx index 947a6e6..a7ed244 100644 --- a/app/(home)/page.tsx +++ b/app/(home)/page.tsx @@ -4,7 +4,15 @@ */ import Link from "next/link"; -import { ArrowRight, BarChart3, ShieldCheck, Sparkles, Zap } from "lucide-react"; +import type { LucideIcon } from "lucide-react"; +import { + Activity, + ArrowRight, + ShieldCheck, + Sparkles, + TrendingUp, + Zap, +} from "lucide-react"; import { Header } from "@/features/layout/components/header"; import { AUTH_ROUTES } from "@/features/auth/constants"; import { Button } from "@/components/ui/button"; @@ -12,6 +20,85 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import ShaderBackground from "@/components/ui/shader-background"; import { createClient } from "@/utils/supabase/server"; +interface ValuePoint { + value: string; + label: string; + detail: string; +} + +interface FeatureItem { + icon: LucideIcon; + eyebrow: string; + title: string; + description: string; +} + +interface StartStep { + step: string; + title: string; + description: string; +} + +const VALUE_POINTS: ValuePoint[] = [ + { + value: "3분", + label: "초기 세팅 시간", + detail: "복잡한 설정 대신 질문 기반으로 빠르게 시작합니다.", + }, + { + value: "24시간", + label: "실시간 시장 관제", + detail: "자리 비운 시간에도 규칙 기반으로 자동 대응합니다.", + }, + { + value: "0원", + label: "가입 시작 비용", + detail: "부담 없이 계정 생성 후 내 투자 스타일부터 점검합니다.", + }, +]; + +const FEATURE_ITEMS: FeatureItem[] = [ + { + icon: ShieldCheck, + eyebrow: "Risk Guard", + title: "손실 방어를 먼저 설계합니다", + description: + "진입보다 중요한 것은 방어입니다. 손절 기준과 노출 한도를 먼저 세워 감정 개입을 줄입니다.", + }, + { + icon: TrendingUp, + eyebrow: "Data Momentum", + title: "데이터로 타점을 좁힙니다", + description: + "실시간 데이터 흐름을 읽어 조건이 맞을 때만 실행합니다. 초보도 납득 가능한 근거를 확인할 수 있습니다.", + }, + { + icon: Zap, + eyebrow: "Auto Execution", + title: "기회가 오면 즉시 자동 실행합니다", + description: + "규칙이 충족되면 지연 없이 주문이 실행됩니다. 잠자는 시간과 업무 시간에도 전략은 멈추지 않습니다.", + }, +]; + +const START_STEPS: StartStep[] = [ + { + step: "STEP 01", + title: "계정 연결", + description: "안내에 따라 거래 계정을 안전하게 연결합니다.", + }, + { + step: "STEP 02", + title: "성향 선택", + description: "공격형·균형형·안정형 중 내 스타일을 고릅니다.", + }, + { + step: "STEP 03", + title: "자동 실행 시작", + description: "선택한 전략으로 실시간 관제를 바로 시작합니다.", + }, +]; + /** * 홈 메인 랜딩 페이지 * @returns 랜딩 UI @@ -24,138 +111,236 @@ export default async function HomePage() { data: { user }, } = await supabase.auth.getUser(); + // [CTA 분기] 로그인 여부에 따라 같은 위치에서 다른 행동으로 자연스럽게 전환합니다. + const primaryCtaHref = user ? AUTH_ROUTES.DASHBOARD : AUTH_ROUTES.SIGNUP; + const primaryCtaLabel = user ? "대시보드로 전략 실행하기" : "무료로 시작하고 첫 전략 받기"; + const secondaryCtaHref = user ? AUTH_ROUTES.DASHBOARD : AUTH_ROUTES.LOGIN; + const secondaryCtaLabel = user ? "실시간 상태 확인하기" : "기존 계정으로 로그인"; + return (

-
+
{/* ========== SHADER BACKGROUND SECTION ========== */} +