웹 디자인 전면 개편

This commit is contained in:
2026-02-17 08:15:41 +09:00
parent 7042373448
commit 028bda551f
16 changed files with 1850 additions and 1050 deletions

View File

@@ -191,14 +191,14 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
// Loading View
if (loading || checkingRecord) {
return (
<div className="bg-white rounded-3xl shadow-xl p-8 md:p-12 mb-8 animate-pulse border border-gray-100">
<div className="glass-panel-light rounded-2xl p-8 md:p-12 mb-6 animate-pulse">
<div className="flex flex-col items-center justify-center space-y-6 py-12">
<div className="w-16 h-16 border-4 border-indigo-200 border-t-indigo-600 rounded-full animate-spin"></div>
<div className="w-16 h-16 border-4 border-[#173658]/20 border-t-[#173658] rounded-full animate-spin"></div>
<div className="text-center space-y-2">
<h3 className="text-xl font-bold text-gray-800">
<h3 className="text-xl font-bold text-[#173658]">
{checkingRecord ? '기존 기록을 확인하고 있습니다...' : '사주를 분석하고 있습니다...'}
</h3>
<p className="text-gray-500">
<p className="text-[#5d6d7e]">
{checkingRecord
? '잠시만 기다려주세요.'
: <> , .<br /> .</>
@@ -214,30 +214,30 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
if (!isUnlocked) {
return (
<>
<div className="relative bg-white rounded-3xl shadow-2xl p-8 md:p-12 mb-8 border border-gray-100 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-white/80 to-white z-10 flex flex-col items-center justify-center pb-12">
<div className="text-center p-8 bg-white/90 backdrop-blur-md rounded-2xl shadow-xl border border-indigo-100 max-w-sm mx-auto">
<div className="relative glass-panel-light rounded-2xl p-8 md:p-12 mb-6 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-[#F3E7E3]/80 to-[#F3E7E3] z-10 flex flex-col items-center justify-center pb-12">
<div className="text-center p-8 bg-white/90 backdrop-blur-md rounded-2xl shadow-xl border-2 border-[#173658]/20 max-w-sm mx-auto">
<div className="text-4xl mb-4">🔐</div>
<h3 className="text-2xl font-bold text-gray-900 mb-2"> </h3>
<p className="text-gray-600 mb-2">
<h3 className="text-2xl font-bold text-[#173658] mb-2"> </h3>
<p className="text-[#5d6d7e] mb-2">
AI .
</p>
<p className="text-sm text-gray-500 mb-4">
1 | : <span className="font-bold text-indigo-600">{credits}</span>
<p className="text-sm text-[#5d6d7e] mb-4">
10 | : <span className="font-bold text-[#173658]">{credits}</span>
</p>
<button
onClick={handleTokenUse}
className="w-full bg-gradient-to-r from-indigo-600 to-purple-600 text-white font-bold py-3 px-6 rounded-xl hover:shadow-lg hover:scale-105 transition transform flex items-center justify-center gap-2"
className="w-full bg-[#173658] hover:bg-[#1e426a] text-white font-bold py-3 px-6 rounded-xl hover:shadow-lg hover:scale-105 transition transform flex items-center justify-center gap-2"
>
{credits >= 1 ? (
{credits >= 10 ? (
<>
<span> 1 </span>
<span> 10 </span>
</>
) : (
<span> </span>
)}
</button>
<p className="text-xs text-gray-400 mt-4">
<p className="text-xs text-[#5d6d7e] mt-4">
* .<br />
* .
</p>
@@ -246,8 +246,8 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
{/* Blurred Content Placeholder */}
<div className="filter blur-sm select-none opacity-50 pointer-events-none">
<h2 className="text-3xl font-bold text-gray-900 mb-8 text-center flex items-center justify-center">
<span className="text-4xl mr-3"></span>
<h2 className="text-2xl font-bold text-[#173658] mb-8 text-center flex items-center justify-center">
<span className="text-3xl mr-3"></span>
</h2>
<div className="space-y-4">
@@ -290,13 +290,13 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
const sections = interpretation ? parseSections(interpretation) : [];
return (
<div className="bg-white rounded-3xl shadow-2xl p-6 md:p-10 mb-8 border border-gray-100">
<div className="glass-panel-light rounded-2xl p-6 md:p-10 mb-6">
<div className="text-center mb-8">
<h2 className="text-3xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent mb-2">
<h2 className="text-2xl md:text-3xl font-bold gradient-text mb-2">
</h2>
<p className="text-gray-500">AI .</p>
{user && <span className="inline-block mt-2 px-3 py-1 bg-green-100 text-green-700 text-xs rounded-full"> / </span>}
<p className="text-[#5d6d7e]">AI .</p>
{user && <span className="inline-block mt-2 px-3 py-1 bg-emerald-100 text-emerald-700 text-xs rounded-full font-bold"> / </span>}
</div>
{sections.length > 0 ? (
@@ -312,18 +312,18 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
))}
</div>
) : (
<article className="prose prose-lg max-w-none prose-indigo prose-headings:text-indigo-900 prose-p:text-gray-700 prose-li:text-gray-700">
<article className="prose prose-lg max-w-none prose-headings:text-[#173658] prose-p:text-[#5d6d7e] prose-li:text-[#5d6d7e]">
<ReactMarkdown remarkPlugins={[remarkGfm]}>
{interpretation || ''}
</ReactMarkdown>
</article>
)}
<div className="mt-10 p-5 bg-indigo-50/50 rounded-2xl border border-indigo-100 flex items-start gap-4">
<div className="mt-10 p-5 bg-[#F3E7E3] rounded-2xl border-2 border-[#173658]/20 flex items-start gap-4">
<span className="text-2xl pt-1">💡</span>
<div>
<h4 className="font-bold text-indigo-900 mb-1"></h4>
<p className="text-sm text-indigo-800/80 leading-relaxed">
<h4 className="font-bold text-[#173658] mb-1"></h4>
<p className="text-sm text-[#5d6d7e] leading-relaxed">
AI를 .
,
.

161
components/Footer.tsx Normal file
View File

@@ -0,0 +1,161 @@
import Link from 'next/link';
export default function Footer() {
const currentYear = new Date().getFullYear();
return (
<footer className="bg-[#173658] text-white pt-16">
<div className="container-custom pb-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{/* 브랜드 */}
<div>
<div className="flex items-center space-x-2 mb-4">
<div className="w-10 h-10 bg-gradient-to-br from-[#d4af37] to-[#F3E7E3] rounded-lg flex items-center justify-center">
<span className="text-[#173658] text-xl font-bold"></span>
</div>
<span className="text-xl font-bold"></span>
</div>
<p className="text-gray-400 text-sm leading-relaxed">
AI와 <br />
</p>
<div className="flex space-x-3 mt-4">
<a
href="#"
className="w-9 h-9 bg-[#122a45] rounded-lg flex items-center justify-center hover:bg-[#1e426a] transition-colors"
aria-label="Facebook"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/>
</svg>
</a>
<a
href="#"
className="w-9 h-9 bg-[#122a45] rounded-lg flex items-center justify-center hover:bg-[#1e426a] transition-colors"
aria-label="Instagram"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
</svg>
</a>
<a
href="#"
className="w-9 h-9 bg-[#122a45] rounded-lg flex items-center justify-center hover:bg-[#1e426a] transition-colors"
aria-label="YouTube"
>
<svg className="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/>
</svg>
</a>
</div>
</div>
{/* 서비스 */}
<div>
<h3 className="font-bold text-lg mb-4"></h3>
<ul className="space-y-2">
<li>
<Link href="/saju" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</Link>
</li>
<li>
<Link href="/compatibility" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</Link>
</li>
<li>
<Link href="/tojeong" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</Link>
</li>
<li>
<Link href="/fortune" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</Link>
</li>
</ul>
</div>
{/* 고객 지원 */}
<div>
<h3 className="font-bold text-lg mb-4"> </h3>
<ul className="space-y-2">
<li>
<Link href="/mypage" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</Link>
</li>
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</a>
</li>
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</a>
</li>
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
1:1
</a>
</li>
</ul>
</div>
{/* 정보 */}
<div>
<h3 className="font-bold text-lg mb-4"></h3>
<ul className="space-y-2">
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</a>
</li>
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</a>
</li>
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</a>
</li>
<li>
<a href="#" className="text-gray-400 hover:text-[#d4af37] transition-colors">
</a>
</li>
</ul>
</div>
</div>
{/* 하단 정보 */}
<div className="border-t border-gray-700 mt-8 pt-8">
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
<div className="text-gray-400 text-sm text-center md:text-left">
<p>&copy; {currentYear} . All rights reserved.</p>
<p className="mt-1">사업자등록번호: 123-45-67890 | 대표: 홍길동</p>
</div>
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<svg className="w-5 h-5 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M2.166 4.999A11.954 11.954 0 0010 1.944 11.954 11.954 0 0017.834 5c.11.65.166 1.32.166 2.001 0 5.225-3.34 9.67-8 11.317C5.34 16.67 2 12.225 2 7c0-.682.057-1.35.166-2.001zm11.541 3.708a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
<span className="text-gray-400 text-sm"> </span>
</div>
<div className="flex items-center space-x-2">
<svg className="w-5 h-5 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clipRule="evenodd" />
</svg>
<span className="text-gray-400 text-sm"> </span>
</div>
</div>
</div>
</div>
</div>
</footer>
);
}

186
components/Header.tsx Normal file
View File

@@ -0,0 +1,186 @@
'use client';
import Link from 'next/link';
import { useEffect, useState } from 'react';
import { createBrowserClient } from '@supabase/ssr';
import { User } from '@supabase/supabase-js';
export default function Header() {
const [user, setUser] = useState<User | null>(null);
const [tokens, setTokens] = useState<number>(0);
const [isMenuOpen, setIsMenuOpen] = useState(false);
const supabase = createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
useEffect(() => {
const getUser = async () => {
const { data: { user } } = await supabase.auth.getUser();
setUser(user);
if (user) {
// 토큰 정보 가져오기
const { data: profile } = await supabase
.from('user_profiles')
.select('tokens')
.eq('user_id', user.id)
.single();
if (profile) {
setTokens(profile.tokens || 0);
}
}
};
getUser();
const { data: { subscription } } = supabase.auth.onAuthStateChange((_event, session) => {
setUser(session?.user ?? null);
if (!session?.user) {
setTokens(0);
}
});
return () => {
subscription.unsubscribe();
};
}, []);
return (
<header className="glass-nav fixed top-0 left-0 right-0 z-50">
<nav className="container-custom">
<div className="flex items-center justify-between h-16 md:h-20">
{/* 로고 */}
<Link href="/" className="flex items-center space-x-2 group">
<div className="w-10 h-10 bg-gradient-to-br from-[#d4af37] to-[#F3E7E3] rounded-lg flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform">
<span className="text-[#173658] text-xl font-bold"></span>
</div>
<span className="text-white text-xl md:text-2xl font-bold hidden sm:block">
</span>
</Link>
{/* 데스크탑 메뉴 */}
<div className="hidden md:flex items-center space-x-1">
<Link
href="/saju"
className="text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors font-medium"
>
</Link>
<Link
href="/compatibility"
className="text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors font-medium"
>
</Link>
<Link
href="/tojeong"
className="text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors font-medium"
>
</Link>
<Link
href="/fortune"
className="text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors font-medium"
>
</Link>
</div>
{/* 우측 사용자 메뉴 */}
<div className="flex items-center space-x-3">
{user ? (
<>
{/* 토큰 표시 */}
<div className="hidden sm:flex items-center space-x-2 bg-[#F3E7E3] px-3 py-1.5 rounded-full">
<svg className="w-5 h-5 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
<path d="M8.433 7.418c.155-.103.346-.196.567-.267v1.698a2.305 2.305 0 01-.567-.267C8.07 8.34 8 8.114 8 8c0-.114.07-.34.433-.582zM11 12.849v-1.698c.22.071.412.164.567.267.364.243.433.468.433.582 0 .114-.07.34-.433.582a2.305 2.305 0 01-.567.267z" />
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-13a1 1 0 10-2 0v.092a4.535 4.535 0 00-1.676.662C6.602 6.234 6 7.009 6 8c0 .99.602 1.765 1.324 2.246.48.32 1.054.545 1.676.662v1.941c-.391-.127-.68-.317-.843-.504a1 1 0 10-1.51 1.31c.562.649 1.413 1.076 2.353 1.253V15a1 1 0 102 0v-.092a4.535 4.535 0 001.676-.662C13.398 13.766 14 12.991 14 12c0-.99-.602-1.765-1.324-2.246A4.535 4.535 0 0011 9.092V7.151c.391.127.68.317.843.504a1 1 0 101.511-1.31c-.563-.649-1.413-1.076-2.354-1.253V5z" clipRule="evenodd" />
</svg>
<span className="text-[#173658] font-bold text-sm">{tokens}</span>
</div>
{/* 프로필 버튼 */}
<Link
href="/mypage"
className="bg-[#F3E7E3] hover:bg-[#d4af37] text-[#173658] px-4 py-2 rounded-lg transition-all font-medium text-sm shadow-md hover:shadow-lg"
>
<span className="hidden sm:inline"></span>
<span className="sm:hidden">MY</span>
</Link>
</>
) : (
<Link
href="/login"
className="bg-[#F3E7E3] hover:bg-[#d4af37] text-[#173658] px-5 py-2 rounded-lg transition-all font-bold text-sm shadow-md hover:shadow-lg"
>
</Link>
)}
{/* 모바일 메뉴 버튼 */}
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="md:hidden text-white p-2"
aria-label="메뉴 열기"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{isMenuOpen ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
</div>
</div>
{/* 모바일 메뉴 */}
{isMenuOpen && (
<div className="md:hidden pb-4 space-y-2">
<Link
href="/saju"
className="block text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors"
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/compatibility"
className="block text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors"
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/tojeong"
className="block text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors"
onClick={() => setIsMenuOpen(false)}
>
</Link>
<Link
href="/fortune"
className="block text-white hover:text-[#d4af37] px-4 py-2 rounded-lg transition-colors"
onClick={() => setIsMenuOpen(false)}
>
</Link>
{user && (
<div className="sm:hidden flex items-center space-x-2 bg-[#F3E7E3] px-4 py-2 rounded-lg mt-2">
<svg className="w-5 h-5 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
<path d="M8.433 7.418c.155-.103.346-.196.567-.267v1.698a2.305 2.305 0 01-.567-.267C8.07 8.34 8 8.114 8 8c0-.114.07-.34.433-.582zM11 12.849v-1.698c.22.071.412.164.567.267.364.243.433.468.433.582 0 .114-.07.34-.433.582a2.305 2.305 0 01-.567.267z" />
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-13a1 1 0 10-2 0v.092a4.535 4.535 0 00-1.676.662C6.602 6.234 6 7.009 6 8c0 .99.602 1.765 1.324 2.246.48.32 1.054.545 1.676.662v1.941c-.391-.127-.68-.317-.843-.504a1 1 0 10-1.51 1.31c.562.649 1.413 1.076 2.353 1.253V15a1 1 0 102 0v-.092a4.535 4.535 0 001.676-.662C13.398 13.766 14 12.991 14 12c0-.99-.602-1.765-1.324-2.246A4.535 4.535 0 0011 9.092V7.151c.391.127.68.317.843.504a1 1 0 101.511-1.31c-.563-.649-1.413-1.076-2.354-1.253V5z" clipRule="evenodd" />
</svg>
<span className="text-[#173658] font-bold">: {tokens}</span>
</div>
)}
</div>
)}
</nav>
</header>
);
}