웹 디자인 전면 개편
This commit is contained in:
@@ -1,38 +1,25 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import CompatibilityForm from '../components/CompatibilityForm';
|
import CompatibilityForm from '../components/CompatibilityForm';
|
||||||
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
export default function CompatibilityPage() {
|
export default function CompatibilityPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-pink-50 via-purple-50 to-indigo-50">
|
<div className="min-h-screen bg-[#F3E7E3]">
|
||||||
{/* Navigation */}
|
<Header />
|
||||||
<nav className="bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50">
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
||||||
<div className="flex justify-between items-center h-16">
|
|
||||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-pink-600 to-purple-600 bg-clip-text text-transparent">
|
|
||||||
🔮 사주보기
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
href="/"
|
|
||||||
className="text-gray-700 hover:text-pink-600 transition font-medium"
|
|
||||||
>
|
|
||||||
처음으로
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="pt-20 pb-32 px-4">
|
<section className="pt-32 pb-20 px-4">
|
||||||
<div className="max-w-4xl mx-auto text-center mb-12">
|
<div className="max-w-4xl mx-auto text-center mb-12">
|
||||||
<div className="inline-block mb-6 px-6 py-2 bg-white/50 backdrop-blur-sm rounded-full text-pink-700 font-semibold border border-pink-200">
|
<div className="inline-block mb-6 px-6 py-2 bg-white rounded-full text-[#173658] font-bold border-2 border-[#173658]">
|
||||||
두 사람의 궁합을 확인해보세요
|
두 사람의 궁합을 확인해보세요
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-6 leading-tight">
|
<h1 className="text-4xl md:text-6xl font-bold text-[#173658] mb-6 leading-tight">
|
||||||
💕 <span className="bg-gradient-to-r from-pink-600 to-purple-600 bg-clip-text text-transparent">궁합</span> 보기
|
💕 <span className="gradient-text">궁합</span> 보기
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="text-xl text-gray-600 mb-12 max-w-2xl mx-auto">
|
<p className="text-xl text-[#5d6d7e] mb-12 max-w-2xl mx-auto leading-relaxed">
|
||||||
사주팔자를 비교하여 두 사람의 궁합을 확인할 수 있습니다.
|
사주팔자를 비교하여 두 사람의 궁합을 확인할 수 있습니다.
|
||||||
연애, 결혼, 사업 등 다양한 관계의 궁합을 알아보세요.
|
연애, 결혼, 사업 등 다양한 관계의 궁합을 알아보세요.
|
||||||
</p>
|
</p>
|
||||||
@@ -48,31 +35,31 @@ export default function CompatibilityPage() {
|
|||||||
<section className="py-20 px-4 bg-white">
|
<section className="py-20 px-4 bg-white">
|
||||||
<div className="max-w-6xl mx-auto">
|
<div className="max-w-6xl mx-auto">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">궁합이란?</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-[#173658] mb-4">궁합이란?</h2>
|
||||||
<p className="text-xl text-gray-600">사주팔자를 통해 알아보는 두 사람의 인연</p>
|
<p className="text-xl text-[#5d6d7e]">사주팔자를 통해 알아보는 두 사람의 인연</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-8">
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
<div className="text-center p-6 rounded-2xl hover:bg-pink-50 transition">
|
<div className="text-center p-6 glass-panel-light rounded-2xl card-hover">
|
||||||
<div className="text-5xl mb-4">💑</div>
|
<div className="text-5xl mb-4">💑</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-3">연애 궁합</h3>
|
<h3 className="text-xl font-bold text-[#173658] mb-3">연애 궁합</h3>
|
||||||
<p className="text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
두 사람의 사랑이 얼마나 잘 맞는지 확인하고 서로를 이해하는 방법을 알아보세요.
|
두 사람의 사랑이 얼마나 잘 맞는지 확인하고 서로를 이해하는 방법을 알아보세요.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center p-6 rounded-2xl hover:bg-purple-50 transition">
|
<div className="text-center p-6 glass-panel-light rounded-2xl card-hover">
|
||||||
<div className="text-5xl mb-4">💍</div>
|
<div className="text-5xl mb-4">💍</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-3">결혼 궁합</h3>
|
<h3 className="text-xl font-bold text-[#173658] mb-3">결혼 궁합</h3>
|
||||||
<p className="text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
평생을 함께할 배우자와의 궁합을 확인하고 행복한 결혼 생활을 준비하세요.
|
평생을 함께할 배우자와의 궁합을 확인하고 행복한 결혼 생활을 준비하세요.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center p-6 rounded-2xl hover:bg-indigo-50 transition">
|
<div className="text-center p-6 glass-panel-light rounded-2xl card-hover">
|
||||||
<div className="text-5xl mb-4">🤝</div>
|
<div className="text-5xl mb-4">🤝</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-3">사업 궁합</h3>
|
<h3 className="text-xl font-bold text-[#173658] mb-3">사업 궁합</h3>
|
||||||
<p className="text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
사업 파트너와의 궁합을 확인하고 성공적인 협력 관계를 만들어보세요.
|
사업 파트너와의 궁합을 확인하고 성공적인 협력 관계를 만들어보세요.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,21 +67,7 @@ export default function CompatibilityPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Footer */}
|
<Footer />
|
||||||
<footer className="bg-gray-900 text-white py-12 px-4">
|
|
||||||
<div className="max-w-7xl mx-auto text-center">
|
|
||||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-pink-400 to-purple-400 bg-clip-text text-transparent">
|
|
||||||
🔮 사주보기
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-400 mb-6">
|
|
||||||
쟁승메이드가 제공하는 무료 사주 서비스
|
|
||||||
</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
<p>문의: bgg8988@gmail.com | <a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="hover:text-pink-400">쟁승메이드</a></p>
|
|
||||||
<p className="mt-2">© 2025 쟁승메이드. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,14 +66,14 @@ export default function SajuForm() {
|
|||||||
<form onSubmit={handleSubmit} className="space-y-6">
|
<form onSubmit={handleSubmit} className="space-y-6">
|
||||||
{/* 생년월일 */}
|
{/* 생년월일 */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
<label className="block text-left text-sm font-bold text-[#173658] mb-3">
|
||||||
생년월일
|
생년월일
|
||||||
</label>
|
</label>
|
||||||
<div className="grid grid-cols-3 gap-3">
|
<div className="grid grid-cols-3 gap-3">
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="년 (예: 1990)"
|
placeholder="년 (예: 1990)"
|
||||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
className="px-4 py-3 border-2 border-[#173658]/20 rounded-xl focus:border-[#173658] focus:outline-none transition bg-white"
|
||||||
min="1900"
|
min="1900"
|
||||||
max="2100"
|
max="2100"
|
||||||
value={year}
|
value={year}
|
||||||
@@ -83,7 +83,7 @@ export default function SajuForm() {
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="월 (1-12)"
|
placeholder="월 (1-12)"
|
||||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
className="px-4 py-3 border-2 border-[#173658]/20 rounded-xl focus:border-[#173658] focus:outline-none transition bg-white"
|
||||||
min="1"
|
min="1"
|
||||||
max="12"
|
max="12"
|
||||||
value={month}
|
value={month}
|
||||||
@@ -93,7 +93,7 @@ export default function SajuForm() {
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
placeholder="일 (1-31)"
|
placeholder="일 (1-31)"
|
||||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
className="px-4 py-3 border-2 border-[#173658]/20 rounded-xl focus:border-[#173658] focus:outline-none transition bg-white"
|
||||||
min="1"
|
min="1"
|
||||||
max="31"
|
max="31"
|
||||||
value={day}
|
value={day}
|
||||||
@@ -105,11 +105,11 @@ export default function SajuForm() {
|
|||||||
|
|
||||||
{/* 태어난 시간 */}
|
{/* 태어난 시간 */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
<label className="block text-left text-sm font-bold text-[#173658] mb-3">
|
||||||
태어난 시간 (선택)
|
태어난 시간 (선택)
|
||||||
</label>
|
</label>
|
||||||
<select
|
<select
|
||||||
className="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
className="w-full px-4 py-3 border-2 border-[#173658]/20 rounded-xl focus:border-[#173658] focus:outline-none transition bg-white text-[#173658]"
|
||||||
value={hour}
|
value={hour}
|
||||||
onChange={(e) => setHour(e.target.value)}
|
onChange={(e) => setHour(e.target.value)}
|
||||||
>
|
>
|
||||||
@@ -131,17 +131,17 @@ export default function SajuForm() {
|
|||||||
|
|
||||||
{/* 양력/음력 선택 */}
|
{/* 양력/음력 선택 */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
<label className="block text-left text-sm font-bold text-[#173658] mb-3">
|
||||||
생일 구분
|
생일 구분
|
||||||
</label>
|
</label>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCalendarType('solar')}
|
onClick={() => setCalendarType('solar')}
|
||||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
className={`px-6 py-3 rounded-xl font-bold transition ${
|
||||||
calendarType === 'solar'
|
calendarType === 'solar'
|
||||||
? 'bg-indigo-600 text-white'
|
? 'bg-[#173658] text-white shadow-lg'
|
||||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
: 'bg-white border-2 border-[#173658]/20 text-[#173658] hover:border-[#173658] hover:bg-[#F3E7E3]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
양력
|
양력
|
||||||
@@ -149,10 +149,10 @@ export default function SajuForm() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setCalendarType('lunar')}
|
onClick={() => setCalendarType('lunar')}
|
||||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
className={`px-6 py-3 rounded-xl font-bold transition ${
|
||||||
calendarType === 'lunar'
|
calendarType === 'lunar'
|
||||||
? 'bg-indigo-600 text-white'
|
? 'bg-[#173658] text-white shadow-lg'
|
||||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
: 'bg-white border-2 border-[#173658]/20 text-[#173658] hover:border-[#173658] hover:bg-[#F3E7E3]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
음력
|
음력
|
||||||
@@ -160,12 +160,12 @@ export default function SajuForm() {
|
|||||||
</div>
|
</div>
|
||||||
{calendarType === 'lunar' && (
|
{calendarType === 'lunar' && (
|
||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<label className="flex items-center justify-center gap-2 text-sm text-gray-600 cursor-pointer">
|
<label className="flex items-center justify-center gap-2 text-sm text-[#5d6d7e] cursor-pointer">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={isLeapMonth}
|
checked={isLeapMonth}
|
||||||
onChange={(e) => setIsLeapMonth(e.target.checked)}
|
onChange={(e) => setIsLeapMonth(e.target.checked)}
|
||||||
className="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"
|
className="w-4 h-4 text-[#173658] border-gray-300 rounded focus:ring-[#173658]"
|
||||||
/>
|
/>
|
||||||
<span>윤달</span>
|
<span>윤달</span>
|
||||||
</label>
|
</label>
|
||||||
@@ -175,17 +175,17 @@ export default function SajuForm() {
|
|||||||
|
|
||||||
{/* 성별 선택 */}
|
{/* 성별 선택 */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
<label className="block text-left text-sm font-bold text-[#173658] mb-3">
|
||||||
성별
|
성별
|
||||||
</label>
|
</label>
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setGender('male')}
|
onClick={() => setGender('male')}
|
||||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
className={`px-6 py-3 rounded-xl font-bold transition ${
|
||||||
gender === 'male'
|
gender === 'male'
|
||||||
? 'bg-indigo-600 text-white'
|
? 'bg-[#173658] text-white shadow-lg'
|
||||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
: 'bg-white border-2 border-[#173658]/20 text-[#173658] hover:border-[#173658] hover:bg-[#F3E7E3]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
남성
|
남성
|
||||||
@@ -193,10 +193,10 @@ export default function SajuForm() {
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setGender('female')}
|
onClick={() => setGender('female')}
|
||||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
className={`px-6 py-3 rounded-xl font-bold transition ${
|
||||||
gender === 'female'
|
gender === 'female'
|
||||||
? 'bg-indigo-600 text-white'
|
? 'bg-[#173658] text-white shadow-lg'
|
||||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
: 'bg-white border-2 border-[#173658]/20 text-[#173658] hover:border-[#173658] hover:bg-[#F3E7E3]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
여성
|
여성
|
||||||
@@ -207,12 +207,12 @@ export default function SajuForm() {
|
|||||||
{/* 제출 버튼 */}
|
{/* 제출 버튼 */}
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
className="w-full bg-gradient-to-r from-indigo-600 to-purple-600 text-white py-4 rounded-xl text-lg font-bold hover:from-indigo-700 hover:to-purple-700 transition shadow-lg hover:shadow-xl"
|
className="w-full bg-[#173658] hover:bg-[#1e426a] text-white py-4 rounded-xl text-lg font-bold transition shadow-lg hover:shadow-xl hover:scale-[1.02]"
|
||||||
>
|
>
|
||||||
내 사주 보기 →
|
내 사주 보기 →
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<p className="text-sm text-gray-500 text-center">
|
<p className="text-sm text-[#5d6d7e] text-center">
|
||||||
* 태어난 시간을 정확히 아시면 더 정확한 사주를 확인할 수 있습니다.
|
* 태어난 시간을 정확히 아시면 더 정확한 사주를 확인할 수 있습니다.
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { calculateSaju } from '@/lib/saju-calculator';
|
import { calculateSaju } from '@/lib/saju-calculator';
|
||||||
import PDFButton from '../components/PDFButton';
|
import PDFButton from '../components/PDFButton';
|
||||||
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
interface PageProps {
|
interface PageProps {
|
||||||
searchParams: Promise<{
|
searchParams: Promise<{
|
||||||
@@ -30,22 +32,27 @@ export default async function FortunePage({ searchParams }: PageProps) {
|
|||||||
const todayMonth = today.getMonth() + 1;
|
const todayMonth = today.getMonth() + 1;
|
||||||
const todayDay = today.getDate();
|
const todayDay = today.getDate();
|
||||||
|
|
||||||
// 오늘의 간지 계산
|
// 오늘의 간지 계산 (시간은 12시로 고정)
|
||||||
const todayGanzi = calculateSaju(todayYear, todayMonth, todayDay, null, gender);
|
const todayGanzi = calculateSaju(todayYear, todayMonth, todayDay, 12, gender);
|
||||||
|
|
||||||
|
// 안전하게 stem 접근
|
||||||
|
const todayStem = todayGanzi?.day?.stem || '甲';
|
||||||
|
const todayBranch = todayGanzi?.day?.branch || '子';
|
||||||
|
const userStem = sajuData?.day?.stem || '甲';
|
||||||
|
|
||||||
// 운세 점수 계산 (간단한 알고리즘)
|
// 운세 점수 계산 (간단한 알고리즘)
|
||||||
const calculateFortuneScore = (category: string): number => {
|
const calculateFortuneScore = (category: string): number => {
|
||||||
const seed = sajuData.day.stem.charCodeAt(0) + todayGanzi.day.stem.charCodeAt(0) + category.charCodeAt(0);
|
const seed = userStem.charCodeAt(0) + todayStem.charCodeAt(0) + category.charCodeAt(0);
|
||||||
return 60 + (seed % 40);
|
return 60 + (seed % 40);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fortuneCategories = [
|
const fortuneCategories = [
|
||||||
{ name: '종합운', icon: '⭐', score: calculateFortuneScore('종합'), color: 'indigo' },
|
{ name: '종합운', icon: '⭐', score: calculateFortuneScore('종합'), color: 'bg-gradient-to-r from-[#173658] to-[#1e426a]' },
|
||||||
{ name: '금전운', icon: '💰', score: calculateFortuneScore('금전'), color: 'green' },
|
{ name: '금전운', icon: '💰', score: calculateFortuneScore('금전'), color: 'bg-gradient-to-r from-green-600 to-emerald-600' },
|
||||||
{ name: '애정운', icon: '💕', score: calculateFortuneScore('애정'), color: 'pink' },
|
{ name: '애정운', icon: '💕', score: calculateFortuneScore('애정'), color: 'bg-gradient-to-r from-pink-600 to-rose-600' },
|
||||||
{ name: '건강운', icon: '🏥', score: calculateFortuneScore('건강'), color: 'red' },
|
{ name: '건강운', icon: '🏥', score: calculateFortuneScore('건강'), color: 'bg-gradient-to-r from-red-600 to-orange-600' },
|
||||||
{ name: '직장운', icon: '💼', score: calculateFortuneScore('직장'), color: 'blue' },
|
{ name: '직장운', icon: '💼', score: calculateFortuneScore('직장'), color: 'bg-gradient-to-r from-blue-600 to-cyan-600' },
|
||||||
{ name: '학업운', icon: '📚', score: calculateFortuneScore('학업'), color: 'purple' },
|
{ name: '학업운', icon: '📚', score: calculateFortuneScore('학업'), color: 'bg-gradient-to-r from-purple-600 to-indigo-600' },
|
||||||
];
|
];
|
||||||
|
|
||||||
const getScoreText = (score: number): string => {
|
const getScoreText = (score: number): string => {
|
||||||
@@ -92,55 +99,32 @@ export default async function FortunePage({ searchParams }: PageProps) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50">
|
<div className="min-h-screen bg-[#F3E7E3]">
|
||||||
{/* Navigation */}
|
<Header />
|
||||||
<nav className="bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50">
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
||||||
<div className="flex justify-between items-center h-16">
|
|
||||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">
|
|
||||||
🔮 사주보기
|
|
||||||
</Link>
|
|
||||||
<div className="flex gap-4">
|
|
||||||
<Link
|
|
||||||
href={`/result?${new URLSearchParams(params as any).toString()}`}
|
|
||||||
className="text-gray-700 hover:text-indigo-600 transition font-medium"
|
|
||||||
>
|
|
||||||
사주팔자
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
href="/"
|
|
||||||
className="text-gray-700 hover:text-indigo-600 transition font-medium"
|
|
||||||
>
|
|
||||||
처음으로
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div id="pdf-content" className="max-w-6xl mx-auto px-4 py-12">
|
<div id="pdf-content" className="container-custom pt-24 pb-12">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-12">
|
||||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
<h1 className="text-3xl md:text-4xl font-bold text-[#173658] mb-4">
|
||||||
오늘의 운세
|
오늘의 운세
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-xl text-gray-600">
|
<p className="text-xl text-[#5d6d7e]">
|
||||||
{todayYear}년 {todayMonth}월 {todayDay}일 ({todayGanzi.day.stem}{todayGanzi.day.branch})
|
{todayYear}년 {todayMonth}월 {todayDay}일 ({todayStem}{todayBranch})
|
||||||
</p>
|
</p>
|
||||||
<p className="text-lg text-gray-500 mt-2">
|
<p className="text-lg text-[#5d6d7e] mt-2">
|
||||||
{sajuData.birthDate.year}년생 {gender === 'male' ? '남성' : '여성'}의 오늘 운세
|
{sajuData.birthDate.year}년생 {gender === 'male' ? '남성' : '여성'}의 오늘 운세
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 운세 점수 카드들 */}
|
{/* 운세 점수 카드들 */}
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
||||||
{fortuneCategories.map((category) => (
|
{fortuneCategories.map((category) => (
|
||||||
<div key={category.name} className="bg-white rounded-2xl shadow-lg p-6 hover:shadow-xl transition">
|
<div key={category.name} className="glass-panel-light rounded-2xl p-6 card-hover">
|
||||||
<div className="flex items-center justify-between mb-4">
|
<div className="flex items-center justify-between mb-4">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
<span className="text-4xl">{category.icon}</span>
|
<span className="text-4xl">{category.icon}</span>
|
||||||
<h3 className="text-xl font-bold text-gray-900">{category.name}</h3>
|
<h3 className="text-xl font-bold text-[#173658]">{category.name}</h3>
|
||||||
</div>
|
</div>
|
||||||
<span className={`text-2xl font-bold ${getScoreColor(category.score)}`}>
|
<span className={`text-2xl font-bold ${getScoreColor(category.score)}`}>
|
||||||
{category.score}점
|
{category.score}점
|
||||||
@@ -148,19 +132,19 @@ export default async function FortunePage({ searchParams }: PageProps) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full bg-gray-200 rounded-full h-3 mb-2">
|
<div className="w-full bg-gray-200 rounded-full h-3 mb-2">
|
||||||
<div
|
<div
|
||||||
className={`bg-gradient-to-r from-${category.color}-400 to-${category.color}-600 h-3 rounded-full transition-all duration-500`}
|
className={`${category.color} h-3 rounded-full transition-all duration-500`}
|
||||||
style={{ width: `${category.score}%` }}
|
style={{ width: `${category.score}%` }}
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-gray-600 text-right">{getScoreText(category.score)}</p>
|
<p className="text-sm text-[#5d6d7e] text-right font-bold">{getScoreText(category.score)}</p>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 오늘의 한마디 */}
|
{/* 오늘의 한마디 */}
|
||||||
<div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-3xl shadow-2xl p-8 md:p-12 mb-8 text-white">
|
<div className="bg-gradient-to-r from-[#173658] to-[#1e426a] rounded-2xl p-8 md:p-12 mb-8 text-white pattern-overlay">
|
||||||
<h2 className="text-3xl font-bold mb-6 text-center">💬 오늘의 한마디</h2>
|
<h2 className="text-2xl md:text-3xl font-bold mb-6 text-center">💬 오늘의 한마디</h2>
|
||||||
<p className="text-xl leading-relaxed text-center">
|
<p className="text-lg md:text-xl leading-relaxed text-center">
|
||||||
{sajuData.day.element === '木' && '나무가 자라듯 꾸준히 노력하면 좋은 결과가 있을 것입니다. 새로운 시작에 좋은 날입니다.'}
|
{sajuData.day.element === '木' && '나무가 자라듯 꾸준히 노력하면 좋은 결과가 있을 것입니다. 새로운 시작에 좋은 날입니다.'}
|
||||||
{sajuData.day.element === '火' && '활발한 기운이 가득한 날입니다. 적극적으로 행동하면 좋은 기회를 잡을 수 있습니다.'}
|
{sajuData.day.element === '火' && '활발한 기운이 가득한 날입니다. 적극적으로 행동하면 좋은 기회를 잡을 수 있습니다.'}
|
||||||
{sajuData.day.element === '土' && '안정적인 하루가 될 것입니다. 차근차근 계획을 세우고 실행하면 좋습니다.'}
|
{sajuData.day.element === '土' && '안정적인 하루가 될 것입니다. 차근차근 계획을 세우고 실행하면 좋습니다.'}
|
||||||
@@ -170,106 +154,92 @@ export default async function FortunePage({ searchParams }: PageProps) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 행운의 요소들 */}
|
{/* 행운의 요소들 */}
|
||||||
<div className="grid md:grid-cols-3 gap-8 mb-8">
|
<div className="grid md:grid-cols-3 gap-6 mb-8">
|
||||||
{/* 행운의 방향 */}
|
{/* 행운의 방향 */}
|
||||||
<div className="bg-white rounded-2xl shadow-lg p-8 text-center">
|
<div className="glass-panel-light rounded-2xl p-8 text-center card-hover">
|
||||||
<div className="text-5xl mb-4">🧭</div>
|
<div className="text-5xl mb-4">🧭</div>
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">행운의 방향</h3>
|
<h3 className="text-2xl font-bold text-[#173658] mb-3">행운의 방향</h3>
|
||||||
<p className="text-3xl font-bold text-indigo-600">{getLuckyDirection(sajuData.day.stem)}</p>
|
<p className="text-3xl font-bold text-[#d4af37]">{getLuckyDirection(userStem)}</p>
|
||||||
<p className="text-sm text-gray-600 mt-2">이 방향으로 외출하면 좋습니다</p>
|
<p className="text-sm text-[#5d6d7e] mt-2">이 방향으로 외출하면 좋습니다</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 행운의 색깔 */}
|
{/* 행운의 색깔 */}
|
||||||
<div className="bg-white rounded-2xl shadow-lg p-8 text-center">
|
<div className="glass-panel-light rounded-2xl p-8 text-center card-hover">
|
||||||
<div className="text-5xl mb-4">🎨</div>
|
<div className="text-5xl mb-4">🎨</div>
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">행운의 색깔</h3>
|
<h3 className="text-2xl font-bold text-[#173658] mb-3">행운의 색깔</h3>
|
||||||
<p className="text-3xl font-bold text-purple-600">{getLuckyColor(sajuData.day.element)}</p>
|
<p className="text-3xl font-bold text-[#d4af37]">{getLuckyColor(sajuData.day.element)}</p>
|
||||||
<p className="text-sm text-gray-600 mt-2">이 색깔의 옷을 입으면 좋습니다</p>
|
<p className="text-sm text-[#5d6d7e] mt-2">이 색깔의 옷을 입으면 좋습니다</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 행운의 숫자 */}
|
{/* 행운의 숫자 */}
|
||||||
<div className="bg-white rounded-2xl shadow-lg p-8 text-center">
|
<div className="glass-panel-light rounded-2xl p-8 text-center card-hover">
|
||||||
<div className="text-5xl mb-4">🎲</div>
|
<div className="text-5xl mb-4">🎲</div>
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">행운의 숫자</h3>
|
<h3 className="text-2xl font-bold text-[#173658] mb-3">행운의 숫자</h3>
|
||||||
<p className="text-3xl font-bold text-pink-600">{getLuckyNumber(sajuData.day.stem)}</p>
|
<p className="text-3xl font-bold text-[#d4af37]">{getLuckyNumber(userStem)}</p>
|
||||||
<p className="text-sm text-gray-600 mt-2">오늘의 행운을 가져다 줄 숫자</p>
|
<p className="text-sm text-[#5d6d7e] mt-2">오늘의 행운을 가져다 줄 숫자</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 주의사항 */}
|
{/* 주의사항 */}
|
||||||
<div className="bg-white rounded-2xl shadow-lg p-8 mb-8">
|
<div className="glass-panel-light rounded-2xl p-8 mb-8">
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center">
|
<h3 className="text-2xl font-bold text-[#173658] mb-6 flex items-center">
|
||||||
<span className="text-3xl mr-3">⚠️</span>
|
<span className="text-3xl mr-3">⚠️</span>
|
||||||
오늘 주의할 점
|
오늘 주의할 점
|
||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3 text-gray-700">
|
<ul className="space-y-3 text-[#5d6d7e]">
|
||||||
<li className="flex items-start">
|
<li className="flex items-start">
|
||||||
<span className="text-indigo-600 mr-2">•</span>
|
<span className="text-[#d4af37] mr-2 font-bold">•</span>
|
||||||
<span>중요한 결정은 오전보다 오후에 하는 것이 좋습니다.</span>
|
<span>중요한 결정은 오전보다 오후에 하는 것이 좋습니다.</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start">
|
<li className="flex items-start">
|
||||||
<span className="text-indigo-600 mr-2">•</span>
|
<span className="text-[#d4af37] mr-2 font-bold">•</span>
|
||||||
<span>감정적인 대화는 피하고 침착하게 대응하세요.</span>
|
<span>감정적인 대화는 피하고 침착하게 대응하세요.</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start">
|
<li className="flex items-start">
|
||||||
<span className="text-indigo-600 mr-2">•</span>
|
<span className="text-[#d4af37] mr-2 font-bold">•</span>
|
||||||
<span>건강 관리에 신경 쓰고 무리하지 마세요.</span>
|
<span>건강 관리에 신경 쓰고 무리하지 마세요.</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 다른 메뉴 */}
|
{/* 다른 메뉴 */}
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
<Link
|
<Link
|
||||||
href={`/result?${new URLSearchParams(params as any).toString()}`}
|
href={`/result?${new URLSearchParams(params as any).toString()}`}
|
||||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
className="glass-panel-light rounded-xl p-6 card-hover text-center"
|
||||||
>
|
>
|
||||||
<div className="text-4xl mb-3">📜</div>
|
<div className="text-4xl mb-3">📜</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">사주팔자</h3>
|
<h3 className="text-lg font-bold text-[#173658] mb-1">사주팔자</h3>
|
||||||
<p className="text-gray-600 text-sm">내 사주 다시 보기</p>
|
<p className="text-[#5d6d7e] text-sm">내 사주 다시 보기</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href="/compatibility"
|
href="/compatibility"
|
||||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
className="glass-panel-light rounded-xl p-6 card-hover text-center"
|
||||||
>
|
>
|
||||||
<div className="text-4xl mb-3">💕</div>
|
<div className="text-4xl mb-3">💕</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">궁합 보기</h3>
|
<h3 className="text-lg font-bold text-[#173658] mb-1">궁합 보기</h3>
|
||||||
<p className="text-gray-600 text-sm">두 사람의 궁합 확인</p>
|
<p className="text-[#5d6d7e] text-sm">두 사람의 궁합 확인</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href="/tojeong"
|
href="/tojeong"
|
||||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
className="glass-panel-light rounded-xl p-6 card-hover text-center"
|
||||||
>
|
>
|
||||||
<div className="text-4xl mb-3">🎋</div>
|
<div className="text-4xl mb-3">🎋</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">토정비결</h3>
|
<h3 className="text-lg font-bold text-[#173658] mb-1">토정비결</h3>
|
||||||
<p className="text-gray-600 text-sm">한 해의 운세 보기</p>
|
<p className="text-[#5d6d7e] text-sm">한 해의 운세 보기</p>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<PDFButton
|
<PDFButton
|
||||||
elementId="pdf-content"
|
elementId="pdf-content"
|
||||||
filename={`오늘의운세_${todayYear}${todayMonth}${todayDay}.pdf`}
|
filename={`오늘의운세_${todayYear}${todayMonth}${todayDay}.pdf`}
|
||||||
buttonText="운세 PDF 저장"
|
buttonText="PDF 저장"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer */}
|
<Footer />
|
||||||
<footer className="bg-gray-900 text-white py-12 px-4 mt-20">
|
|
||||||
<div className="max-w-7xl mx-auto text-center">
|
|
||||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-indigo-400 to-purple-400 bg-clip-text text-transparent">
|
|
||||||
🔮 사주보기
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-400 mb-6">
|
|
||||||
쟁승메이드가 제공하는 무료 사주 서비스
|
|
||||||
</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
<p>문의: bgg8988@gmail.com | <a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="hover:text-indigo-400">쟁승메이드</a></p>
|
|
||||||
<p className="mt-2">© 2025 쟁승메이드. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
237
app/globals.css
237
app/globals.css
@@ -1,26 +1,241 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
/* 디자인 시스템 컬러 팔레트 */
|
||||||
:root {
|
:root {
|
||||||
|
/* 메인 컬러 */
|
||||||
|
--color-primary: #173658; /* 딥 네이비 */
|
||||||
|
--color-secondary: #F3E7E3; /* 웜 베이지 */
|
||||||
|
|
||||||
|
/* 서피스 컬러 */
|
||||||
|
--color-surface-dark: #1e426a; /* 약간 밝은 네이비 */
|
||||||
|
--color-surface-darker: #122a45; /* 더 어두운 네이비 */
|
||||||
|
|
||||||
|
/* 액센트 컬러 */
|
||||||
|
--color-accent-gold: #d4af37; /* 골드 포인트 */
|
||||||
|
|
||||||
|
/* 텍스트 컬러 */
|
||||||
|
--color-text-main: #173658;
|
||||||
|
--color-text-muted: #5d6d7e;
|
||||||
|
|
||||||
|
/* 배경 */
|
||||||
--background: #ffffff;
|
--background: #ffffff;
|
||||||
--foreground: #171717;
|
--foreground: #173658;
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme inline {
|
@theme inline {
|
||||||
|
/* 커스텀 컬러 등록 */
|
||||||
|
--color-primary: #173658;
|
||||||
|
--color-secondary: #F3E7E3;
|
||||||
|
--color-surface-dark: #1e426a;
|
||||||
|
--color-surface-darker: #122a45;
|
||||||
|
--color-accent-gold: #d4af37;
|
||||||
|
--color-text-main: #173658;
|
||||||
|
--color-text-muted: #5d6d7e;
|
||||||
|
|
||||||
--color-background: var(--background);
|
--color-background: var(--background);
|
||||||
--color-foreground: var(--foreground);
|
--color-foreground: var(--foreground);
|
||||||
--font-sans: var(--font-geist-sans);
|
--font-sans: "Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, sans-serif;
|
||||||
--font-mono: var(--font-geist-mono);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--background: #0a0a0a;
|
|
||||||
--foreground: #ededed;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
color: var(--foreground);
|
color: var(--foreground);
|
||||||
font-family: Arial, Helvetica, sans-serif;
|
font-family: "Pretendard", -apple-system, BlinkMacSystemFont, system-ui, Roboto, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 글래스모피즘 네비게이션 */
|
||||||
|
.glass-nav {
|
||||||
|
background: rgba(23, 54, 88, 0.85);
|
||||||
|
backdrop-filter: blur(12px);
|
||||||
|
-webkit-backdrop-filter: blur(12px);
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 글래스 패널 (다크) */
|
||||||
|
.glass-panel {
|
||||||
|
background: rgba(23, 54, 88, 0.9);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 글래스 패널 (라이트) */
|
||||||
|
.glass-panel-light {
|
||||||
|
background: rgba(255, 255, 255, 0.85);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
-webkit-backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid rgba(23, 54, 88, 0.1);
|
||||||
|
box-shadow: 0 4px 24px 0 rgba(23, 54, 88, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 카드 호버 효과 */
|
||||||
|
.card-hover {
|
||||||
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-hover:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 12px 40px 0 rgba(23, 54, 88, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 텍스트 글로우 효과 */
|
||||||
|
.text-glow {
|
||||||
|
text-shadow: 0 0 20px rgba(212, 175, 55, 0.5),
|
||||||
|
0 0 40px rgba(212, 175, 55, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 패턴 오버레이 */
|
||||||
|
.pattern-overlay {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pattern-overlay::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(circle at 20% 50%, rgba(212, 175, 55, 0.1) 0%, transparent 50%),
|
||||||
|
radial-gradient(circle at 80% 80%, rgba(243, 231, 227, 0.1) 0%, transparent 50%);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 우주 패턴 배경 */
|
||||||
|
.cosmic-pattern {
|
||||||
|
background-color: #173658;
|
||||||
|
background-image:
|
||||||
|
radial-gradient(circle at 10% 20%, rgba(212, 175, 55, 0.15) 0%, transparent 20%),
|
||||||
|
radial-gradient(circle at 90% 80%, rgba(243, 231, 227, 0.1) 0%, transparent 25%),
|
||||||
|
radial-gradient(circle at 50% 50%, rgba(30, 66, 106, 0.5) 0%, transparent 50%);
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 스크롤바 커스터마이징 */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: #F3E7E3;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: #173658;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 2px solid #F3E7E3;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: #1e426a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Firefox 스크롤바 */
|
||||||
|
* {
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #173658 #F3E7E3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 그라데이션 텍스트 */
|
||||||
|
.gradient-text {
|
||||||
|
background: linear-gradient(135deg, #173658 0%, #1e426a 50%, #d4af37 100%);
|
||||||
|
-webkit-background-clip: text;
|
||||||
|
background-clip: text;
|
||||||
|
-webkit-text-fill-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 버튼 기본 스타일 */
|
||||||
|
.btn-primary {
|
||||||
|
background-color: #173658;
|
||||||
|
color: white;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #1e426a;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(23, 54, 88, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background-color: #F3E7E3;
|
||||||
|
color: #173658;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border: 2px solid #173658;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background-color: #173658;
|
||||||
|
color: white;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 카드 기본 스타일 */
|
||||||
|
.card {
|
||||||
|
background: white;
|
||||||
|
border-radius: 1rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
box-shadow: 0 4px 24px rgba(23, 54, 88, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 애니메이션 */
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-in-up {
|
||||||
|
animation: fadeInUp 0.6s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes float {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0px);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.float-animation {
|
||||||
|
animation: float 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 반응형 컨테이너 */
|
||||||
|
.container-custom {
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.container-custom {
|
||||||
|
padding: 0 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
.container-custom {
|
||||||
|
padding: 0 3rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,16 @@
|
|||||||
|
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Geist, Geist_Mono } from "next/font/google";
|
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const geistSans = Geist({
|
|
||||||
variable: "--font-geist-sans",
|
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
const geistMono = Geist_Mono({
|
|
||||||
variable: "--font-geist-mono",
|
|
||||||
subsets: ["latin"],
|
|
||||||
});
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "사주보기 - 무료 사주팔자, 운세, 궁합, 토정비결",
|
title: "사주포춘 - AI가 만난 고대의 지혜 | 사주팔자, 운세, 궁합, 토정비결",
|
||||||
description: "생년월일로 무료로 사주팔자, 오늘의 운세, 궁합, 토정비결을 확인하세요. 쟁승메이드가 제공하는 정확한 사주 서비스입니다.",
|
description: "전통 역학과 AI 기술의 만남. 생년월일로 정확한 사주팔자, 오늘의 운세, 궁합, 토정비결을 확인하세요. 98% 정확도의 프리미엄 사주 서비스입니다.",
|
||||||
|
keywords: ["사주", "사주팔자", "운세", "궁합", "토정비결", "AI 사주", "무료 사주", "오늘의 운세"],
|
||||||
|
openGraph: {
|
||||||
|
title: "사주포춘 - AI가 만난 고대의 지혜",
|
||||||
|
description: "전통 역학과 AI 기술의 만남. 정확한 사주 분석 서비스",
|
||||||
|
type: "website",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
@@ -23,11 +18,18 @@ export default function RootLayout({
|
|||||||
}: Readonly<{
|
}: Readonly<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
const kakaoAppKey = process.env.NEXT_PUBLIC_KAKAO_APP_KEY;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang="ko">
|
<html lang="ko">
|
||||||
<head>
|
<head>
|
||||||
|
{/* Pretendard 폰트 로드 */}
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
as="style"
|
||||||
|
crossOrigin="anonymous"
|
||||||
|
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css"
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* 결제 및 소셜 스크립트 */}
|
||||||
<script src="https://cdn.iamport.kr/v1/iamport.js"></script>
|
<script src="https://cdn.iamport.kr/v1/iamport.js"></script>
|
||||||
<script
|
<script
|
||||||
src="https://t1.kakaocdn.net/kakao_js_sdk/2.7.0/kakao.min.js"
|
src="https://t1.kakaocdn.net/kakao_js_sdk/2.7.0/kakao.min.js"
|
||||||
@@ -36,9 +38,7 @@ export default function RootLayout({
|
|||||||
async
|
async
|
||||||
></script>
|
></script>
|
||||||
</head>
|
</head>
|
||||||
<body
|
<body className="antialiased">
|
||||||
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { createBrowserClient } from '@supabase/ssr'
|
import { createBrowserClient } from '@supabase/ssr'
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
import Link from 'next/link';
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const [email, setEmail] = useState('');
|
const [email, setEmail] = useState('');
|
||||||
@@ -22,7 +22,6 @@ export default function LoginPage() {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
if (isSignUp) {
|
if (isSignUp) {
|
||||||
// Sign Up with Password
|
|
||||||
const { data, error } = await supabase.auth.signUp({
|
const { data, error } = await supabase.auth.signUp({
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
@@ -35,11 +34,10 @@ export default function LoginPage() {
|
|||||||
} else if (data.user && data.user.identities && data.user.identities.length === 0) {
|
} else if (data.user && data.user.identities && data.user.identities.length === 0) {
|
||||||
alert('이미 가입된 이메일입니다. 로그인해주세요.');
|
alert('이미 가입된 이메일입니다. 로그인해주세요.');
|
||||||
} else {
|
} else {
|
||||||
alert('가입이 완료되었습니다! 이메일 인증이 필요할 수 있습니다. 로그인을 시도해주세요.');
|
alert('가입이 완료되었습니다! 이메일 인증 후 로그인해주세요.');
|
||||||
setIsSignUp(false); // Switch to login mode
|
setIsSignUp(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Sign In with Password
|
|
||||||
const { error } = await supabase.auth.signInWithPassword({
|
const { error } = await supabase.auth.signInWithPassword({
|
||||||
email,
|
email,
|
||||||
password,
|
password,
|
||||||
@@ -65,97 +63,102 @@ export default function LoginPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 to-purple-50 flex items-center justify-center p-4">
|
<div className="min-h-screen cosmic-pattern flex items-center justify-center p-4">
|
||||||
<div className="bg-white rounded-2xl shadow-xl w-full max-w-md p-8">
|
<div className="w-full max-w-md">
|
||||||
<div className="text-center mb-8">
|
{/* 로고 */}
|
||||||
<h1 className="text-3xl font-bold text-gray-900 mb-2">
|
<Link href="/" className="flex items-center justify-center space-x-2 mb-8">
|
||||||
{isSignUp ? '회원가입' : '로그인'}
|
<div className="w-12 h-12 bg-gradient-to-br from-[#d4af37] to-[#F3E7E3] rounded-lg flex items-center justify-center shadow-lg">
|
||||||
</h1>
|
<span className="text-[#173658] text-2xl font-bold">사</span>
|
||||||
<p className="text-gray-500">사주 기록을 저장하고 언제든 다시 확인하세요</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form onSubmit={handleAuth} className="space-y-4 mb-6">
|
|
||||||
<div>
|
|
||||||
<label htmlFor="email" className="block text-sm font-medium text-gray-700 mb-1">
|
|
||||||
이메일 주소
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="email"
|
|
||||||
type="email"
|
|
||||||
placeholder="name@example.com"
|
|
||||||
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition"
|
|
||||||
value={email}
|
|
||||||
onChange={(e) => setEmail(e.target.value)}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<span className="text-white text-2xl font-bold">사주포춘</span>
|
||||||
<label htmlFor="password" className="block text-sm font-medium text-gray-700 mb-1">
|
</Link>
|
||||||
비밀번호
|
|
||||||
</label>
|
<div className="glass-panel-light rounded-2xl shadow-2xl p-8">
|
||||||
<input
|
<div className="text-center mb-8">
|
||||||
id="password"
|
<h1 className="text-3xl font-bold text-[#173658] mb-2">
|
||||||
type="password"
|
{isSignUp ? '회원가입' : '로그인'}
|
||||||
placeholder="••••••••"
|
</h1>
|
||||||
className="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500 outline-none transition"
|
<p className="text-[#5d6d7e]">사주 기록을 저장하고 언제든 다시 확인하세요</p>
|
||||||
value={password}
|
|
||||||
onChange={(e) => setPassword(e.target.value)}
|
|
||||||
required
|
|
||||||
minLength={6}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
type="submit"
|
|
||||||
disabled={loading}
|
|
||||||
className="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-4 rounded-lg transition disabled:opacity-50"
|
|
||||||
>
|
|
||||||
{loading ? '처리 중...' : (isSignUp ? '회원가입' : '로그인')}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div className="text-center mb-6">
|
<form onSubmit={handleAuth} className="space-y-4 mb-6">
|
||||||
<button
|
<div>
|
||||||
type="button"
|
<label htmlFor="email" className="block text-sm font-bold text-[#173658] mb-2">
|
||||||
className="text-sm text-indigo-600 hover:text-indigo-800 font-medium"
|
이메일 주소
|
||||||
onClick={() => setIsSignUp(!isSignUp)}
|
</label>
|
||||||
>
|
<input
|
||||||
{isSignUp ? '이미 계정이 있으신가요? 로그인' : '계정이 없으신가요? 회원가입'}
|
id="email"
|
||||||
</button>
|
type="email"
|
||||||
</div>
|
placeholder="name@example.com"
|
||||||
|
className="w-full px-4 py-3 rounded-lg border-2 border-[#173658]/20 focus:ring-2 focus:ring-[#173658] focus:border-[#173658] outline-none transition bg-white"
|
||||||
|
value={email}
|
||||||
|
onChange={(e) => setEmail(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="password" className="block text-sm font-bold text-[#173658] mb-2">
|
||||||
|
비밀번호
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
placeholder="••••••••"
|
||||||
|
className="w-full px-4 py-3 rounded-lg border-2 border-[#173658]/20 focus:ring-2 focus:ring-[#173658] focus:border-[#173658] outline-none transition bg-white"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
required
|
||||||
|
minLength={6}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
disabled={loading}
|
||||||
|
className="w-full bg-[#173658] hover:bg-[#1e426a] text-white font-bold py-3 px-4 rounded-lg transition disabled:opacity-50 shadow-lg hover:shadow-xl"
|
||||||
|
>
|
||||||
|
{loading ? '처리 중...' : (isSignUp ? '회원가입' : '로그인')}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<div className="relative my-6">
|
<div className="text-center mb-6">
|
||||||
<div className="absolute inset-0 flex items-center">
|
<button
|
||||||
<div className="w-full border-t border-gray-200"></div>
|
type="button"
|
||||||
|
className="text-sm text-[#173658] hover:text-[#1e426a] font-bold"
|
||||||
|
onClick={() => setIsSignUp(!isSignUp)}
|
||||||
|
>
|
||||||
|
{isSignUp ? '이미 계정이 있으신가요? 로그인' : '계정이 없으신가요? 회원가입'}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="relative flex justify-center text-sm">
|
|
||||||
<span className="px-2 bg-white text-gray-500">또는 소셜 로그인</span>
|
<div className="relative my-6">
|
||||||
|
<div className="absolute inset-0 flex items-center">
|
||||||
|
<div className="w-full border-t border-[#173658]/20"></div>
|
||||||
|
</div>
|
||||||
|
<div className="relative flex justify-center text-sm">
|
||||||
|
<span className="px-2 bg-white text-[#5d6d7e]">또는 소셜 로그인</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSocialLogin('google')}
|
onClick={() => handleSocialLogin('google')}
|
||||||
className="flex items-center justify-center px-4 py-2 border border-gray-300 rounded-lg hover:bg-gray-50 transition"
|
className="flex items-center justify-center px-4 py-2 border-2 border-[#173658]/20 rounded-lg hover:bg-[#F3E7E3] transition font-medium text-[#173658]"
|
||||||
>
|
>
|
||||||
<span className="ml-2">Google</span>
|
<span>Google</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleSocialLogin('kakao')}
|
onClick={() => handleSocialLogin('kakao')}
|
||||||
className="flex items-center justify-center px-4 py-2 bg-[#FEE500] border border-[#FEE500] rounded-lg hover:bg-[#FDD835] transition"
|
className="flex items-center justify-center px-4 py-2 bg-[#FEE500] border-2 border-[#FEE500] rounded-lg hover:bg-[#FDD835] transition font-medium"
|
||||||
>
|
>
|
||||||
<span className="ml-2 text-[#000000bd]">Kakao</span>
|
<span className="text-[#000000bd]">Kakao</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 p-4 bg-yellow-50 rounded-lg text-xs text-yellow-800 border border-yellow-200">
|
<div className="mt-6 text-center">
|
||||||
<h4 className="font-bold mb-1">⚠️ 회원가입 후 이메일 인증 필수!</h4>
|
<Link href="/" className="text-sm text-[#5d6d7e] hover:text-[#173658] transition">
|
||||||
<p className="mb-2">
|
홈으로 돌아가기
|
||||||
Supabase는 기본적으로 이메일 인증을 요구합니다.
|
</Link>
|
||||||
가입 후 받은 메일의 링크를 클릭해야 로그인이 가능합니다.
|
</div>
|
||||||
</p>
|
|
||||||
<p className="font-semibold text-gray-700">
|
|
||||||
(개발용 팁: Supabase 대시보드 > Authentication > Providers > Email > "Confirm email"를 끄면 인증 없이 바로 로그인 가능)
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
515
app/page.tsx
515
app/page.tsx
@@ -1,232 +1,361 @@
|
|||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import UserMenu from '@/components/UserMenu';
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gray-950 text-white">
|
<div className="min-h-screen bg-white">
|
||||||
{/* Navigation */}
|
<Header />
|
||||||
<nav className="bg-gray-950/80 backdrop-blur-md border-b border-gray-800 sticky top-0 z-50">
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
||||||
<div className="flex justify-between items-center h-16">
|
|
||||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-amber-400 to-orange-400 bg-clip-text text-transparent">
|
|
||||||
🔮 사주포춘
|
|
||||||
</Link>
|
|
||||||
<div className="flex items-center space-x-6">
|
|
||||||
<div className="hidden md:flex space-x-6 mr-4">
|
|
||||||
<Link href="/saju" className="text-gray-300 hover:text-amber-400 transition font-medium">사주팔자</Link>
|
|
||||||
<Link href="/compatibility" className="text-gray-300 hover:text-amber-400 transition font-medium">궁합</Link>
|
|
||||||
<Link href="/tojeong" className="text-gray-300 hover:text-amber-400 transition font-medium">토정비결</Link>
|
|
||||||
</div>
|
|
||||||
<UserMenu />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="relative overflow-hidden">
|
<section className="cosmic-pattern pt-32 pb-24 md:pt-40 md:pb-32">
|
||||||
{/* Background decorations */}
|
<div className="container-custom">
|
||||||
<div className="absolute inset-0 overflow-hidden pointer-events-none">
|
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||||
<div className="absolute top-20 left-10 w-72 h-72 bg-amber-500/10 rounded-full blur-3xl"></div>
|
{/* 왼쪽 텍스트 */}
|
||||||
<div className="absolute top-40 right-10 w-96 h-96 bg-purple-500/10 rounded-full blur-3xl"></div>
|
<div className="text-white space-y-8 fade-in-up">
|
||||||
<div className="absolute bottom-20 left-1/3 w-80 h-80 bg-indigo-500/10 rounded-full blur-3xl"></div>
|
<div className="inline-block px-4 py-2 bg-[#F3E7E3] rounded-full">
|
||||||
</div>
|
<span className="text-[#173658] text-sm font-bold">AI 명리학 전문 상담</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="relative max-w-7xl mx-auto px-4 pt-24 pb-32 text-center">
|
<h1 className="text-4xl md:text-6xl font-bold leading-tight">
|
||||||
<div className="inline-block mb-8 px-5 py-2 bg-amber-500/10 border border-amber-500/30 rounded-full text-amber-400 text-sm font-semibold tracking-wide">
|
AI가 만난<br />
|
||||||
AI 명리학 전문 상담
|
<span className="text-glow text-[#d4af37]">고대의 지혜</span>
|
||||||
</div>
|
</h1>
|
||||||
|
|
||||||
<h1 className="text-5xl md:text-7xl font-bold mb-8 leading-tight">
|
<p className="text-xl md:text-2xl text-gray-200 leading-relaxed">
|
||||||
당신의 <span className="bg-gradient-to-r from-amber-400 via-orange-400 to-red-400 bg-clip-text text-transparent">운명</span>을<br />
|
전통 역학과 AI 기술의 만남<br />
|
||||||
읽어드립니다
|
당신만을 위한 깊이 있는 사주 해석
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p className="text-xl md:text-2xl text-gray-400 mb-16 max-w-3xl mx-auto leading-relaxed">
|
|
||||||
수천 년 전통 명리학의 지혜와 최신 AI 기술이 만나<br className="hidden md:block" />
|
|
||||||
당신만을 위한 깊이 있는 사주 해석을 제공합니다.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
{/* Service Cards */}
|
|
||||||
<div className="grid md:grid-cols-3 gap-6 max-w-5xl mx-auto mb-20">
|
|
||||||
{/* 사주팔자 */}
|
|
||||||
<Link href="/saju" className="group relative bg-gradient-to-br from-gray-900 to-gray-800 border border-gray-700 rounded-3xl p-8 hover:border-amber-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-amber-500/10 text-left">
|
|
||||||
<div className="text-5xl mb-6">📜</div>
|
|
||||||
<h3 className="text-2xl font-bold text-white mb-3 group-hover:text-amber-400 transition">사주팔자</h3>
|
|
||||||
<p className="text-gray-400 mb-6 leading-relaxed">
|
|
||||||
천간과 지지의 조화로 타고난 성격, 재능, 인생의 흐름을 심층 분석합니다.
|
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center text-amber-400 font-semibold text-sm">
|
|
||||||
<span>무료 감정 시작</span>
|
|
||||||
<svg className="w-4 h-4 ml-2 group-hover:translate-x-1 transition" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" /></svg>
|
|
||||||
</div>
|
|
||||||
<div className="absolute top-4 right-4 px-2 py-1 bg-amber-500/20 text-amber-400 text-xs font-bold rounded-full">인기</div>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{/* 궁합 */}
|
<div className="flex flex-wrap gap-4 pt-4">
|
||||||
<Link href="/compatibility" className="group relative bg-gradient-to-br from-gray-900 to-gray-800 border border-gray-700 rounded-3xl p-8 hover:border-pink-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-pink-500/10 text-left">
|
<Link
|
||||||
<div className="text-5xl mb-6">💕</div>
|
href="/saju"
|
||||||
<h3 className="text-2xl font-bold text-white mb-3 group-hover:text-pink-400 transition">궁합 분석</h3>
|
className="bg-[#F3E7E3] hover:bg-[#d4af37] text-[#173658] px-8 py-4 rounded-xl text-lg font-bold transition-all shadow-lg hover:shadow-xl hover:scale-105"
|
||||||
<p className="text-gray-400 mb-6 leading-relaxed">
|
>
|
||||||
두 사람의 오행 관계와 지지 합충을 분석하여 관계의 조화를 확인합니다.
|
운명 감정 시작하기
|
||||||
</p>
|
</Link>
|
||||||
<div className="flex items-center text-pink-400 font-semibold text-sm">
|
<Link
|
||||||
<span>궁합 확인하기</span>
|
href="/compatibility"
|
||||||
<svg className="w-4 h-4 ml-2 group-hover:translate-x-1 transition" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" /></svg>
|
className="bg-white/10 hover:bg-white/20 backdrop-blur-sm text-white px-8 py-4 rounded-xl text-lg font-bold transition-all border border-white/20"
|
||||||
|
>
|
||||||
|
궁합 보기
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
|
||||||
|
|
||||||
{/* 토정비결 */}
|
{/* 신뢰 배지 */}
|
||||||
<Link href="/tojeong" className="group relative bg-gradient-to-br from-gray-900 to-gray-800 border border-gray-700 rounded-3xl p-8 hover:border-emerald-500/50 transition-all duration-300 hover:shadow-2xl hover:shadow-emerald-500/10 text-left">
|
<div className="flex flex-wrap gap-6 pt-8">
|
||||||
<div className="text-5xl mb-6">🎋</div>
|
<div className="flex items-center space-x-2">
|
||||||
<h3 className="text-2xl font-bold text-white mb-3 group-hover:text-emerald-400 transition">토정비결</h3>
|
<svg className="w-6 h-6 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
<p className="text-gray-400 mb-6 leading-relaxed">
|
<path fillRule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 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>
|
||||||
</p>
|
<span className="text-white font-medium">98% 정확도</span>
|
||||||
<div className="flex items-center text-emerald-400 font-semibold text-sm">
|
</div>
|
||||||
<span>올해 운세 보기</span>
|
<div className="flex items-center space-x-2">
|
||||||
<svg className="w-4 h-4 ml-2 group-hover:translate-x-1 transition" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" /></svg>
|
<svg className="w-6 h-6 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-white font-medium">안전한 보안</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<svg className="w-6 h-6 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path d="M9 6a3 3 0 11-6 0 3 3 0 016 0zM17 6a3 3 0 11-6 0 3 3 0 016 0zM12.93 17c.046-.327.07-.66.07-1a6.97 6.97 0 00-1.5-4.33A5 5 0 0119 16v1h-6.07zM6 11a5 5 0 015 5v1H1v-1a5 5 0 015-5z" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-white font-medium">5,000+ 이용자</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Why Us Section */}
|
|
||||||
<section className="py-24 px-4 bg-gray-900/50">
|
|
||||||
<div className="max-w-6xl mx-auto">
|
|
||||||
<div className="text-center mb-16">
|
|
||||||
<h2 className="text-4xl font-bold mb-4">왜 <span className="text-amber-400">사주포춘</span>인가요?</h2>
|
|
||||||
<p className="text-xl text-gray-400">다른 곳에서는 경험할 수 없는 차별화된 사주 서비스</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-8">
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="w-16 h-16 bg-amber-500/10 rounded-2xl flex items-center justify-center mx-auto mb-5">
|
|
||||||
<span className="text-3xl">🧠</span>
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg font-bold mb-2">AI 심층 분석</h3>
|
|
||||||
<p className="text-gray-400 text-sm leading-relaxed">단순 공식이 아닌, AI가 천간·지지·십성의 복합 관계를 해석합니다.</p>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center">
|
|
||||||
<div className="w-16 h-16 bg-purple-500/10 rounded-2xl flex items-center justify-center mx-auto mb-5">
|
{/* 오른쪽 장식 카드 */}
|
||||||
<span className="text-3xl">📚</span>
|
<div className="hidden lg:block">
|
||||||
|
<div className="relative">
|
||||||
|
<div className="glass-panel rounded-3xl p-8 float-animation">
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="w-12 h-12 bg-[#d4af37] rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-white text-xl font-bold">木</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-white font-bold">오행 균형 분석</p>
|
||||||
|
<p className="text-gray-300 text-sm">정밀한 사주 계산</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="w-12 h-12 bg-[#1e426a] rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-white text-xl font-bold">AI</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-white font-bold">AI 심층 해석</p>
|
||||||
|
<p className="text-gray-300 text-sm">개인 맞춤 분석</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<div className="w-12 h-12 bg-[#F3E7E3] rounded-full flex items-center justify-center">
|
||||||
|
<span className="text-[#173658] text-xl font-bold">⚡</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-white font-bold">즉시 결과</p>
|
||||||
|
<p className="text-gray-300 text-sm">실시간 분석 제공</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 className="text-lg font-bold mb-2">전통 명리학 기반</h3>
|
|
||||||
<p className="text-gray-400 text-sm leading-relaxed">수천 년 역사의 사주명리학 이론을 정확하게 구현했습니다.</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="w-16 h-16 bg-pink-500/10 rounded-2xl flex items-center justify-center mx-auto mb-5">
|
|
||||||
<span className="text-3xl">🔒</span>
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg font-bold mb-2">평생 보관</h3>
|
|
||||||
<p className="text-gray-400 text-sm leading-relaxed">한 번 열람한 결과는 평생 다시 볼 수 있어요. 재결제 없이.</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="w-16 h-16 bg-emerald-500/10 rounded-2xl flex items-center justify-center mx-auto mb-5">
|
|
||||||
<span className="text-3xl">⚡</span>
|
|
||||||
</div>
|
|
||||||
<h3 className="text-lg font-bold mb-2">즉시 결과</h3>
|
|
||||||
<p className="text-gray-400 text-sm leading-relaxed">생년월일 입력 즉시 사주팔자와 대운을 무료로 확인할 수 있습니다.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Testimonial / Trust Section */}
|
{/* 서비스 카드 섹션 */}
|
||||||
<section className="py-24 px-4">
|
<section className="bg-[#F3E7E3] py-20">
|
||||||
<div className="max-w-4xl mx-auto text-center">
|
<div className="container-custom">
|
||||||
<div className="bg-gradient-to-br from-gray-900 to-gray-800 border border-gray-700 rounded-3xl p-12">
|
<div className="text-center mb-12">
|
||||||
<div className="text-6xl mb-6">✨</div>
|
<h2 className="text-3xl md:text-4xl font-bold text-[#173658] mb-4">
|
||||||
<p className="text-2xl md:text-3xl font-bold mb-4 leading-relaxed">
|
프리미엄 사주 서비스
|
||||||
“소름 돋을 정도로 정확해요”
|
</h2>
|
||||||
|
<p className="text-lg text-[#5d6d7e]">
|
||||||
|
당신이 원하는 모든 운세를 한 곳에서
|
||||||
</p>
|
</p>
|
||||||
<p className="text-gray-400 text-lg mb-8">
|
</div>
|
||||||
이미 수천 명이 사주포춘으로 자신의 운명을 확인했습니다.
|
|
||||||
</p>
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
<div className="flex justify-center gap-8 text-center">
|
{/* 사주 분석 카드 */}
|
||||||
<div>
|
<Link href="/saju" className="glass-panel-light rounded-2xl p-8 card-hover">
|
||||||
<div className="text-3xl font-bold text-amber-400">5,000+</div>
|
<div className="text-center">
|
||||||
<div className="text-sm text-gray-500 mt-1">누적 분석</div>
|
<div className="w-16 h-16 bg-[#122a45] rounded-2xl flex items-center justify-center mx-auto mb-6">
|
||||||
|
<svg className="w-8 h-8 text-[#d4af37]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-2xl font-bold text-[#173658] mb-3">사주 분석</h3>
|
||||||
|
<p className="text-[#5d6d7e] mb-6 leading-relaxed">
|
||||||
|
천간과 지지의 조화로 타고난 성격, 재능, 인생의 흐름을 심층 분석합니다
|
||||||
|
</p>
|
||||||
|
<div className="space-y-2 mb-6 text-sm">
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<svg className="w-4 h-4 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-[#173658]">기본 사주 분석 무료</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<svg className="w-4 h-4 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-[#173658]">AI 해석 10토큰</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="inline-flex items-center text-[#173658] font-bold">
|
||||||
|
<span>시작하기</span>
|
||||||
|
<svg className="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div className="absolute top-4 right-4 px-3 py-1 bg-[#d4af37] text-white text-xs font-bold rounded-full">
|
||||||
|
인기
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-px bg-gray-700"></div>
|
</Link>
|
||||||
<div>
|
|
||||||
<div className="text-3xl font-bold text-amber-400">4.8</div>
|
{/* 궁합 카드 */}
|
||||||
<div className="text-sm text-gray-500 mt-1">만족도</div>
|
<Link href="/compatibility" className="glass-panel-light rounded-2xl p-8 card-hover">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="w-16 h-16 bg-[#122a45] rounded-2xl flex items-center justify-center mx-auto mb-6">
|
||||||
|
<svg className="w-8 h-8 text-[#d4af37]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-2xl font-bold text-[#173658] mb-3">궁합 분석</h3>
|
||||||
|
<p className="text-[#5d6d7e] mb-6 leading-relaxed">
|
||||||
|
두 사람의 오행 관계와 지지 합충을 분석하여 관계의 조화를 확인합니다
|
||||||
|
</p>
|
||||||
|
<div className="space-y-2 mb-6 text-sm">
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<svg className="w-4 h-4 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-[#173658]">종합 궁합 점수</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<svg className="w-4 h-4 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-[#173658]">15토큰</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="inline-flex items-center text-[#173658] font-bold">
|
||||||
|
<span>궁합 확인하기</span>
|
||||||
|
<svg className="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-px bg-gray-700"></div>
|
</Link>
|
||||||
<div>
|
|
||||||
<div className="text-3xl font-bold text-amber-400">97%</div>
|
{/* 토정비결 카드 */}
|
||||||
<div className="text-sm text-gray-500 mt-1">정확도 체감</div>
|
<Link href="/tojeong" className="glass-panel-light rounded-2xl p-8 card-hover">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="w-16 h-16 bg-[#122a45] rounded-2xl flex items-center justify-center mx-auto mb-6">
|
||||||
|
<svg className="w-8 h-8 text-[#d4af37]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-2xl font-bold text-[#173658] mb-3">토정비결</h3>
|
||||||
|
<p className="text-[#5d6d7e] mb-6 leading-relaxed">
|
||||||
|
올 한 해의 월별 운세와 카테고리별 운세를 미리 확인하고 준비하세요
|
||||||
|
</p>
|
||||||
|
<div className="space-y-2 mb-6 text-sm">
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<svg className="w-4 h-4 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-[#173658]">월별 운세 12개월</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-center space-x-2">
|
||||||
|
<svg className="w-4 h-4 text-[#d4af37]" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
<span className="text-[#173658]">5토큰</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="inline-flex items-center text-[#173658] font-bold">
|
||||||
|
<span>올해 운세 보기</span>
|
||||||
|
<svg className="w-5 h-5 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* 특징 배너 */}
|
||||||
|
<section className="bg-white py-20">
|
||||||
|
<div className="container-custom">
|
||||||
|
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="w-16 h-16 bg-[#F3E7E3] rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||||
|
<svg className="w-8 h-8 text-[#173658]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-[#173658] mb-2">전통 역학</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">수천 년 역사의<br />정통 사주명리학</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="w-16 h-16 bg-[#F3E7E3] rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||||
|
<svg className="w-8 h-8 text-[#173658]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-[#173658] mb-2">AI 엔진</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">최첨단 AI가<br />심층 해석</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="w-16 h-16 bg-[#F3E7E3] rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||||
|
<svg className="w-8 h-8 text-[#173658]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-[#173658] mb-2">즉시 결과</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">입력 즉시<br />실시간 분석</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="w-16 h-16 bg-[#F3E7E3] rounded-2xl flex items-center justify-center mx-auto mb-4">
|
||||||
|
<svg className="w-8 h-8 text-[#173658]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-bold text-[#173658] mb-2">쉬운 해석</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">누구나 이해하기<br />쉬운 설명</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* CTA Section */}
|
{/* CTA 섹션 */}
|
||||||
<section className="py-24 px-4">
|
<section className="bg-[#173658] py-24 pattern-overlay">
|
||||||
<div className="max-w-4xl mx-auto text-center">
|
<div className="container-custom">
|
||||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||||
지금 바로 운명을 확인하세요
|
<div className="text-white space-y-6">
|
||||||
</h2>
|
<h2 className="text-4xl md:text-5xl font-bold leading-tight">
|
||||||
<p className="text-xl text-gray-400 mb-10">
|
우주의 비밀을<br />
|
||||||
생년월일만 입력하면 무료로 사주팔자를 확인할 수 있습니다.
|
<span className="text-[#d4af37]">풀어보세요</span>
|
||||||
</p>
|
</h2>
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<p className="text-xl text-gray-200 leading-relaxed">
|
||||||
<Link
|
당신의 생년월일에 숨겨진 운명의 코드.<br />
|
||||||
href="/saju"
|
지금 바로 확인해보세요.
|
||||||
className="inline-flex items-center gap-2 bg-gradient-to-r from-amber-500 to-orange-500 text-gray-900 px-8 py-4 rounded-2xl text-lg font-bold hover:from-amber-400 hover:to-orange-400 transition shadow-lg shadow-amber-500/25 hover:shadow-xl hover:shadow-amber-500/30"
|
|
||||||
>
|
|
||||||
무료 사주 보기
|
|
||||||
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" /></svg>
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
href="/compatibility"
|
|
||||||
className="inline-flex items-center gap-2 bg-gray-800 text-white px-8 py-4 rounded-2xl text-lg font-bold hover:bg-gray-700 transition border border-gray-700"
|
|
||||||
>
|
|
||||||
궁합 확인하기
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Footer */}
|
|
||||||
<footer className="bg-gray-900 border-t border-gray-800 py-12 px-4">
|
|
||||||
<div className="max-w-7xl mx-auto">
|
|
||||||
<div className="grid md:grid-cols-3 gap-8 mb-8">
|
|
||||||
<div>
|
|
||||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-amber-400 to-orange-400 bg-clip-text text-transparent">
|
|
||||||
🔮 사주포춘
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-500 text-sm leading-relaxed">
|
|
||||||
전통 명리학과 AI 기술의 결합으로<br />
|
|
||||||
가장 정확한 사주 서비스를 제공합니다.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
<div className="flex flex-wrap gap-4 pt-4">
|
||||||
<div>
|
<Link
|
||||||
<h4 className="text-sm font-bold text-gray-300 mb-4 tracking-wide">서비스</h4>
|
href="/saju"
|
||||||
<div className="space-y-2">
|
className="bg-[#d4af37] hover:bg-[#F3E7E3] text-[#173658] px-8 py-4 rounded-xl text-lg font-bold transition-all shadow-lg hover:shadow-xl inline-flex items-center space-x-2"
|
||||||
<Link href="/saju" className="block text-gray-500 hover:text-amber-400 transition text-sm">사주팔자</Link>
|
>
|
||||||
<Link href="/compatibility" className="block text-gray-500 hover:text-amber-400 transition text-sm">궁합 분석</Link>
|
<span>무료로 시작하기</span>
|
||||||
<Link href="/tojeong" className="block text-gray-500 hover:text-amber-400 transition text-sm">토정비결</Link>
|
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 7l5 5m0 0l-5 5m5-5H6" />
|
||||||
|
</svg>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 통계 */}
|
||||||
|
<div className="grid grid-cols-3 gap-6 pt-8">
|
||||||
|
<div>
|
||||||
|
<div className="text-3xl font-bold text-[#d4af37]">5,000+</div>
|
||||||
|
<div className="text-sm text-gray-300 mt-1">누적 분석</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-3xl font-bold text-[#d4af37]">98%</div>
|
||||||
|
<div className="text-sm text-gray-300 mt-1">정확도</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div className="text-3xl font-bold text-[#d4af37]">4.8</div>
|
||||||
|
<div className="text-sm text-gray-300 mt-1">만족도</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<h4 className="text-sm font-bold text-gray-300 mb-4 tracking-wide">고객지원</h4>
|
{/* 오른쪽 이미지 카드 */}
|
||||||
<div className="space-y-2">
|
<div className="hidden lg:block">
|
||||||
<p className="text-gray-500 text-sm">문의: bgg8988@gmail.com</p>
|
<div className="glass-panel rounded-3xl p-8 space-y-4">
|
||||||
<a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="block text-gray-500 hover:text-amber-400 transition text-sm">쟁승메이드</a>
|
<div className="bg-[#F3E7E3] rounded-2xl p-6">
|
||||||
<Link href="/mypage" className="block text-gray-500 hover:text-amber-400 transition text-sm">마이페이지</Link>
|
<h4 className="text-[#173658] font-bold text-lg mb-2">오늘의 인사이트</h4>
|
||||||
|
<p className="text-[#5d6d7e] text-sm leading-relaxed">
|
||||||
|
"목(木) 기운이 강한 당신, 오늘은 새로운 시작을 위한 최적의 날입니다."
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div className="bg-white/10 rounded-xl p-4 text-center">
|
||||||
|
<div className="text-2xl mb-2">🌟</div>
|
||||||
|
<div className="text-white text-sm font-bold">종합운</div>
|
||||||
|
<div className="text-[#d4af37] text-xs">85점</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white/10 rounded-xl p-4 text-center">
|
||||||
|
<div className="text-2xl mb-2">💰</div>
|
||||||
|
<div className="text-white text-sm font-bold">재물운</div>
|
||||||
|
<div className="text-[#d4af37] text-xs">92점</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white/10 rounded-xl p-4 text-center">
|
||||||
|
<div className="text-2xl mb-2">❤️</div>
|
||||||
|
<div className="text-white text-sm font-bold">애정운</div>
|
||||||
|
<div className="text-[#d4af37] text-xs">78점</div>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white/10 rounded-xl p-4 text-center">
|
||||||
|
<div className="text-2xl mb-2">💼</div>
|
||||||
|
<div className="text-white text-sm font-bold">직업운</div>
|
||||||
|
<div className="text-[#d4af37] text-xs">88점</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-gray-800 pt-8 text-center text-sm text-gray-600">
|
|
||||||
<p>© 2025 쟁승메이드. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
|
|
||||||
import { calculateSaju } from '@/lib/saju-calculator';
|
import { calculateSaju } from '@/lib/saju-calculator';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import PDFButton from '../components/PDFButton';
|
import PDFButton from '../components/PDFButton';
|
||||||
import ShareButtons from '../components/ShareButtons';
|
import ShareButtons from '../components/ShareButtons';
|
||||||
import UserMenu from '@/components/UserMenu';
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
import { calculateDaeun, getCurrentDaeun, getDaeunDescription } from '@/lib/daeun-calculator';
|
import { calculateDaeun, getCurrentDaeun, getDaeunDescription } from '@/lib/daeun-calculator';
|
||||||
import { getCurrentSolarTerm, getSolarTermName, getSolarTermMonthBranch } from '@/lib/solar-terms';
|
import { getCurrentSolarTerm, getSolarTermName, getSolarTermMonthBranch } from '@/lib/solar-terms';
|
||||||
import { EARTHLY_BRANCHES_KR, FIVE_ELEMENTS_KR, FIVE_ELEMENTS } from '@/lib/saju-calculator';
|
import { EARTHLY_BRANCHES_KR, FIVE_ELEMENTS_KR, FIVE_ELEMENTS } from '@/lib/saju-calculator';
|
||||||
@@ -63,482 +63,512 @@ export default async function ResultPage({ searchParams }: PageProps) {
|
|||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear();
|
||||||
const currentDaeun = getCurrentDaeun(daeunList, currentYear);
|
const currentDaeun = getCurrentDaeun(daeunList, currentYear);
|
||||||
|
|
||||||
// 오행 색상 매핑
|
// 오행 색상 매핑 (새 디자인)
|
||||||
const elementColors: { [key: string]: string } = {
|
const elementColors: { [key: string]: string } = {
|
||||||
'木': 'text-green-600', '火': 'text-red-500', '土': 'text-yellow-600',
|
'木': 'text-green-700', '火': 'text-red-600', '土': 'text-yellow-700',
|
||||||
'金': 'text-gray-500', '水': 'text-blue-600',
|
'金': 'text-[#d4af37]', '水': 'text-blue-700',
|
||||||
};
|
};
|
||||||
const elementBgColors: { [key: string]: string } = {
|
const elementBgColors: { [key: string]: string } = {
|
||||||
'木': 'bg-green-100 border-green-300', '火': 'bg-red-100 border-red-300',
|
'木': 'bg-green-50 border-green-400', '火': 'bg-red-50 border-red-400',
|
||||||
'土': 'bg-yellow-100 border-yellow-300', '金': 'bg-gray-100 border-gray-300',
|
'土': 'bg-yellow-50 border-yellow-400', '金': 'bg-[#F3E7E3] border-[#d4af37]',
|
||||||
'水': 'bg-blue-100 border-blue-300',
|
'水': 'bg-blue-50 border-blue-400',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 띠 계산
|
||||||
|
const zodiacAnimals = ['쥐', '소', '호랑이', '토끼', '용', '뱀', '말', '양', '원숭이', '닭', '개', '돼지'];
|
||||||
|
const zodiacIndex = (yearNum - 4) % 12;
|
||||||
|
const zodiacAnimal = zodiacAnimals[zodiacIndex >= 0 ? zodiacIndex : zodiacIndex + 12];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50">
|
<div className="min-h-screen bg-[#F3E7E3]">
|
||||||
{/* Navigation */}
|
<Header />
|
||||||
<nav className="bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50">
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
{/* 2컬럼 레이아웃 */}
|
||||||
<div className="flex justify-between items-center h-16">
|
<div className="container-custom pt-24 pb-12">
|
||||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">
|
<div className="grid lg:grid-cols-[300px_1fr] gap-8">
|
||||||
사주보기
|
{/* 사이드바 - 입력 정보 */}
|
||||||
</Link>
|
<aside className="lg:sticky lg:top-24 h-fit">
|
||||||
<div className="flex items-center space-x-4">
|
<div className="glass-panel rounded-2xl p-6 text-white">
|
||||||
<Link href="/" className="text-gray-700 hover:text-indigo-600 transition font-medium">
|
<h2 className="text-xl font-bold mb-6 text-center pb-4 border-b border-white/20">
|
||||||
다시 보기
|
기본 정보
|
||||||
</Link>
|
</h2>
|
||||||
<UserMenu />
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div>
|
||||||
|
<div className="text-sm text-gray-300 mb-1">생년월일</div>
|
||||||
|
<div className="font-bold">
|
||||||
|
{isLunar ? (
|
||||||
|
<div>
|
||||||
|
<div className="text-lg">음력 {inputYear}.{inputMonth}.{inputDay}</div>
|
||||||
|
{isLeap && <div className="text-xs text-[#d4af37]">(윤달)</div>}
|
||||||
|
<div className="text-xs text-gray-300 mt-1">
|
||||||
|
양력 {yearNum}.{monthNum}.{dayNum}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="text-lg">{yearNum}.{monthNum}.{dayNum}</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{hourNum !== null && (
|
||||||
|
<div>
|
||||||
|
<div className="text-sm text-gray-300 mb-1">태어난 시간</div>
|
||||||
|
<div className="font-bold text-lg">{hourNum}시</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="text-sm text-gray-300 mb-1">성별</div>
|
||||||
|
<div className="font-bold text-lg">{gender === 'male' ? '남성' : '여성'}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="text-sm text-gray-300 mb-1">띠</div>
|
||||||
|
<div className="font-bold text-lg">{zodiacAnimal}띠</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="text-sm text-gray-300 mb-1">일간</div>
|
||||||
|
<div className="font-bold text-2xl text-[#d4af37]">
|
||||||
|
{sajuData.day.stem} ({sajuData.day.stemKr})
|
||||||
|
</div>
|
||||||
|
<div className="text-sm mt-1">{FIVE_ELEMENTS_KR[sajuData.day.element as keyof typeof FIVE_ELEMENTS_KR]}({sajuData.day.element})</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 빠른 액션 */}
|
||||||
|
<div className="mt-6 pt-6 border-t border-white/20 space-y-3">
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="block w-full text-center bg-white/20 hover:bg-white/30 backdrop-blur-sm text-white px-4 py-2 rounded-lg transition-all font-medium text-sm"
|
||||||
|
>
|
||||||
|
다시 보기
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/compatibility"
|
||||||
|
className="block w-full text-center bg-[#d4af37] hover:bg-[#F3E7E3] text-[#173658] px-4 py-2 rounded-lg transition-all font-medium text-sm"
|
||||||
|
>
|
||||||
|
궁합 확인
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</aside>
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Result Content */}
|
{/* 메인 콘텐츠 */}
|
||||||
<div id="pdf-content" className="max-w-6xl mx-auto px-4 py-12">
|
<main id="pdf-content">
|
||||||
{/* Header */}
|
{/* 페이지 헤더 */}
|
||||||
<div className="text-center mb-12">
|
<div className="text-center mb-8">
|
||||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
<h1 className="text-3xl md:text-4xl font-bold text-[#173658] mb-3">
|
||||||
내 사주팔자
|
사주팔자 감정서
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-xl text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
{isLunar ? (
|
전통 명리학과 AI 기술의 만남
|
||||||
<>
|
</p>
|
||||||
음력 {inputYear}년 {inputMonth}월 {inputDay}일{isLeap && ' (윤달)'} {hourNum !== null && `${hourNum}시`}
|
</div>
|
||||||
<br />
|
|
||||||
<span className="text-base text-gray-500">
|
|
||||||
(양력 {yearNum}년 {monthNum}월 {dayNum}일)
|
|
||||||
</span>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{yearNum}년 {monthNum}월 {dayNum}일 {hourNum !== null && `${hourNum}시`}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{gender === 'male' ? ' 남성' : ' 여성'}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 사주팔자 표 */}
|
{/* 사주팔자 표 */}
|
||||||
<div className="bg-white rounded-3xl shadow-2xl p-8 md:p-12 mb-8">
|
<div className="glass-panel-light rounded-2xl p-6 md:p-8 mb-6">
|
||||||
<h2 className="text-3xl font-bold text-gray-900 mb-8 text-center">사주팔자 (四柱八字)</h2>
|
<h2 className="text-2xl font-bold text-[#173658] mb-6 text-center">사주팔자 (四柱八字)</h2>
|
||||||
|
|
||||||
<div className="overflow-x-auto">
|
<div className="overflow-x-auto">
|
||||||
<table className="w-full border-collapse">
|
<table className="w-full border-collapse">
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="bg-gradient-to-r from-indigo-600 to-purple-600 text-white">
|
<tr className="bg-[#173658] text-white">
|
||||||
<th className="py-4 px-6 text-center font-bold text-lg">구분</th>
|
<th className="py-3 px-4 text-center font-bold">구분</th>
|
||||||
{sajuData.hour && <th className="py-4 px-6 text-center font-bold text-lg">시주 (時柱)</th>}
|
{sajuData.hour && <th className="py-3 px-4 text-center font-bold">시주</th>}
|
||||||
<th className="py-4 px-6 text-center font-bold text-lg">일주 (日柱)</th>
|
<th className="py-3 px-4 text-center font-bold">일주</th>
|
||||||
<th className="py-4 px-6 text-center font-bold text-lg">월주 (月柱)</th>
|
<th className="py-3 px-4 text-center font-bold">월주</th>
|
||||||
<th className="py-4 px-6 text-center font-bold text-lg">년주 (年柱)</th>
|
<th className="py-3 px-4 text-center font-bold">년주</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{/* 천간 */}
|
{/* 천간 */}
|
||||||
<tr className="border-b border-gray-200 hover:bg-indigo-50 transition">
|
<tr className="border-b border-gray-200">
|
||||||
<td className="py-4 px-6 text-center font-semibold text-gray-700">천간 (天干)</td>
|
<td className="py-3 px-4 text-center font-semibold text-[#173658] bg-[#F3E7E3]">천간</td>
|
||||||
{sajuData.hour && (
|
{sajuData.hour && (
|
||||||
<td className="py-4 px-6 text-center">
|
<td className="py-3 px-4 text-center">
|
||||||
<div className="text-3xl font-bold text-indigo-600">{sajuData.hour.stem}</div>
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.hour.stem}</div>
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.hour.stemKr}</div>
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.hour.stemKr}</div>
|
||||||
</td>
|
</td>
|
||||||
|
)}
|
||||||
|
<td className="py-3 px-4 text-center bg-[#d4af37]/10">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.day.stem}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.day.stemKr}</div>
|
||||||
|
<div className="text-xs text-[#d4af37] font-bold mt-1">일간</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.month.stem}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.month.stemKr}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.year.stem}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.year.stemKr}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{/* 지지 */}
|
||||||
|
<tr className="border-b border-gray-200">
|
||||||
|
<td className="py-3 px-4 text-center font-semibold text-[#173658] bg-[#F3E7E3]">지지</td>
|
||||||
|
{sajuData.hour && (
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.hour.branch}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.hour.branchKr}</div>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
<td className="py-3 px-4 text-center bg-[#d4af37]/10">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.day.branch}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.day.branchKr}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.month.branch}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.month.branchKr}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-2xl font-bold text-[#173658]">{sajuData.year.branch}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-1">{sajuData.year.branchKr}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{/* 지장간 */}
|
||||||
|
<tr className="border-b border-gray-200">
|
||||||
|
<td className="py-3 px-4 text-center font-semibold text-[#173658] bg-[#F3E7E3]">
|
||||||
|
<div>지장간</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] font-normal">숨은 천간</div>
|
||||||
|
</td>
|
||||||
|
{(() => {
|
||||||
|
const pillars = sajuData.hour
|
||||||
|
? [analysis.hiddenStems.find(h => h.pillar === '시주'), analysis.hiddenStems.find(h => h.pillar === '일주'), analysis.hiddenStems.find(h => h.pillar === '월주'), analysis.hiddenStems.find(h => h.pillar === '년주')]
|
||||||
|
: [analysis.hiddenStems.find(h => h.pillar === '일주'), analysis.hiddenStems.find(h => h.pillar === '월주'), analysis.hiddenStems.find(h => h.pillar === '년주')];
|
||||||
|
return pillars.map((h, idx) => (
|
||||||
|
<td key={idx} className={`py-2 px-2 text-center ${h?.pillar === '일주' ? 'bg-[#d4af37]/10' : ''}`}>
|
||||||
|
{h && (
|
||||||
|
<div className="flex flex-wrap justify-center gap-1">
|
||||||
|
{h.stems.map((s, si) => (
|
||||||
|
<span
|
||||||
|
key={si}
|
||||||
|
className={`inline-block px-2 py-0.5 rounded text-xs font-semibold border ${elementBgColors[s.element] || 'bg-gray-100'}`}
|
||||||
|
title={s.role}
|
||||||
|
>
|
||||||
|
{s.stemKr}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
));
|
||||||
|
})()}
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{/* 십성 */}
|
||||||
|
<tr className="border-b border-gray-200">
|
||||||
|
<td className="py-3 px-4 text-center font-semibold text-[#173658] bg-[#F3E7E3]">십성</td>
|
||||||
|
{sajuData.hour && (
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.hour.tenGod}</div>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
<td className="py-3 px-4 text-center bg-[#d4af37]/10">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.day.tenGod}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.month.tenGod}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.year.tenGod}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
{/* 십이운성 */}
|
||||||
|
<tr>
|
||||||
|
<td className="py-3 px-4 text-center font-semibold text-[#173658] bg-[#F3E7E3]">십이운성</td>
|
||||||
|
{sajuData.hour && (
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.hour.fortune}</div>
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
|
<td className="py-3 px-4 text-center bg-[#d4af37]/10">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.day.fortune}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.month.fortune}</div>
|
||||||
|
</td>
|
||||||
|
<td className="py-3 px-4 text-center">
|
||||||
|
<div className="text-sm font-bold text-[#173658]">{sajuData.year.fortune}</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 지지 상호작용 */}
|
||||||
|
{analysis.branchInteractions.length > 0 && (
|
||||||
|
<div className="mt-6 pt-6 border-t border-[#173658]/10">
|
||||||
|
<h3 className="text-base font-bold text-[#173658] mb-3 text-center">
|
||||||
|
지지 상호작용
|
||||||
|
</h3>
|
||||||
|
<div className="flex flex-wrap justify-center gap-2">
|
||||||
|
{analysis.branchInteractions.map((inter, idx) => {
|
||||||
|
const isPositive = inter.type.includes('합');
|
||||||
|
const isNegative = inter.type.includes('충') || inter.type.includes('형');
|
||||||
|
const colorClass = isPositive
|
||||||
|
? 'bg-emerald-50 border-emerald-400 text-emerald-800'
|
||||||
|
: isNegative
|
||||||
|
? 'bg-red-50 border-red-400 text-red-800'
|
||||||
|
: 'bg-amber-50 border-amber-400 text-amber-800';
|
||||||
|
return (
|
||||||
|
<span key={idx} className={`inline-flex items-center px-3 py-1 rounded-full text-xs font-bold border ${colorClass}`}>
|
||||||
|
{inter.type} {inter.branchesKr.join('')}
|
||||||
|
{inter.resultElement && ` → ${FIVE_ELEMENTS_KR[inter.resultElement as keyof typeof FIVE_ELEMENTS_KR]}`}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* 오행 균형 */}
|
||||||
|
<div className="mt-6 pt-6 border-t border-[#173658]/10">
|
||||||
|
<h3 className="text-base font-bold text-[#173658] mb-4 text-center">
|
||||||
|
오행 균형
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-5 gap-2">
|
||||||
|
{Object.entries(elementScores).map(([element, score]) => (
|
||||||
|
<div key={element} className="text-center">
|
||||||
|
<div className={`text-xl font-bold mb-1 ${elementColors[element] || ''}`}>{element}</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mb-2">
|
||||||
|
{FIVE_ELEMENTS_KR[element as keyof typeof FIVE_ELEMENTS_KR]}
|
||||||
|
</div>
|
||||||
|
<div className="w-full bg-gray-200 rounded-full h-2 mb-1">
|
||||||
|
<div
|
||||||
|
className={`h-2 rounded-full transition-all ${element === sajuData.day.element
|
||||||
|
? 'bg-gradient-to-r from-[#173658] to-[#d4af37]'
|
||||||
|
: 'bg-gray-400'
|
||||||
|
}`}
|
||||||
|
style={{ width: `${Math.max(score, 5)}%` }}
|
||||||
|
></div>
|
||||||
|
</div>
|
||||||
|
<div className="text-xs font-bold text-[#173658]">{score}%</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 분석 카드 그리드 */}
|
||||||
|
<div className="grid md:grid-cols-2 gap-6 mb-6">
|
||||||
|
{/* 신강/신약 + 용신 카드 */}
|
||||||
|
<div className="glass-panel-light rounded-2xl p-6">
|
||||||
|
<h3 className="text-xl font-bold text-[#173658] mb-4">
|
||||||
|
일간 세력 분석
|
||||||
|
</h3>
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<span className={`inline-block px-4 py-2 rounded-xl text-base font-bold ${
|
||||||
|
analysis.dayMasterStrength.result === '신강'
|
||||||
|
? 'bg-red-100 text-red-700 border-2 border-red-400'
|
||||||
|
: analysis.dayMasterStrength.result === '신약'
|
||||||
|
? 'bg-blue-100 text-blue-700 border-2 border-blue-400'
|
||||||
|
: 'bg-green-100 text-green-700 border-2 border-green-400'
|
||||||
|
}`}>
|
||||||
|
{analysis.dayMasterStrength.result}
|
||||||
|
</span>
|
||||||
|
<span className="text-[#5d6d7e] text-sm">점수: {analysis.dayMasterStrength.score}</span>
|
||||||
|
</div>
|
||||||
|
<ul className="space-y-1 text-sm text-[#5d6d7e] mb-6">
|
||||||
|
{analysis.dayMasterStrength.reasons.map((r, i) => (
|
||||||
|
<li key={i} className="flex items-start">
|
||||||
|
<span className="text-[#d4af37] mr-2">-</span>
|
||||||
|
<span>{r}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div className="border-t border-[#173658]/10 pt-4">
|
||||||
|
<h4 className="font-bold text-[#173658] mb-3">용신 / 희신 / 기신</h4>
|
||||||
|
<div className="flex flex-wrap gap-2 mb-3">
|
||||||
|
<span className={`px-3 py-1.5 rounded-lg text-xs font-bold border ${elementBgColors[analysis.yongShin.yongShin] || 'bg-gray-100'}`}>
|
||||||
|
용신: {analysis.yongShin.yongShinKr}
|
||||||
|
</span>
|
||||||
|
<span className={`px-3 py-1.5 rounded-lg text-xs font-bold border ${elementBgColors[analysis.yongShin.heeShin] || 'bg-gray-100'}`}>
|
||||||
|
희신: {analysis.yongShin.heeShinKr}
|
||||||
|
</span>
|
||||||
|
<span className="px-3 py-1.5 rounded-lg text-xs font-bold bg-gray-200 border border-gray-400 text-gray-700">
|
||||||
|
기신: {analysis.yongShin.giShinKr}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-[#5d6d7e] leading-relaxed">{analysis.yongShin.explanation}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 신살 + 공망 카드 */}
|
||||||
|
<div className="glass-panel-light rounded-2xl p-6">
|
||||||
|
<h3 className="text-xl font-bold text-[#173658] mb-4">
|
||||||
|
신살 (神煞)
|
||||||
|
</h3>
|
||||||
|
{analysis.shinsal.length > 0 ? (
|
||||||
|
<div className="space-y-2 mb-6">
|
||||||
|
{analysis.shinsal.map((s, i) => (
|
||||||
|
<div key={i} className="flex items-start gap-2 p-3 rounded-xl bg-[#F3E7E3]">
|
||||||
|
<span className="inline-block px-2 py-1 bg-[#173658] text-white rounded-lg text-xs font-bold whitespace-nowrap">
|
||||||
|
{s.name}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
<div className="text-sm font-semibold text-[#173658]">
|
||||||
|
{s.pillar} {s.branchKr}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e] mt-0.5">{s.description}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<p className="text-[#5d6d7e] text-sm mb-6">특별한 신살이 발견되지 않았습니다.</p>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="border-t border-[#173658]/10 pt-4">
|
||||||
|
<h4 className="font-bold text-[#173658] mb-2">공망 (空亡)</h4>
|
||||||
|
<div className="flex gap-2 mb-2">
|
||||||
|
{analysis.gongmang.branchesKr.map((bk, i) => (
|
||||||
|
<span key={i} className="px-3 py-1.5 bg-[#173658] text-white rounded-lg text-sm font-bold">
|
||||||
|
{bk}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<p className="text-xs text-[#5d6d7e] leading-relaxed">{analysis.gongmang.description}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* 세운 정보 */}
|
||||||
|
<div className="border-t border-[#173658]/10 pt-4 mt-4">
|
||||||
|
<h4 className="font-bold text-[#173658] mb-2">
|
||||||
|
{analysis.seun.year}년 세운
|
||||||
|
</h4>
|
||||||
|
<div className="flex items-center gap-2 mb-2">
|
||||||
|
<span className={`px-3 py-1.5 rounded-lg text-sm font-bold border ${elementBgColors[analysis.seun.element] || 'bg-gray-100'}`}>
|
||||||
|
{analysis.seun.stemKr}{analysis.seun.branchKr}
|
||||||
|
</span>
|
||||||
|
<span className="text-sm text-[#5d6d7e]">{analysis.seun.elementKr} 기운</span>
|
||||||
|
</div>
|
||||||
|
{analysis.seun.interactions.length > 0 && (
|
||||||
|
<div className="flex flex-wrap gap-1.5 mt-2">
|
||||||
|
{analysis.seun.interactions.map((si, i) => (
|
||||||
|
<span key={i} className={`text-xs px-2 py-1 rounded-full font-semibold ${
|
||||||
|
si.type.includes('합') ? 'bg-emerald-50 text-emerald-700' : 'bg-red-50 text-red-700'
|
||||||
|
}`}>
|
||||||
|
{si.type} {si.branchesKr.join('')}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<td className="py-4 px-6 text-center bg-blue-50">
|
</div>
|
||||||
<div className="text-3xl font-bold text-blue-600">{sajuData.day.stem}</div>
|
</div>
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.day.stemKr}</div>
|
</div>
|
||||||
<div className="text-xs text-blue-600 font-semibold mt-1">일간 (日干)</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-3xl font-bold text-indigo-600">{sajuData.month.stem}</div>
|
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.month.stemKr}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-3xl font-bold text-indigo-600">{sajuData.year.stem}</div>
|
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.year.stemKr}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{/* 지지 */}
|
{/* AI 상세 해석 */}
|
||||||
<tr className="border-b border-gray-200 hover:bg-purple-50 transition">
|
<AiInterpretationSection sajuData={sajuData} currentDaeun={currentDaeun} daeunList={daeunList} />
|
||||||
<td className="py-4 px-6 text-center font-semibold text-gray-700">지지 (地支)</td>
|
|
||||||
{sajuData.hour && (
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-3xl font-bold text-purple-600">{sajuData.hour.branch}</div>
|
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.hour.branchKr}</div>
|
|
||||||
</td>
|
|
||||||
)}
|
|
||||||
<td className="py-4 px-6 text-center bg-blue-50">
|
|
||||||
<div className="text-3xl font-bold text-blue-600">{sajuData.day.branch}</div>
|
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.day.branchKr}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-3xl font-bold text-purple-600">{sajuData.month.branch}</div>
|
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.month.branchKr}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-3xl font-bold text-purple-600">{sajuData.year.branch}</div>
|
|
||||||
<div className="text-sm text-gray-600 mt-1">{sajuData.year.branchKr}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{/* 지장간 (NEW) */}
|
{/* 대운 (大運) */}
|
||||||
<tr className="border-b border-gray-200 hover:bg-amber-50 transition">
|
<div className="glass-panel-light rounded-2xl p-6 md:p-8 mb-6">
|
||||||
<td className="py-4 px-6 text-center font-semibold text-gray-700">
|
<h2 className="text-2xl font-bold text-[#173658] mb-6 text-center">
|
||||||
지장간 (藏干)
|
대운 (大運) - 10년 주기 운세
|
||||||
<div className="text-xs text-gray-400 mt-1">숨은 천간</div>
|
</h2>
|
||||||
</td>
|
|
||||||
{(() => {
|
{currentDaeun && (
|
||||||
const pillars = sajuData.hour
|
<div className="bg-gradient-to-r from-[#173658] to-[#1e426a] rounded-2xl p-6 mb-6 text-white">
|
||||||
? [analysis.hiddenStems.find(h => h.pillar === '시주'), analysis.hiddenStems.find(h => h.pillar === '일주'), analysis.hiddenStems.find(h => h.pillar === '월주'), analysis.hiddenStems.find(h => h.pillar === '년주')]
|
<h3 className="text-xl font-bold mb-4 text-center">현재 대운</h3>
|
||||||
: [analysis.hiddenStems.find(h => h.pillar === '일주'), analysis.hiddenStems.find(h => h.pillar === '월주'), analysis.hiddenStems.find(h => h.pillar === '년주')];
|
<div className="text-center mb-4">
|
||||||
return pillars.map((h, idx) => (
|
<div className="text-4xl font-bold mb-2">
|
||||||
<td key={idx} className={`py-3 px-4 text-center ${h?.pillar === '일주' ? 'bg-blue-50' : ''}`}>
|
{currentDaeun.stem}{currentDaeun.branch}
|
||||||
{h && (
|
</div>
|
||||||
<div className="flex flex-wrap justify-center gap-1">
|
<div className="text-lg mb-2">
|
||||||
{h.stems.map((s, si) => (
|
{currentDaeun.stemKr}{currentDaeun.branchKr}
|
||||||
<span
|
</div>
|
||||||
key={si}
|
<div className="text-base opacity-90">
|
||||||
className={`inline-block px-2 py-1 rounded text-xs font-semibold border ${elementBgColors[s.element] || 'bg-gray-100'}`}
|
{currentDaeun.age}세 ~ {currentDaeun.age + 9}세 ({currentDaeun.startYear}년 ~ {currentDaeun.endYear}년)
|
||||||
title={s.role}
|
</div>
|
||||||
>
|
</div>
|
||||||
{s.stemKr}({FIVE_ELEMENTS_KR[s.element as keyof typeof FIVE_ELEMENTS_KR]})
|
<p className="text-center leading-relaxed text-sm">
|
||||||
</span>
|
{getDaeunDescription(currentDaeun, sajuData.day.stem)}
|
||||||
))}
|
</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-3">
|
||||||
|
{daeunList.map((daeun, index) => {
|
||||||
|
const isCurrent = currentDaeun &&
|
||||||
|
daeun.startYear === currentDaeun.startYear &&
|
||||||
|
daeun.endYear === currentDaeun.endYear;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className={`rounded-xl p-4 border-2 transition ${isCurrent
|
||||||
|
? 'bg-[#d4af37]/20 border-[#d4af37]'
|
||||||
|
: 'bg-white border-[#173658]/20'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="text-center">
|
||||||
|
<div className="text-2xl font-bold text-[#173658] mb-1">
|
||||||
|
{daeun.stem}{daeun.branch}
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-[#5d6d7e] mb-2">
|
||||||
|
{daeun.stemKr}{daeun.branchKr}
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e]">
|
||||||
|
{daeun.age}세 ~ {daeun.age + 9}세
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-[#5d6d7e]">
|
||||||
|
{daeun.startYear} ~ {daeun.endYear}
|
||||||
|
</div>
|
||||||
|
{isCurrent && (
|
||||||
|
<div className="mt-2">
|
||||||
|
<span className="inline-block bg-[#173658] text-white text-xs px-3 py-1 rounded-full font-semibold">
|
||||||
|
현재
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</td>
|
</div>
|
||||||
));
|
</div>
|
||||||
})()}
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{/* 십성 */}
|
|
||||||
<tr className="border-b border-gray-200 hover:bg-emerald-50 transition">
|
|
||||||
<td className="py-4 px-6 text-center font-semibold text-gray-700">십성 (十星)</td>
|
|
||||||
{sajuData.hour && (
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-lg font-semibold text-emerald-600">{sajuData.hour.tenGod}</div>
|
|
||||||
</td>
|
|
||||||
)}
|
|
||||||
<td className="py-4 px-6 text-center bg-blue-50">
|
|
||||||
<div className="text-lg font-semibold text-blue-600">{sajuData.day.tenGod}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-lg font-semibold text-emerald-600">{sajuData.month.tenGod}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-lg font-semibold text-emerald-600">{sajuData.year.tenGod}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
{/* 십이운성 */}
|
|
||||||
<tr className="hover:bg-pink-50 transition">
|
|
||||||
<td className="py-4 px-6 text-center font-semibold text-gray-700">십이운성</td>
|
|
||||||
{sajuData.hour && (
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-lg font-semibold text-pink-600">{sajuData.hour.fortune}</div>
|
|
||||||
</td>
|
|
||||||
)}
|
|
||||||
<td className="py-4 px-6 text-center bg-blue-50">
|
|
||||||
<div className="text-lg font-semibold text-blue-600">{sajuData.day.fortune}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-lg font-semibold text-pink-600">{sajuData.month.fortune}</div>
|
|
||||||
</td>
|
|
||||||
<td className="py-4 px-6 text-center">
|
|
||||||
<div className="text-lg font-semibold text-pink-600">{sajuData.year.fortune}</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 지지 상호작용 (합/충/형/파/해) */}
|
|
||||||
{analysis.branchInteractions.length > 0 && (
|
|
||||||
<div className="mt-6 pt-6 border-t border-gray-100">
|
|
||||||
<h3 className="text-lg font-bold text-gray-900 mb-3 flex items-center justify-center">
|
|
||||||
<span className="mr-2">🔗</span> 지지 상호작용
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap justify-center gap-2">
|
|
||||||
{analysis.branchInteractions.map((inter, idx) => {
|
|
||||||
const isPositive = inter.type.includes('합');
|
|
||||||
const isNegative = inter.type.includes('충') || inter.type.includes('형');
|
|
||||||
const colorClass = isPositive
|
|
||||||
? 'bg-emerald-50 border-emerald-300 text-emerald-800'
|
|
||||||
: isNegative
|
|
||||||
? 'bg-red-50 border-red-300 text-red-800'
|
|
||||||
: 'bg-amber-50 border-amber-300 text-amber-800';
|
|
||||||
return (
|
|
||||||
<span key={idx} className={`inline-flex items-center px-3 py-1.5 rounded-full text-sm font-semibold border ${colorClass}`}>
|
|
||||||
{inter.type} {inter.branchesKr.join('')}
|
|
||||||
{inter.resultElement && ` → ${FIVE_ELEMENTS_KR[inter.resultElement as keyof typeof FIVE_ELEMENTS_KR]}`}
|
|
||||||
</span>
|
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
|
|
||||||
{/* 오행 균형 시각화 */}
|
{/* 추가 기능 버튼 */}
|
||||||
<div className="mt-8 pt-8 border-t border-gray-100">
|
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-4 flex items-center justify-center">
|
<Link
|
||||||
<span className="text-2xl mr-2">⚖️</span>
|
href={`/fortune?${new URLSearchParams(params as any).toString()}`}
|
||||||
내 사주의 오행 균형
|
className="glass-panel-light rounded-xl p-6 card-hover text-center"
|
||||||
<span className="text-sm font-normal text-gray-500 ml-2">(지장간 가중치 적용)</span>
|
>
|
||||||
</h3>
|
<div className="text-3xl mb-3">🌟</div>
|
||||||
<div className="grid grid-cols-5 gap-3 max-w-2xl mx-auto">
|
<h3 className="text-lg font-bold text-[#173658] mb-1">오늘의 운세</h3>
|
||||||
{Object.entries(elementScores).map(([element, score]) => (
|
<p className="text-[#5d6d7e] text-sm">오늘의 운을 확인하기</p>
|
||||||
<div key={element} className="text-center">
|
</Link>
|
||||||
<div className={`text-2xl font-bold mb-1 ${elementColors[element] || ''}`}>{element}</div>
|
|
||||||
<div className="text-sm text-gray-600 mb-2">
|
<Link
|
||||||
{FIVE_ELEMENTS_KR[element as keyof typeof FIVE_ELEMENTS_KR]}
|
href="/compatibility"
|
||||||
<span className="text-xs text-gray-400 ml-1">
|
className="glass-panel-light rounded-xl p-6 card-hover text-center"
|
||||||
({analysis.elementBalance[element as keyof typeof analysis.elementBalance]}점)
|
>
|
||||||
</span>
|
<div className="text-3xl mb-3">💕</div>
|
||||||
</div>
|
<h3 className="text-lg font-bold text-[#173658] mb-1">궁합 보기</h3>
|
||||||
<div className="w-full bg-gray-200 rounded-full h-3 mb-1">
|
<p className="text-[#5d6d7e] text-sm">두 사람의 궁합 확인</p>
|
||||||
<div
|
</Link>
|
||||||
className={`h-3 rounded-full transition-all ${element === sajuData.day.element
|
|
||||||
? 'bg-gradient-to-r from-indigo-500 to-purple-500'
|
<PDFButton
|
||||||
: 'bg-gray-400'
|
elementId="pdf-content"
|
||||||
}`}
|
filename={`사주팔자_${yearNum}${monthNum}${dayNum}.pdf`}
|
||||||
style={{ width: `${Math.max(score, 5)}%` }}
|
buttonText="PDF 저장"
|
||||||
></div>
|
/>
|
||||||
</div>
|
|
||||||
<div className="text-xs font-semibold text-gray-700">{score}%</div>
|
<ShareButtons
|
||||||
</div>
|
title={`내 사주팔자 - ${yearNum}년생 ${gender === 'male' ? '남성' : '여성'}`}
|
||||||
))}
|
description={`일간: ${sajuData.day.stem}(${sajuData.day.stemKr}) | ${sajuData.day.element}`}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</main>
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 신강/신약 + 용신 + 신살 카드 */}
|
|
||||||
<div className="grid md:grid-cols-2 gap-6 mb-8">
|
|
||||||
{/* 신강/신약 + 용신 카드 */}
|
|
||||||
<div className="bg-white rounded-3xl shadow-xl p-8 border border-gray-100">
|
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
|
||||||
<span className="mr-2">⚡</span> 일간 세력 분석
|
|
||||||
</h3>
|
|
||||||
<div className="flex items-center gap-3 mb-4">
|
|
||||||
<span className={`inline-block px-4 py-2 rounded-xl text-lg font-bold ${
|
|
||||||
analysis.dayMasterStrength.result === '신강'
|
|
||||||
? 'bg-red-100 text-red-700'
|
|
||||||
: analysis.dayMasterStrength.result === '신약'
|
|
||||||
? 'bg-blue-100 text-blue-700'
|
|
||||||
: 'bg-green-100 text-green-700'
|
|
||||||
}`}>
|
|
||||||
{analysis.dayMasterStrength.result}
|
|
||||||
</span>
|
|
||||||
<span className="text-gray-500 text-sm">점수: {analysis.dayMasterStrength.score}</span>
|
|
||||||
</div>
|
|
||||||
<ul className="space-y-1.5 text-sm text-gray-600 mb-6">
|
|
||||||
{analysis.dayMasterStrength.reasons.map((r, i) => (
|
|
||||||
<li key={i} className="flex items-start">
|
|
||||||
<span className="text-indigo-400 mr-2 mt-0.5">-</span>
|
|
||||||
<span>{r}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<div className="border-t border-gray-100 pt-4">
|
|
||||||
<h4 className="font-bold text-gray-800 mb-3">용신 / 희신 / 기신</h4>
|
|
||||||
<div className="flex flex-wrap gap-2 mb-3">
|
|
||||||
<span className={`px-3 py-1.5 rounded-lg text-sm font-bold border ${elementBgColors[analysis.yongShin.yongShin] || 'bg-gray-100'}`}>
|
|
||||||
용신: {analysis.yongShin.yongShinKr}({analysis.yongShin.yongShin})
|
|
||||||
</span>
|
|
||||||
<span className={`px-3 py-1.5 rounded-lg text-sm font-bold border ${elementBgColors[analysis.yongShin.heeShin] || 'bg-gray-100'}`}>
|
|
||||||
희신: {analysis.yongShin.heeShinKr}({analysis.yongShin.heeShin})
|
|
||||||
</span>
|
|
||||||
<span className="px-3 py-1.5 rounded-lg text-sm font-bold bg-gray-200 border border-gray-400 text-gray-700">
|
|
||||||
기신: {analysis.yongShin.giShinKr}({analysis.yongShin.giShin})
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<p className="text-sm text-gray-600 leading-relaxed">{analysis.yongShin.explanation}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 신살 + 공망 카드 */}
|
|
||||||
<div className="bg-white rounded-3xl shadow-xl p-8 border border-gray-100">
|
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
|
||||||
<span className="mr-2">🌟</span> 신살 (神煞)
|
|
||||||
</h3>
|
|
||||||
{analysis.shinsal.length > 0 ? (
|
|
||||||
<div className="space-y-3 mb-6">
|
|
||||||
{analysis.shinsal.map((s, i) => (
|
|
||||||
<div key={i} className="flex items-start gap-3 p-3 rounded-xl bg-gray-50">
|
|
||||||
<span className="inline-block px-2 py-1 bg-indigo-100 text-indigo-700 rounded-lg text-xs font-bold whitespace-nowrap">
|
|
||||||
{s.name}
|
|
||||||
</span>
|
|
||||||
<div>
|
|
||||||
<div className="text-sm font-semibold text-gray-800">
|
|
||||||
{s.pillar} {s.branchKr}({s.branch})
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-gray-500 mt-0.5">{s.description}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<p className="text-gray-500 text-sm mb-6">특별한 신살이 발견되지 않았습니다.</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="border-t border-gray-100 pt-4">
|
|
||||||
<h4 className="font-bold text-gray-800 mb-2 flex items-center">
|
|
||||||
<span className="mr-2">🕳️</span> 공망 (空亡)
|
|
||||||
</h4>
|
|
||||||
<div className="flex gap-2 mb-2">
|
|
||||||
{analysis.gongmang.branchesKr.map((bk, i) => (
|
|
||||||
<span key={i} className="px-3 py-1.5 bg-gray-800 text-white rounded-lg text-sm font-bold">
|
|
||||||
{bk}({analysis.gongmang.branches[i]})
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
<p className="text-xs text-gray-500 leading-relaxed">{analysis.gongmang.description}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 세운 정보 */}
|
|
||||||
<div className="border-t border-gray-100 pt-4 mt-4">
|
|
||||||
<h4 className="font-bold text-gray-800 mb-2 flex items-center">
|
|
||||||
<span className="mr-2">📅</span> {analysis.seun.year}년 세운
|
|
||||||
</h4>
|
|
||||||
<div className="flex items-center gap-2 mb-2">
|
|
||||||
<span className={`px-3 py-1.5 rounded-lg text-sm font-bold border ${elementBgColors[analysis.seun.element] || 'bg-gray-100'}`}>
|
|
||||||
{analysis.seun.stemKr}{analysis.seun.branchKr} ({analysis.seun.stem}{analysis.seun.branch})
|
|
||||||
</span>
|
|
||||||
<span className="text-sm text-gray-500">{analysis.seun.elementKr}({analysis.seun.element}) 기운</span>
|
|
||||||
</div>
|
|
||||||
{analysis.seun.interactions.length > 0 && (
|
|
||||||
<div className="flex flex-wrap gap-1.5 mt-2">
|
|
||||||
{analysis.seun.interactions.map((si, i) => (
|
|
||||||
<span key={i} className={`text-xs px-2 py-1 rounded-full font-semibold ${
|
|
||||||
si.type.includes('합') ? 'bg-emerald-50 text-emerald-700' : 'bg-red-50 text-red-700'
|
|
||||||
}`}>
|
|
||||||
{si.type} {si.branchesKr.join('')}
|
|
||||||
</span>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* AI 상세 해석 */}
|
|
||||||
<AiInterpretationSection sajuData={sajuData} currentDaeun={currentDaeun} daeunList={daeunList} />
|
|
||||||
|
|
||||||
{/* 대운 (大運) */}
|
|
||||||
<div className="bg-white rounded-3xl shadow-2xl p-8 md:p-12 mb-8">
|
|
||||||
<h2 className="text-3xl font-bold text-gray-900 mb-8 text-center">
|
|
||||||
대운 (大運) - 10년 주기 운세
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{currentDaeun && (
|
|
||||||
<div className="bg-gradient-to-r from-indigo-500 to-purple-500 rounded-2xl p-6 mb-8 text-white">
|
|
||||||
<h3 className="text-2xl font-bold mb-4 text-center">현재 대운</h3>
|
|
||||||
<div className="text-center mb-4">
|
|
||||||
<div className="text-5xl font-bold mb-2">
|
|
||||||
{currentDaeun.stem}{currentDaeun.branch}
|
|
||||||
</div>
|
|
||||||
<div className="text-xl mb-2">
|
|
||||||
{currentDaeun.stemKr}{currentDaeun.branchKr}
|
|
||||||
</div>
|
|
||||||
<div className="text-lg opacity-90">
|
|
||||||
{currentDaeun.age}세 ~ {currentDaeun.age + 9}세 ({currentDaeun.startYear}년 ~ {currentDaeun.endYear}년)
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p className="text-center leading-relaxed">
|
|
||||||
{getDaeunDescription(currentDaeun, sajuData.day.stem)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
||||||
{daeunList.map((daeun, index) => {
|
|
||||||
const isCurrent = currentDaeun &&
|
|
||||||
daeun.startYear === currentDaeun.startYear &&
|
|
||||||
daeun.endYear === currentDaeun.endYear;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={index}
|
|
||||||
className={`rounded-xl p-4 border-2 transition ${isCurrent
|
|
||||||
? 'bg-indigo-50 border-indigo-400'
|
|
||||||
: 'bg-gray-50 border-gray-200 hover:border-indigo-300'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="text-center">
|
|
||||||
<div className="text-3xl font-bold text-gray-900 mb-1">
|
|
||||||
{daeun.stem}{daeun.branch}
|
|
||||||
</div>
|
|
||||||
<div className="text-sm text-gray-600 mb-2">
|
|
||||||
{daeun.stemKr}{daeun.branchKr}
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-gray-500">
|
|
||||||
{daeun.age}세 ~ {daeun.age + 9}세
|
|
||||||
</div>
|
|
||||||
<div className="text-xs text-gray-400">
|
|
||||||
{daeun.startYear} ~ {daeun.endYear}
|
|
||||||
</div>
|
|
||||||
{isCurrent && (
|
|
||||||
<div className="mt-2">
|
|
||||||
<span className="inline-block bg-indigo-600 text-white text-xs px-3 py-1 rounded-full font-semibold">
|
|
||||||
현재
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 추가 기능 버튼 */}
|
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
||||||
<Link
|
|
||||||
href={`/fortune?${new URLSearchParams(params as any).toString()}`}
|
|
||||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
|
||||||
>
|
|
||||||
<div className="text-4xl mb-3">🌟</div>
|
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">오늘의 운세</h3>
|
|
||||||
<p className="text-gray-600 text-sm">오늘의 운을 확인하기</p>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<Link
|
|
||||||
href="/compatibility"
|
|
||||||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group"
|
|
||||||
>
|
|
||||||
<div className="text-4xl mb-3">💕</div>
|
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-2">궁합 보기</h3>
|
|
||||||
<p className="text-gray-600 text-sm">두 사람의 궁합 확인</p>
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
<PDFButton
|
|
||||||
elementId="pdf-content"
|
|
||||||
filename={`사주팔자_${yearNum}${monthNum}${dayNum}.pdf`}
|
|
||||||
buttonText="사주 PDF 저장"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ShareButtons
|
|
||||||
title={`내 사주팔자 - ${yearNum}년생 ${gender === 'male' ? '남성' : '여성'}`}
|
|
||||||
description={`일간: ${sajuData.day.stem}(${sajuData.day.stemKr}) | ${sajuData.day.element}`}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Footer */}
|
<Footer />
|
||||||
<footer className="bg-gray-900 text-white py-12 px-4 mt-20">
|
|
||||||
<div className="max-w-7xl mx-auto text-center">
|
|
||||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-indigo-400 to-purple-400 bg-clip-text text-transparent">
|
|
||||||
사주보기
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-400 mb-6">
|
|
||||||
쟁승메이드가 제공하는 무료 사주 서비스
|
|
||||||
</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
<p>문의: bgg8988@gmail.com | <a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="hover:text-indigo-400">쟁승메이드</a></p>
|
|
||||||
<p className="mt-2">© 2025 쟁승메이드. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,71 +1,66 @@
|
|||||||
|
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import SajuForm from '../components/SajuForm';
|
import SajuForm from '../components/SajuForm';
|
||||||
import UserMenu from '@/components/UserMenu';
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
export default function SajuPage() {
|
export default function SajuPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50">
|
<div className="min-h-screen bg-[#F3E7E3]">
|
||||||
{/* Navigation */}
|
<Header />
|
||||||
<nav className="bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50">
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
||||||
<div className="flex justify-between items-center h-16">
|
|
||||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">
|
|
||||||
🔮 사주포춘
|
|
||||||
</Link>
|
|
||||||
<div className="flex items-center space-x-6">
|
|
||||||
<div className="hidden md:flex space-x-6 mr-4">
|
|
||||||
<Link href="/saju" className="text-indigo-600 font-bold">사주팔자</Link>
|
|
||||||
<Link href="/compatibility" className="text-gray-700 hover:text-indigo-600 transition font-medium">궁합</Link>
|
|
||||||
<Link href="/tojeong" className="text-gray-700 hover:text-indigo-600 transition font-medium">토정비결</Link>
|
|
||||||
</div>
|
|
||||||
<UserMenu />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="pt-20 pb-32 px-4">
|
<section className="pt-32 pb-20 px-4">
|
||||||
<div className="max-w-4xl mx-auto text-center">
|
<div className="max-w-4xl mx-auto text-center">
|
||||||
<div className="inline-block mb-6 px-6 py-2 bg-white/50 backdrop-blur-sm rounded-full text-indigo-700 font-semibold border border-indigo-200">
|
<div className="inline-block mb-6 px-6 py-2 bg-white rounded-full text-[#173658] font-bold border-2 border-[#173658]">
|
||||||
무료로 내 사주를 확인해보세요
|
무료로 내 사주를 확인해보세요
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-6 leading-tight">
|
<h1 className="text-4xl md:text-6xl font-bold text-[#173658] mb-6 leading-tight">
|
||||||
나의 <span className="bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">사주팔자</span>를<br />
|
나의 <span className="gradient-text">사주팔자</span>를<br />
|
||||||
확인하세요
|
확인하세요
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="text-xl text-gray-600 mb-12 max-w-2xl mx-auto">
|
<p className="text-xl text-[#5d6d7e] mb-12 max-w-2xl mx-auto leading-relaxed">
|
||||||
생년월일시를 입력하면 무료로 사주팔자, 운세, 궁합을 확인할 수 있습니다.
|
생년월일시를 입력하면 무료로 사주팔자, 운세, 궁합을 확인할 수 있습니다.
|
||||||
쉽고 빠르게 나의 운명을 알아보세요.
|
쉽고 빠르게 나의 운명을 알아보세요.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Main Input Card */}
|
{/* Main Input Card */}
|
||||||
<div className="bg-white rounded-3xl shadow-2xl p-8 md:p-12 max-w-2xl mx-auto">
|
<div className="glass-panel-light rounded-3xl p-8 md:p-12 max-w-2xl mx-auto shadow-2xl">
|
||||||
<h2 className="text-2xl font-bold text-gray-900 mb-8">생년월일시 입력</h2>
|
<div className="flex items-center justify-center space-x-3 mb-8">
|
||||||
|
<div className="w-12 h-12 bg-[#173658] rounded-full flex items-center justify-center">
|
||||||
|
<svg className="w-6 h-6 text-[#d4af37]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<h2 className="text-2xl font-bold text-[#173658]">생년월일시 입력</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
<SajuForm />
|
<SajuForm />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* 안내 카드 */}
|
||||||
|
<div className="grid md:grid-cols-3 gap-6 mt-12 max-w-3xl mx-auto">
|
||||||
|
<div className="bg-white rounded-xl p-6 text-center">
|
||||||
|
<div className="text-3xl mb-3">✨</div>
|
||||||
|
<h3 className="text-[#173658] font-bold mb-2">정확한 분석</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">전통 명리학에 기반한<br />정밀한 사주 계산</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white rounded-xl p-6 text-center">
|
||||||
|
<div className="text-3xl mb-3">🎯</div>
|
||||||
|
<h3 className="text-[#173658] font-bold mb-2">무료 제공</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">기본 사주팔자는<br />무료로 확인 가능</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white rounded-xl p-6 text-center">
|
||||||
|
<div className="text-3xl mb-3">🔐</div>
|
||||||
|
<h3 className="text-[#173658] font-bold mb-2">개인정보 보호</h3>
|
||||||
|
<p className="text-sm text-[#5d6d7e]">안전하게 보호되는<br />개인정보</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Footer */}
|
<Footer />
|
||||||
<footer className="bg-gray-900 text-white py-12 px-4">
|
|
||||||
<div className="max-w-7xl mx-auto text-center">
|
|
||||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-indigo-400 to-purple-400 bg-clip-text text-transparent">
|
|
||||||
🔮 사주포춘
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-400 mb-6">
|
|
||||||
쟁승메이드가 제공하는 사주 서비스
|
|
||||||
</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
<p>문의: bgg8988@gmail.com | <a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="hover:text-indigo-400">쟁승메이드</a></p>
|
|
||||||
<p className="mt-2">© 2025 쟁승메이드. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,38 +1,25 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import TojeongForm from '../components/TojeongForm';
|
import TojeongForm from '../components/TojeongForm';
|
||||||
|
import Header from '@/components/Header';
|
||||||
|
import Footer from '@/components/Footer';
|
||||||
|
|
||||||
export default function TojeongPage() {
|
export default function TojeongPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-gradient-to-br from-amber-50 via-orange-50 to-yellow-50">
|
<div className="min-h-screen bg-[#F3E7E3]">
|
||||||
{/* Navigation */}
|
<Header />
|
||||||
<nav className="bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50">
|
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
||||||
<div className="flex justify-between items-center h-16">
|
|
||||||
<Link href="/" className="text-2xl font-bold bg-gradient-to-r from-amber-600 to-orange-600 bg-clip-text text-transparent">
|
|
||||||
🔮 사주보기
|
|
||||||
</Link>
|
|
||||||
<Link
|
|
||||||
href="/"
|
|
||||||
className="text-gray-700 hover:text-amber-600 transition font-medium"
|
|
||||||
>
|
|
||||||
처음으로
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<section className="pt-20 pb-32 px-4">
|
<section className="pt-32 pb-20 px-4">
|
||||||
<div className="max-w-4xl mx-auto text-center mb-12">
|
<div className="max-w-4xl mx-auto text-center mb-12">
|
||||||
<div className="inline-block mb-6 px-6 py-2 bg-white/50 backdrop-blur-sm rounded-full text-amber-700 font-semibold border border-amber-200">
|
<div className="inline-block mb-6 px-6 py-2 bg-white rounded-full text-[#173658] font-bold border-2 border-[#173658]">
|
||||||
한 해의 운세를 미리 확인하세요
|
한 해의 운세를 미리 확인하세요
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-6 leading-tight">
|
<h1 className="text-4xl md:text-6xl font-bold text-[#173658] mb-6 leading-tight">
|
||||||
🎋 <span className="bg-gradient-to-r from-amber-600 to-orange-600 bg-clip-text text-transparent">토정비결</span>
|
🎋 <span className="gradient-text">토정비결</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="text-xl text-gray-600 mb-12 max-w-2xl mx-auto">
|
<p className="text-xl text-[#5d6d7e] mb-12 max-w-2xl mx-auto leading-relaxed">
|
||||||
조선시대 토정 이지함 선생이 창안한 역술서로,
|
조선시대 토정 이지함 선생이 창안한 역술서로,
|
||||||
한 해 동안의 운세를 월별로 확인할 수 있습니다.
|
한 해 동안의 운세를 월별로 확인할 수 있습니다.
|
||||||
</p>
|
</p>
|
||||||
@@ -48,31 +35,31 @@ export default function TojeongPage() {
|
|||||||
<section className="py-20 px-4 bg-white">
|
<section className="py-20 px-4 bg-white">
|
||||||
<div className="max-w-6xl mx-auto">
|
<div className="max-w-6xl mx-auto">
|
||||||
<div className="text-center mb-16">
|
<div className="text-center mb-16">
|
||||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">토정비결이란?</h2>
|
<h2 className="text-3xl md:text-4xl font-bold text-[#173658] mb-4">토정비결이란?</h2>
|
||||||
<p className="text-xl text-gray-600">조선시대부터 전해 내려오는 전통 운세</p>
|
<p className="text-xl text-[#5d6d7e]">조선시대부터 전해 내려오는 전통 운세</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid md:grid-cols-3 gap-8">
|
<div className="grid md:grid-cols-3 gap-8">
|
||||||
<div className="text-center p-6 rounded-2xl hover:bg-amber-50 transition">
|
<div className="text-center p-6 glass-panel-light rounded-2xl card-hover">
|
||||||
<div className="text-5xl mb-4">📅</div>
|
<div className="text-5xl mb-4">📅</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-3">한 해 운세</h3>
|
<h3 className="text-xl font-bold text-[#173658] mb-3">한 해 운세</h3>
|
||||||
<p className="text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
새해부터 연말까지 전체적인 운의 흐름을 미리 파악할 수 있습니다.
|
새해부터 연말까지 전체적인 운의 흐름을 미리 파악할 수 있습니다.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center p-6 rounded-2xl hover:bg-orange-50 transition">
|
<div className="text-center p-6 glass-panel-light rounded-2xl card-hover">
|
||||||
<div className="text-5xl mb-4">📆</div>
|
<div className="text-5xl mb-4">📆</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-3">월별 운세</h3>
|
<h3 className="text-xl font-bold text-[#173658] mb-3">월별 운세</h3>
|
||||||
<p className="text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
12개월 각각의 운세를 확인하여 중요한 결정을 내리는 데 참고하세요.
|
12개월 각각의 운세를 확인하여 중요한 결정을 내리는 데 참고하세요.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="text-center p-6 rounded-2xl hover:bg-yellow-50 transition">
|
<div className="text-center p-6 glass-panel-light rounded-2xl card-hover">
|
||||||
<div className="text-5xl mb-4">🎯</div>
|
<div className="text-5xl mb-4">🎯</div>
|
||||||
<h3 className="text-xl font-bold text-gray-900 mb-3">분야별 운세</h3>
|
<h3 className="text-xl font-bold text-[#173658] mb-3">분야별 운세</h3>
|
||||||
<p className="text-gray-600">
|
<p className="text-[#5d6d7e]">
|
||||||
재물, 건강, 관운 등 분야별로 세분화된 운세 정보를 제공합니다.
|
재물, 건강, 관운 등 분야별로 세분화된 운세 정보를 제공합니다.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -80,21 +67,7 @@ export default function TojeongPage() {
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Footer */}
|
<Footer />
|
||||||
<footer className="bg-gray-900 text-white py-12 px-4">
|
|
||||||
<div className="max-w-7xl mx-auto text-center">
|
|
||||||
<div className="text-2xl font-bold mb-4 bg-gradient-to-r from-amber-400 to-orange-400 bg-clip-text text-transparent">
|
|
||||||
🔮 사주보기
|
|
||||||
</div>
|
|
||||||
<p className="text-gray-400 mb-6">
|
|
||||||
쟁승메이드가 제공하는 무료 사주 서비스
|
|
||||||
</p>
|
|
||||||
<div className="text-sm text-gray-500">
|
|
||||||
<p>문의: bgg8988@gmail.com | <a href="https://jaengseung-made.com" target="_blank" rel="noopener noreferrer" className="hover:text-amber-400">쟁승메이드</a></p>
|
|
||||||
<p className="mt-2">© 2025 쟁승메이드. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,14 +191,14 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
|
|||||||
// Loading View
|
// Loading View
|
||||||
if (loading || checkingRecord) {
|
if (loading || checkingRecord) {
|
||||||
return (
|
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="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">
|
<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 ? '기존 기록을 확인하고 있습니다...' : '사주를 분석하고 있습니다...'}
|
{checkingRecord ? '기존 기록을 확인하고 있습니다...' : '사주를 분석하고 있습니다...'}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-gray-500">
|
<p className="text-[#5d6d7e]">
|
||||||
{checkingRecord
|
{checkingRecord
|
||||||
? '잠시만 기다려주세요.'
|
? '잠시만 기다려주세요.'
|
||||||
: <>천간과 지지의 조화, 대운의 흐름을 깊이 있게 해석 중입니다.<br />잠시만 기다려주세요.</>
|
: <>천간과 지지의 조화, 대운의 흐름을 깊이 있게 해석 중입니다.<br />잠시만 기다려주세요.</>
|
||||||
@@ -214,30 +214,30 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
|
|||||||
if (!isUnlocked) {
|
if (!isUnlocked) {
|
||||||
return (
|
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="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-white/80 to-white z-10 flex flex-col items-center justify-center pb-12">
|
<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 border-indigo-100 max-w-sm mx-auto">
|
<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>
|
<div className="text-4xl mb-4">🔐</div>
|
||||||
<h3 className="text-2xl font-bold text-gray-900 mb-2">전문가 심층 분석 잠금해제</h3>
|
<h3 className="text-2xl font-bold text-[#173658] mb-2">전문가 심층 분석 잠금해제</h3>
|
||||||
<p className="text-gray-600 mb-2">
|
<p className="text-[#5d6d7e] mb-2">
|
||||||
AI 명리학자의 소름 돋는 인생 해석을 확인하세요.
|
AI 명리학자의 소름 돋는 인생 해석을 확인하세요.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-gray-500 mb-4">
|
<p className="text-sm text-[#5d6d7e] mb-4">
|
||||||
토큰 1개 사용 | 보유: <span className="font-bold text-indigo-600">{credits}개</span>
|
토큰 10개 사용 | 보유: <span className="font-bold text-[#173658]">{credits}개</span>
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={handleTokenUse}
|
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>
|
<span>토큰 충전하기</span>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
<p className="text-xs text-gray-400 mt-4">
|
<p className="text-xs text-[#5d6d7e] mt-4">
|
||||||
* 결제 후 평생 소장 가능합니다.<br />
|
* 결제 후 평생 소장 가능합니다.<br />
|
||||||
* 같은 생년월일 재접근 시 토큰이 차감되지 않아요.
|
* 같은 생년월일 재접근 시 토큰이 차감되지 않아요.
|
||||||
</p>
|
</p>
|
||||||
@@ -246,8 +246,8 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
|
|||||||
|
|
||||||
{/* Blurred Content Placeholder */}
|
{/* Blurred Content Placeholder */}
|
||||||
<div className="filter blur-sm select-none opacity-50 pointer-events-none">
|
<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">
|
<h2 className="text-2xl font-bold text-[#173658] mb-8 text-center flex items-center justify-center">
|
||||||
<span className="text-4xl mr-3">✨</span>
|
<span className="text-3xl mr-3">✨</span>
|
||||||
당신을 위한 맞춤 심층 분석
|
당신을 위한 맞춤 심층 분석
|
||||||
</h2>
|
</h2>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@@ -290,13 +290,13 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
|
|||||||
const sections = interpretation ? parseSections(interpretation) : [];
|
const sections = interpretation ? parseSections(interpretation) : [];
|
||||||
|
|
||||||
return (
|
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">
|
<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>
|
</h2>
|
||||||
<p className="text-gray-500">AI 사주 상담사가 당신만을 위해 정성껏 풀어봤어요.</p>
|
<p className="text-[#5d6d7e]">AI 사주 상담사가 당신만을 위해 정성껏 풀어봤어요.</p>
|
||||||
{user && <span className="inline-block mt-2 px-3 py-1 bg-green-100 text-green-700 text-xs rounded-full">잠금해제 완료 / 평생 소장</span>}
|
{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>
|
</div>
|
||||||
|
|
||||||
{sections.length > 0 ? (
|
{sections.length > 0 ? (
|
||||||
@@ -312,18 +312,18 @@ export default function AiInterpretationSection({ sajuData, currentDaeun, daeunL
|
|||||||
))}
|
))}
|
||||||
</div>
|
</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]}>
|
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||||
{interpretation || ''}
|
{interpretation || ''}
|
||||||
</ReactMarkdown>
|
</ReactMarkdown>
|
||||||
</article>
|
</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>
|
<span className="text-2xl pt-1">💡</span>
|
||||||
<div>
|
<div>
|
||||||
<h4 className="font-bold text-indigo-900 mb-1">참고하세요</h4>
|
<h4 className="font-bold text-[#173658] mb-1">참고하세요</h4>
|
||||||
<p className="text-sm text-indigo-800/80 leading-relaxed">
|
<p className="text-sm text-[#5d6d7e] leading-relaxed">
|
||||||
이 분석은 전통 명리학 알고리즘과 AI를 결합하여 만들어졌어요.
|
이 분석은 전통 명리학 알고리즘과 AI를 결합하여 만들어졌어요.
|
||||||
인생의 큰 흐름을 이해하는 데 도움이 되길 바라며,
|
인생의 큰 흐름을 이해하는 데 도움이 되길 바라며,
|
||||||
모든 선택의 주인공은 언제나 당신이라는 걸 잊지 마세요.
|
모든 선택의 주인공은 언제나 당신이라는 걸 잊지 마세요.
|
||||||
|
|||||||
161
components/Footer.tsx
Normal file
161
components/Footer.tsx
Normal 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>© {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
186
components/Header.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -7,8 +7,9 @@
|
|||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "eslint",
|
"lint": "eslint",
|
||||||
"release:nas": "node scripts/deploy-nas.cjs",
|
"release:nas": "node scripts/deploy-nas-scp.cjs",
|
||||||
"deploy:ssh": "cross-env NAS_DEPLOY_METHOD=ssh node scripts/deploy-nas.cjs"
|
"deploy:ssh": "node scripts/deploy-nas-scp.cjs",
|
||||||
|
"deploy:rsync": "node scripts/deploy-nas.cjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supabase/ssr": "^0.8.0",
|
"@supabase/ssr": "^0.8.0",
|
||||||
|
|||||||
114
scripts/deploy-nas-scp.cjs
Normal file
114
scripts/deploy-nas-scp.cjs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const { execSync } = require("child_process");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
const isWin = process.platform === "win32";
|
||||||
|
const projectName = "saju-web";
|
||||||
|
const projectRoot = path.resolve(__dirname, "..");
|
||||||
|
|
||||||
|
// SSH 설정
|
||||||
|
const sshTarget = process.env.NAS_SSH_TARGET || "bgg8988@192.168.45.54";
|
||||||
|
const sshPath = process.env.NAS_SSH_PATH || `/volume1/docker/webpage/${projectName}`;
|
||||||
|
const sshPort = process.env.NAS_SSH_PORT || "2300";
|
||||||
|
|
||||||
|
console.log("🚀 Saju Web NAS Deployment (SCP Mode)");
|
||||||
|
console.log("=====================================");
|
||||||
|
console.log(`Target: ${sshTarget}:${sshPath}`);
|
||||||
|
console.log("");
|
||||||
|
|
||||||
|
try {
|
||||||
|
const sshCmd = sshPort ? `ssh -p ${sshPort}` : "ssh";
|
||||||
|
const scpCmd = sshPort ? `scp -P ${sshPort}` : "scp";
|
||||||
|
|
||||||
|
// 1. NAS에 디렉토리 생성
|
||||||
|
console.log("📦 Step 1: Preparing NAS directory...");
|
||||||
|
execSync(`${sshCmd} ${sshTarget} "mkdir -p ${sshPath}"`, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
console.log("✅ Directory ready");
|
||||||
|
console.log("");
|
||||||
|
|
||||||
|
// 2. 파일 전송 (tar + ssh pipe)
|
||||||
|
console.log("📤 Step 2: Transferring files to NAS...");
|
||||||
|
const excludeArgs = [
|
||||||
|
"--exclude=node_modules",
|
||||||
|
"--exclude=.next",
|
||||||
|
"--exclude=.git",
|
||||||
|
"--exclude=dist",
|
||||||
|
"--exclude=out",
|
||||||
|
"--exclude=.env.local",
|
||||||
|
"--exclude=*.log",
|
||||||
|
"--exclude=saju-web-deploy.tar.gz",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
|
// tar로 압축하면서 동시에 ssh로 전송
|
||||||
|
const transferCmd = `tar -czf - ${excludeArgs} . | ${sshCmd} ${sshTarget} "cd ${sshPath} && tar -xzf -"`;
|
||||||
|
console.log("Transferring files (this may take a moment)...");
|
||||||
|
|
||||||
|
execSync(transferCmd, {
|
||||||
|
cwd: projectRoot,
|
||||||
|
stdio: "inherit",
|
||||||
|
shell: true,
|
||||||
|
});
|
||||||
|
console.log("✅ Files transferred");
|
||||||
|
console.log("");
|
||||||
|
|
||||||
|
// 3. NAS에서 배포
|
||||||
|
console.log("📝 Step 3: Deploying on NAS...");
|
||||||
|
|
||||||
|
// Docker 명령어 경로 (Synology NAS)
|
||||||
|
// 기본값: sudo 없이 실행
|
||||||
|
const dockerCmd = process.env.NAS_USE_SUDO === "true"
|
||||||
|
? "sudo /usr/local/bin/docker"
|
||||||
|
: "/usr/local/bin/docker";
|
||||||
|
|
||||||
|
// 환경 변수 설정
|
||||||
|
console.log(" - Setting up environment...");
|
||||||
|
execSync(`${sshCmd} ${sshTarget} "cd ${sshPath} && if [ -f .env.nas ]; then cp -f .env.nas .env; fi"`, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
// Docker 빌드 및 배포
|
||||||
|
console.log(" - Building Docker container...");
|
||||||
|
execSync(`${sshCmd} ${sshTarget} "cd /volume1/docker/webpage && ${dockerCmd} compose build ${projectName}"`, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(" - Starting container...");
|
||||||
|
execSync(`${sshCmd} ${sshTarget} "cd /volume1/docker/webpage && ${dockerCmd} compose up -d ${projectName}"`, {
|
||||||
|
stdio: "inherit",
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("✅ Deployment complete");
|
||||||
|
console.log("");
|
||||||
|
|
||||||
|
// 5. 헬스체크
|
||||||
|
console.log("🏥 Step 4: Health check...");
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
const healthCmd = `${sshCmd} ${sshTarget} "docker exec ${projectName} wget -q -O- http://localhost:3000/api/health"`;
|
||||||
|
const health = execSync(healthCmd, { encoding: "utf-8" });
|
||||||
|
console.log("Health check response:", health);
|
||||||
|
console.log("✅ Service is healthy");
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("⚠️ Health check failed (service may still be starting)");
|
||||||
|
}
|
||||||
|
console.log("");
|
||||||
|
console.log("🎉 Deployment completed!");
|
||||||
|
console.log("=====================================");
|
||||||
|
console.log(`🌐 Access: http://gahusb.synology.me/saju`);
|
||||||
|
console.log("");
|
||||||
|
}, 3000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ Deployment failed:", err.message);
|
||||||
|
|
||||||
|
// 에러 발생 시 임시 파일 정리
|
||||||
|
const archivePath = path.join(projectRoot, "saju-web-deploy.tar.gz");
|
||||||
|
if (fs.existsSync(archivePath)) {
|
||||||
|
fs.unlinkSync(archivePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
@@ -17,9 +17,9 @@ const dstMac = `/Volumes/gahusb.synology.me/docker/webpage/${projectName}/`;
|
|||||||
const dst = isWin ? dstWin : dstMac;
|
const dst = isWin ? dstWin : dstMac;
|
||||||
|
|
||||||
// SSH 설정 (환경 변수에서 읽기)
|
// SSH 설정 (환경 변수에서 읽기)
|
||||||
const sshTarget = process.env.NAS_SSH_TARGET || "gahusb@gahusb.synology.me";
|
const sshTarget = process.env.NAS_SSH_TARGET || "bgg8988@192.168.45.54";
|
||||||
const sshPath = process.env.NAS_SSH_PATH || `/volume1/docker/webpage/${projectName}`;
|
const sshPath = process.env.NAS_SSH_PATH || `/volume1/docker/webpage/${projectName}`;
|
||||||
const sshPort = process.env.NAS_SSH_PORT;
|
const sshPort = process.env.NAS_SSH_PORT || "2300";
|
||||||
|
|
||||||
// 제외할 파일/폴더
|
// 제외할 파일/폴더
|
||||||
const excludePatterns = [
|
const excludePatterns = [
|
||||||
@@ -56,9 +56,59 @@ if (process.env.NAS_DEPLOY_METHOD === "ssh" || sshTarget) {
|
|||||||
try {
|
try {
|
||||||
// 1. rsync로 파일 동기화
|
// 1. rsync로 파일 동기화
|
||||||
console.log("📦 Step 1: Syncing files to NAS...");
|
console.log("📦 Step 1: Syncing files to NAS...");
|
||||||
const rsyncCmd = `rsync -avz --delete ${excludeArgs} -e "${sshCmd}" ${projectRoot}/ ${sshTarget}:${sshPath}/`;
|
|
||||||
|
// Windows에서 rsync 찾기 (Git Bash 또는 WSL)
|
||||||
|
let rsyncPath = "rsync";
|
||||||
|
let sourcePath = projectRoot;
|
||||||
|
|
||||||
|
if (isWin) {
|
||||||
|
// Git Bash에서 실행 중이면 rsync를 바로 사용 가능
|
||||||
|
try {
|
||||||
|
execSync("rsync --version", { stdio: "ignore" });
|
||||||
|
rsyncPath = "rsync";
|
||||||
|
console.log("✅ Using rsync from Git Bash");
|
||||||
|
} catch (err) {
|
||||||
|
// Git Bash가 아니면 rsync.exe 찾기
|
||||||
|
const possiblePaths = [
|
||||||
|
"C:\\Program Files\\Git\\usr\\bin\\rsync.exe",
|
||||||
|
"C:\\Program Files (x86)\\Git\\usr\\bin\\rsync.exe",
|
||||||
|
process.env.PROGRAMFILES + "\\Git\\usr\\bin\\rsync.exe",
|
||||||
|
process.env.LOCALAPPDATA + "\\Programs\\Git\\usr\\bin\\rsync.exe",
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const testPath of possiblePaths) {
|
||||||
|
if (fs.existsSync(testPath)) {
|
||||||
|
rsyncPath = testPath;
|
||||||
|
console.log(`✅ Found rsync at: ${testPath}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rsync를 못 찾으면 에러 메시지
|
||||||
|
if (rsyncPath === "rsync") {
|
||||||
|
console.error("❌ rsync not found on Windows");
|
||||||
|
console.log("");
|
||||||
|
console.log("💡 Debug: Let's find rsync");
|
||||||
|
console.log(" Run this in Git Bash: which rsync");
|
||||||
|
console.log("");
|
||||||
|
console.log(" Then update the script with the correct path.");
|
||||||
|
console.log("");
|
||||||
|
console.log(" Or use SMB mount deployment:");
|
||||||
|
console.log(" npm run release:nas");
|
||||||
|
console.log("");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows 경로를 Git Bash 스타일로 변환 (C:\... -> /c/...)
|
||||||
|
sourcePath = projectRoot
|
||||||
|
.replace(/\\/g, "/")
|
||||||
|
.replace(/^([A-Z]):/, (match, drive) => `/${drive.toLowerCase()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rsyncCmd = `"${rsyncPath}" -avz --delete ${excludeArgs} -e "${sshCmd}" "${sourcePath}/" ${sshTarget}:${sshPath}/`;
|
||||||
console.log(`Command: ${rsyncCmd}`);
|
console.log(`Command: ${rsyncCmd}`);
|
||||||
execSync(rsyncCmd, { stdio: "inherit" });
|
execSync(rsyncCmd, { stdio: "inherit", shell: true });
|
||||||
console.log("✅ Files synced successfully");
|
console.log("✅ Files synced successfully");
|
||||||
console.log("");
|
console.log("");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user