feat: 사주 웹사이트 핵심 기능 구현
- 사주팔자 계산 라이브러리 구현 (천간, 지지, 십성, 십이운성) - 사주 결과 페이지 구현 (사주팔자 표 및 해석) - 오늘의 운세 페이지 구현 (일일 운세, 행운의 요소) - 궁합 보기 기능 구현 (두 사람 입력 폼) - 궁합 결과 페이지 구현 (종합 점수, 세부 분석) - 페이지 간 네비게이션 연결 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
100
app/compatibility/page.tsx
Normal file
100
app/compatibility/page.tsx
Normal file
@@ -0,0 +1,100 @@
|
||||
import Link from 'next/link';
|
||||
import CompatibilityForm from '../components/CompatibilityForm';
|
||||
|
||||
export default function CompatibilityPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-pink-50 via-purple-50 to-indigo-50">
|
||||
{/* Navigation */}
|
||||
<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 */}
|
||||
<section className="pt-20 pb-32 px-4">
|
||||
<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>
|
||||
|
||||
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-6 leading-tight">
|
||||
💕 <span className="bg-gradient-to-r from-pink-600 to-purple-600 bg-clip-text text-transparent">궁합</span> 보기
|
||||
</h1>
|
||||
|
||||
<p className="text-xl text-gray-600 mb-12 max-w-2xl mx-auto">
|
||||
사주팔자를 비교하여 두 사람의 궁합을 확인할 수 있습니다.
|
||||
연애, 결혼, 사업 등 다양한 관계의 궁합을 알아보세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Input Form */}
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<CompatibilityForm />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 궁합 정보 */}
|
||||
<section className="py-20 px-4 bg-white">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">궁합이란?</h2>
|
||||
<p className="text-xl text-gray-600">사주팔자를 통해 알아보는 두 사람의 인연</p>
|
||||
</div>
|
||||
|
||||
<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-5xl mb-4">💑</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">연애 궁합</h3>
|
||||
<p className="text-gray-600">
|
||||
두 사람의 사랑이 얼마나 잘 맞는지 확인하고 서로를 이해하는 방법을 알아보세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center p-6 rounded-2xl hover:bg-purple-50 transition">
|
||||
<div className="text-5xl mb-4">💍</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">결혼 궁합</h3>
|
||||
<p className="text-gray-600">
|
||||
평생을 함께할 배우자와의 궁합을 확인하고 행복한 결혼 생활을 준비하세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="text-center p-6 rounded-2xl hover:bg-indigo-50 transition">
|
||||
<div className="text-5xl mb-4">🤝</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">사업 궁합</h3>
|
||||
<p className="text-gray-600">
|
||||
사업 파트너와의 궁합을 확인하고 성공적인 협력 관계를 만들어보세요.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* 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>
|
||||
);
|
||||
}
|
||||
395
app/compatibility/result/page.tsx
Normal file
395
app/compatibility/result/page.tsx
Normal file
@@ -0,0 +1,395 @@
|
||||
import Link from 'next/link';
|
||||
import { calculateSaju, FIVE_ELEMENTS } from '@/lib/saju-calculator';
|
||||
|
||||
interface PageProps {
|
||||
searchParams: Promise<{
|
||||
year1: string;
|
||||
month1: string;
|
||||
day1: string;
|
||||
hour1?: string;
|
||||
gender1: 'male' | 'female';
|
||||
year2: string;
|
||||
month2: string;
|
||||
day2: string;
|
||||
hour2?: string;
|
||||
gender2: 'male' | 'female';
|
||||
}>;
|
||||
}
|
||||
|
||||
export default async function CompatibilityResultPage({ searchParams }: PageProps) {
|
||||
const params = await searchParams;
|
||||
const { year1, month1, day1, hour1, gender1, year2, month2, day2, hour2, gender2 } = params;
|
||||
|
||||
// Person 1 Saju
|
||||
const saju1 = calculateSaju(
|
||||
parseInt(year1),
|
||||
parseInt(month1),
|
||||
parseInt(day1),
|
||||
hour1 ? parseInt(hour1) : null,
|
||||
gender1
|
||||
);
|
||||
|
||||
// Person 2 Saju
|
||||
const saju2 = calculateSaju(
|
||||
parseInt(year2),
|
||||
parseInt(month2),
|
||||
parseInt(day2),
|
||||
hour2 ? parseInt(hour2) : null,
|
||||
gender2
|
||||
);
|
||||
|
||||
// 궁합 점수 계산
|
||||
const calculateCompatibility = () => {
|
||||
let score = 50; // 기본 점수
|
||||
|
||||
// 오행 상생/상극 관계
|
||||
const element1 = saju1.day.element;
|
||||
const element2 = saju2.day.element;
|
||||
|
||||
const produceMap: { [key: string]: string } = {
|
||||
'木': '火', '火': '土', '土': '金', '金': '水', '水': '木'
|
||||
};
|
||||
const overcomeMap: { [key: string]: string } = {
|
||||
'木': '土', '火': '金', '土': '水', '金': '木', '水': '火'
|
||||
};
|
||||
|
||||
// 같은 오행: 보통
|
||||
if (element1 === element2) {
|
||||
score += 10;
|
||||
}
|
||||
// 상생 관계: 매우 좋음
|
||||
else if (produceMap[element1] === element2 || produceMap[element2] === element1) {
|
||||
score += 25;
|
||||
}
|
||||
// 상극 관계: 주의 필요
|
||||
else if (overcomeMap[element1] === element2 || overcomeMap[element2] === element1) {
|
||||
score -= 10;
|
||||
}
|
||||
|
||||
// 지지 삼합/육합 관계 확인
|
||||
const branch1 = saju1.day.branch;
|
||||
const branch2 = saju2.day.branch;
|
||||
|
||||
// 육합 (六合) - 특별히 좋은 궁합
|
||||
const sixHarmony: { [key: string]: string } = {
|
||||
'子': '丑', '丑': '子',
|
||||
'寅': '亥', '亥': '寅',
|
||||
'卯': '戌', '戌': '卯',
|
||||
'辰': '酉', '酉': '辰',
|
||||
'巳': '申', '申': '巳',
|
||||
'午': '未', '未': '午'
|
||||
};
|
||||
|
||||
if (sixHarmony[branch1] === branch2) {
|
||||
score += 20;
|
||||
}
|
||||
|
||||
// 삼합 (三合) - 좋은 궁합
|
||||
const threeHarmony = [
|
||||
['申', '子', '辰'], // 수국
|
||||
['寅', '午', '戌'], // 화국
|
||||
['亥', '卯', '未'], // 목국
|
||||
['巳', '酉', '丑'] // 금국
|
||||
];
|
||||
|
||||
for (const harmony of threeHarmony) {
|
||||
if (harmony.includes(branch1) && harmony.includes(branch2)) {
|
||||
score += 15;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 충 (沖) - 나쁜 궁합
|
||||
const conflict: { [key: string]: string } = {
|
||||
'子': '午', '午': '子',
|
||||
'丑': '未', '未': '丑',
|
||||
'寅': '申', '申': '寅',
|
||||
'卯': '酉', '酉': '卯',
|
||||
'辰': '戌', '戌': '辰',
|
||||
'巳': '亥', '亥': '巳'
|
||||
};
|
||||
|
||||
if (conflict[branch1] === branch2) {
|
||||
score -= 20;
|
||||
}
|
||||
|
||||
return Math.min(100, Math.max(0, score));
|
||||
};
|
||||
|
||||
const compatibilityScore = calculateCompatibility();
|
||||
|
||||
const getScoreGrade = (score: number): string => {
|
||||
if (score >= 90) return 'S';
|
||||
if (score >= 80) return 'A';
|
||||
if (score >= 70) return 'B';
|
||||
if (score >= 60) return 'C';
|
||||
return 'D';
|
||||
};
|
||||
|
||||
const getScoreText = (score: number): string => {
|
||||
if (score >= 90) return '천생연분';
|
||||
if (score >= 80) return '매우 좋음';
|
||||
if (score >= 70) return '좋음';
|
||||
if (score >= 60) return '보통';
|
||||
return '주의 필요';
|
||||
};
|
||||
|
||||
const getScoreColor = (score: number): string => {
|
||||
if (score >= 90) return 'from-pink-500 to-red-500';
|
||||
if (score >= 80) return 'from-pink-400 to-purple-400';
|
||||
if (score >= 70) return 'from-purple-400 to-indigo-400';
|
||||
if (score >= 60) return 'from-indigo-400 to-blue-400';
|
||||
return 'from-gray-400 to-gray-500';
|
||||
};
|
||||
|
||||
// 세부 궁합 점수
|
||||
const detailedScores = [
|
||||
{ name: '연애운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💑' },
|
||||
{ name: '결혼운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💍' },
|
||||
{ name: '금전운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💰' },
|
||||
{ name: '사업운', score: compatibilityScore + Math.floor(Math.random() * 10 - 5), icon: '💼' },
|
||||
].map(item => ({ ...item, score: Math.min(100, Math.max(0, item.score)) }));
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-pink-50 via-purple-50 to-indigo-50">
|
||||
{/* Navigation */}
|
||||
<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>
|
||||
<div className="flex gap-4">
|
||||
<Link
|
||||
href="/compatibility"
|
||||
className="text-gray-700 hover:text-pink-600 transition font-medium"
|
||||
>
|
||||
다시 보기
|
||||
</Link>
|
||||
<Link
|
||||
href="/"
|
||||
className="text-gray-700 hover:text-pink-600 transition font-medium"
|
||||
>
|
||||
처음으로
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Result Content */}
|
||||
<div className="max-w-6xl mx-auto px-4 py-12">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
||||
💕 궁합 결과
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600">
|
||||
두 사람의 사주팔자를 비교한 결과입니다
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 두 사람 정보 */}
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-12">
|
||||
{/* Person 1 */}
|
||||
<div className="bg-gradient-to-br from-pink-500 to-pink-600 rounded-2xl shadow-xl p-8 text-white">
|
||||
<div className="text-center mb-6">
|
||||
<div className="text-5xl mb-3">👤</div>
|
||||
<h3 className="text-2xl font-bold">첫 번째 사람</h3>
|
||||
<p className="text-pink-100 mt-2">
|
||||
{saju1.birthDate.year}년 {saju1.birthDate.month}월 {saju1.birthDate.day}일
|
||||
</p>
|
||||
<p className="text-pink-100">
|
||||
{gender1 === 'male' ? '남성' : '여성'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white/20 backdrop-blur-sm rounded-xl p-4">
|
||||
<p className="text-center mb-2 font-semibold">일간 (日干)</p>
|
||||
<div className="text-center">
|
||||
<span className="text-4xl font-bold">{saju1.day.stem}</span>
|
||||
<span className="text-2xl ml-2">({saju1.day.stemKr})</span>
|
||||
</div>
|
||||
<p className="text-center mt-2 text-pink-100">
|
||||
{saju1.day.element} ({['木', '火', '土', '金', '水'].indexOf(saju1.day.element) >= 0
|
||||
? ['목', '화', '토', '금', '수'][['木', '火', '土', '金', '水'].indexOf(saju1.day.element)]
|
||||
: ''})
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Person 2 */}
|
||||
<div className="bg-gradient-to-br from-purple-500 to-purple-600 rounded-2xl shadow-xl p-8 text-white">
|
||||
<div className="text-center mb-6">
|
||||
<div className="text-5xl mb-3">👤</div>
|
||||
<h3 className="text-2xl font-bold">두 번째 사람</h3>
|
||||
<p className="text-purple-100 mt-2">
|
||||
{saju2.birthDate.year}년 {saju2.birthDate.month}월 {saju2.birthDate.day}일
|
||||
</p>
|
||||
<p className="text-purple-100">
|
||||
{gender2 === 'male' ? '남성' : '여성'}
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white/20 backdrop-blur-sm rounded-xl p-4">
|
||||
<p className="text-center mb-2 font-semibold">일간 (日干)</p>
|
||||
<div className="text-center">
|
||||
<span className="text-4xl font-bold">{saju2.day.stem}</span>
|
||||
<span className="text-2xl ml-2">({saju2.day.stemKr})</span>
|
||||
</div>
|
||||
<p className="text-center mt-2 text-purple-100">
|
||||
{saju2.day.element} ({['木', '火', '土', '金', '水'].indexOf(saju2.day.element) >= 0
|
||||
? ['목', '화', '토', '금', '수'][['木', '火', '土', '金', '水'].indexOf(saju2.day.element)]
|
||||
: ''})
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 총합 궁합 점수 */}
|
||||
<div className={`bg-gradient-to-r ${getScoreColor(compatibilityScore)} rounded-3xl shadow-2xl p-12 mb-12 text-white`}>
|
||||
<div className="text-center">
|
||||
<h2 className="text-3xl font-bold mb-6">종합 궁합 점수</h2>
|
||||
<div className="flex items-center justify-center gap-8 mb-6">
|
||||
<div className="text-8xl font-bold">{compatibilityScore}</div>
|
||||
<div className="text-left">
|
||||
<div className="text-6xl font-bold mb-2">{getScoreGrade(compatibilityScore)}</div>
|
||||
<div className="text-2xl">{getScoreText(compatibilityScore)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="w-full bg-white/30 rounded-full h-4">
|
||||
<div
|
||||
className="bg-white h-4 rounded-full transition-all duration-1000"
|
||||
style={{ width: `${compatibilityScore}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 세부 궁합 */}
|
||||
<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">세부 궁합</h2>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{detailedScores.map((item) => (
|
||||
<div key={item.name} className="bg-gray-50 rounded-xl p-6">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-3xl">{item.icon}</span>
|
||||
<h3 className="text-xl font-bold text-gray-900">{item.name}</h3>
|
||||
</div>
|
||||
<span className="text-2xl font-bold text-pink-600">{item.score}점</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-3">
|
||||
<div
|
||||
className="bg-gradient-to-r from-pink-500 to-purple-500 h-3 rounded-full transition-all duration-500"
|
||||
style={{ width: `${item.score}%` }}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 궁합 해석 */}
|
||||
<div className="grid md:grid-cols-2 gap-8 mb-8">
|
||||
{/* 장점 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
||||
<span className="text-3xl mr-3">✅</span>
|
||||
두 사람의 장점
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<li className="flex items-start">
|
||||
<span className="text-pink-600 mr-2">•</span>
|
||||
<span>서로의 부족한 점을 잘 보완해줄 수 있습니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-pink-600 mr-2">•</span>
|
||||
<span>대화와 소통이 원활하게 이루어질 수 있습니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-pink-600 mr-2">•</span>
|
||||
<span>함께 있을 때 편안함을 느낄 수 있습니다.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 주의점 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
||||
<span className="text-3xl mr-3">⚠️</span>
|
||||
주의할 점
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<li className="flex items-start">
|
||||
<span className="text-purple-600 mr-2">•</span>
|
||||
<span>서로의 가치관 차이를 이해하려는 노력이 필요합니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-purple-600 mr-2">•</span>
|
||||
<span>감정적인 대화보다는 이성적인 대화를 나누세요.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-purple-600 mr-2">•</span>
|
||||
<span>작은 문제도 소통으로 해결하려는 자세가 중요합니다.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 조언 */}
|
||||
<div className="bg-gradient-to-r from-indigo-600 to-purple-600 rounded-2xl shadow-lg p-8 text-white mb-8">
|
||||
<h3 className="text-2xl font-bold mb-4 text-center">💡 조언</h3>
|
||||
<p className="text-lg leading-relaxed text-center">
|
||||
궁합은 참고사항일 뿐입니다. 서로를 이해하고 존중하며 노력한다면
|
||||
어떤 궁합이든 행복한 관계를 만들 수 있습니다.
|
||||
사주는 가능성을 보여줄 뿐, 최종 결정은 두 사람의 마음과 노력에 달려있습니다.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 다른 메뉴 */}
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<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>
|
||||
|
||||
<Link
|
||||
href="/"
|
||||
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>
|
||||
|
||||
<button className="bg-gradient-to-r from-pink-600 to-purple-600 text-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 mb-2">PDF 저장</h3>
|
||||
<p className="text-sm opacity-90">궁합 결과 저장하기</p>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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-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>
|
||||
);
|
||||
}
|
||||
281
app/components/CompatibilityForm.tsx
Normal file
281
app/components/CompatibilityForm.tsx
Normal file
@@ -0,0 +1,281 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function CompatibilityForm() {
|
||||
const router = useRouter();
|
||||
|
||||
// Person 1
|
||||
const [year1, setYear1] = useState('');
|
||||
const [month1, setMonth1] = useState('');
|
||||
const [day1, setDay1] = useState('');
|
||||
const [hour1, setHour1] = useState('');
|
||||
const [gender1, setGender1] = useState<'male' | 'female'>('male');
|
||||
|
||||
// Person 2
|
||||
const [year2, setYear2] = useState('');
|
||||
const [month2, setMonth2] = useState('');
|
||||
const [day2, setDay2] = useState('');
|
||||
const [hour2, setHour2] = useState('');
|
||||
const [gender2, setGender2] = useState<'male' | 'female'>('female');
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!year1 || !month1 || !day1) {
|
||||
alert('첫 번째 사람의 생년월일을 모두 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!year2 || !month2 || !day2) {
|
||||
alert('두 번째 사람의 생년월일을 모두 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// URL 파라미터로 전달
|
||||
const params = new URLSearchParams({
|
||||
year1,
|
||||
month1,
|
||||
day1,
|
||||
gender1,
|
||||
year2,
|
||||
month2,
|
||||
day2,
|
||||
gender2,
|
||||
});
|
||||
|
||||
if (hour1) params.append('hour1', hour1);
|
||||
if (hour2) params.append('hour2', hour2);
|
||||
|
||||
router.push(`/compatibility/result?${params.toString()}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="bg-white rounded-3xl shadow-2xl p-8 md:p-12">
|
||||
<div className="grid md:grid-cols-2 gap-12">
|
||||
{/* Person 1 */}
|
||||
<div className="space-y-6">
|
||||
<div className="text-center mb-6">
|
||||
<h3 className="text-2xl font-bold text-pink-600 mb-2">👤 첫 번째 사람</h3>
|
||||
<p className="text-sm text-gray-600">본인의 정보를 입력하세요</p>
|
||||
</div>
|
||||
|
||||
{/* 생년월일 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
생년월일
|
||||
</label>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="년"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-pink-500 focus:outline-none transition"
|
||||
min="1900"
|
||||
max="2100"
|
||||
value={year1}
|
||||
onChange={(e) => setYear1(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="월"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-pink-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="12"
|
||||
value={month1}
|
||||
onChange={(e) => setMonth1(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="일"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-pink-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="31"
|
||||
value={day1}
|
||||
onChange={(e) => setDay1(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 태어난 시간 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
태어난 시간 (선택)
|
||||
</label>
|
||||
<select
|
||||
className="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-pink-500 focus:outline-none transition"
|
||||
value={hour1}
|
||||
onChange={(e) => setHour1(e.target.value)}
|
||||
>
|
||||
<option value="">모름 / 선택 안함</option>
|
||||
<option value="0">자시 (23:00-01:00)</option>
|
||||
<option value="1">축시 (01:00-03:00)</option>
|
||||
<option value="3">인시 (03:00-05:00)</option>
|
||||
<option value="5">묘시 (05:00-07:00)</option>
|
||||
<option value="7">진시 (07:00-09:00)</option>
|
||||
<option value="9">사시 (09:00-11:00)</option>
|
||||
<option value="11">오시 (11:00-13:00)</option>
|
||||
<option value="13">미시 (13:00-15:00)</option>
|
||||
<option value="15">신시 (15:00-17:00)</option>
|
||||
<option value="17">유시 (17:00-19:00)</option>
|
||||
<option value="19">술시 (19:00-21:00)</option>
|
||||
<option value="21">해시 (21:00-23:00)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* 성별 선택 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
성별
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setGender1('male')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
gender1 === 'male'
|
||||
? 'bg-pink-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-pink-500 hover:text-pink-600'
|
||||
}`}
|
||||
>
|
||||
남성
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setGender1('female')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
gender1 === 'female'
|
||||
? 'bg-pink-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-pink-500 hover:text-pink-600'
|
||||
}`}
|
||||
>
|
||||
여성
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Person 2 */}
|
||||
<div className="space-y-6">
|
||||
<div className="text-center mb-6">
|
||||
<h3 className="text-2xl font-bold text-purple-600 mb-2">👤 두 번째 사람</h3>
|
||||
<p className="text-sm text-gray-600">상대방의 정보를 입력하세요</p>
|
||||
</div>
|
||||
|
||||
{/* 생년월일 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
생년월일
|
||||
</label>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="년"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-purple-500 focus:outline-none transition"
|
||||
min="1900"
|
||||
max="2100"
|
||||
value={year2}
|
||||
onChange={(e) => setYear2(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="월"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-purple-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="12"
|
||||
value={month2}
|
||||
onChange={(e) => setMonth2(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="일"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-purple-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="31"
|
||||
value={day2}
|
||||
onChange={(e) => setDay2(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 태어난 시간 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
태어난 시간 (선택)
|
||||
</label>
|
||||
<select
|
||||
className="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-purple-500 focus:outline-none transition"
|
||||
value={hour2}
|
||||
onChange={(e) => setHour2(e.target.value)}
|
||||
>
|
||||
<option value="">모름 / 선택 안함</option>
|
||||
<option value="0">자시 (23:00-01:00)</option>
|
||||
<option value="1">축시 (01:00-03:00)</option>
|
||||
<option value="3">인시 (03:00-05:00)</option>
|
||||
<option value="5">묘시 (05:00-07:00)</option>
|
||||
<option value="7">진시 (07:00-09:00)</option>
|
||||
<option value="9">사시 (09:00-11:00)</option>
|
||||
<option value="11">오시 (11:00-13:00)</option>
|
||||
<option value="13">미시 (13:00-15:00)</option>
|
||||
<option value="15">신시 (15:00-17:00)</option>
|
||||
<option value="17">유시 (17:00-19:00)</option>
|
||||
<option value="19">술시 (19:00-21:00)</option>
|
||||
<option value="21">해시 (21:00-23:00)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* 성별 선택 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
성별
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setGender2('male')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
gender2 === 'male'
|
||||
? 'bg-purple-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-purple-500 hover:text-purple-600'
|
||||
}`}
|
||||
>
|
||||
남성
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setGender2('female')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
gender2 === 'female'
|
||||
? 'bg-purple-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-purple-500 hover:text-purple-600'
|
||||
}`}
|
||||
>
|
||||
여성
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 제출 버튼 */}
|
||||
<div className="mt-8">
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-gradient-to-r from-pink-600 to-purple-600 text-white py-4 rounded-xl text-lg font-bold hover:from-pink-700 hover:to-purple-700 transition shadow-lg hover:shadow-xl"
|
||||
>
|
||||
💕 궁합 확인하기 →
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-sm text-gray-500 text-center mt-4">
|
||||
* 태어난 시간을 정확히 아시면 더 정확한 궁합을 확인할 수 있습니다.
|
||||
</p>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
181
app/components/SajuForm.tsx
Normal file
181
app/components/SajuForm.tsx
Normal file
@@ -0,0 +1,181 @@
|
||||
'use client';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
export default function SajuForm() {
|
||||
const router = useRouter();
|
||||
const [year, setYear] = useState('');
|
||||
const [month, setMonth] = useState('');
|
||||
const [day, setDay] = useState('');
|
||||
const [hour, setHour] = useState('');
|
||||
const [calendarType, setCalendarType] = useState<'solar' | 'lunar'>('solar');
|
||||
const [gender, setGender] = useState<'male' | 'female'>('male');
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (!year || !month || !day) {
|
||||
alert('생년월일을 모두 입력해주세요.');
|
||||
return;
|
||||
}
|
||||
|
||||
// URL 파라미터로 전달
|
||||
const params = new URLSearchParams({
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
gender,
|
||||
calendarType
|
||||
});
|
||||
|
||||
if (hour) {
|
||||
params.append('hour', hour);
|
||||
}
|
||||
|
||||
router.push(`/result?${params.toString()}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
{/* 생년월일 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
생년월일
|
||||
</label>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="년 (예: 1990)"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
min="1900"
|
||||
max="2100"
|
||||
value={year}
|
||||
onChange={(e) => setYear(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="월 (1-12)"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="12"
|
||||
value={month}
|
||||
onChange={(e) => setMonth(e.target.value)}
|
||||
required
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="일 (1-31)"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="31"
|
||||
value={day}
|
||||
onChange={(e) => setDay(e.target.value)}
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 태어난 시간 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
태어난 시간 (선택)
|
||||
</label>
|
||||
<select
|
||||
className="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
value={hour}
|
||||
onChange={(e) => setHour(e.target.value)}
|
||||
>
|
||||
<option value="">모름 / 시간 선택 안함</option>
|
||||
<option value="0">자시 (子時) 23:00 - 01:00</option>
|
||||
<option value="1">축시 (丑時) 01:00 - 03:00</option>
|
||||
<option value="3">인시 (寅時) 03:00 - 05:00</option>
|
||||
<option value="5">묘시 (卯時) 05:00 - 07:00</option>
|
||||
<option value="7">진시 (辰時) 07:00 - 09:00</option>
|
||||
<option value="9">사시 (巳時) 09:00 - 11:00</option>
|
||||
<option value="11">오시 (午時) 11:00 - 13:00</option>
|
||||
<option value="13">미시 (未時) 13:00 - 15:00</option>
|
||||
<option value="15">신시 (申時) 15:00 - 17:00</option>
|
||||
<option value="17">유시 (酉時) 17:00 - 19:00</option>
|
||||
<option value="19">술시 (戌時) 19:00 - 21:00</option>
|
||||
<option value="21">해시 (亥時) 21:00 - 23:00</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* 양력/음력 선택 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
생일 구분
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setCalendarType('solar')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
calendarType === 'solar'
|
||||
? 'bg-indigo-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
||||
}`}
|
||||
>
|
||||
양력
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setCalendarType('lunar')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
calendarType === 'lunar'
|
||||
? 'bg-indigo-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
||||
}`}
|
||||
>
|
||||
음력
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 성별 선택 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
성별
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setGender('male')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
gender === 'male'
|
||||
? 'bg-indigo-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
||||
}`}
|
||||
>
|
||||
남성
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setGender('female')}
|
||||
className={`px-6 py-3 rounded-xl font-semibold transition ${
|
||||
gender === 'female'
|
||||
? 'bg-indigo-600 text-white'
|
||||
: 'bg-white border-2 border-gray-200 text-gray-700 hover:border-indigo-500 hover:text-indigo-600'
|
||||
}`}
|
||||
>
|
||||
여성
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 제출 버튼 */}
|
||||
<button
|
||||
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"
|
||||
>
|
||||
내 사주 보기 →
|
||||
</button>
|
||||
|
||||
<p className="text-sm text-gray-500 text-center">
|
||||
* 태어난 시간을 정확히 아시면 더 정확한 사주를 확인할 수 있습니다.
|
||||
</p>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
268
app/fortune/page.tsx
Normal file
268
app/fortune/page.tsx
Normal file
@@ -0,0 +1,268 @@
|
||||
import Link from 'next/link';
|
||||
import { calculateSaju } from '@/lib/saju-calculator';
|
||||
|
||||
interface PageProps {
|
||||
searchParams: Promise<{
|
||||
year: string;
|
||||
month: string;
|
||||
day: string;
|
||||
hour?: string;
|
||||
gender: 'male' | 'female';
|
||||
calendarType: 'solar' | 'lunar';
|
||||
}>;
|
||||
}
|
||||
|
||||
export default async function FortunePage({ searchParams }: PageProps) {
|
||||
const params = await searchParams;
|
||||
const { year, month, day, hour, gender } = params;
|
||||
|
||||
const yearNum = parseInt(year);
|
||||
const monthNum = parseInt(month);
|
||||
const dayNum = parseInt(day);
|
||||
const hourNum = hour ? parseInt(hour) : null;
|
||||
|
||||
const sajuData = calculateSaju(yearNum, monthNum, dayNum, hourNum, gender);
|
||||
|
||||
// 오늘 날짜
|
||||
const today = new Date();
|
||||
const todayYear = today.getFullYear();
|
||||
const todayMonth = today.getMonth() + 1;
|
||||
const todayDay = today.getDate();
|
||||
|
||||
// 오늘의 간지 계산
|
||||
const todayGanzi = calculateSaju(todayYear, todayMonth, todayDay, null, gender);
|
||||
|
||||
// 운세 점수 계산 (간단한 알고리즘)
|
||||
const calculateFortuneScore = (category: string): number => {
|
||||
const seed = sajuData.day.stem.charCodeAt(0) + todayGanzi.day.stem.charCodeAt(0) + category.charCodeAt(0);
|
||||
return 60 + (seed % 40);
|
||||
};
|
||||
|
||||
const fortuneCategories = [
|
||||
{ name: '종합운', icon: '⭐', score: calculateFortuneScore('종합'), color: 'indigo' },
|
||||
{ name: '금전운', icon: '💰', score: calculateFortuneScore('금전'), color: 'green' },
|
||||
{ name: '애정운', icon: '💕', score: calculateFortuneScore('애정'), color: 'pink' },
|
||||
{ name: '건강운', icon: '🏥', score: calculateFortuneScore('건강'), color: 'red' },
|
||||
{ name: '직장운', icon: '💼', score: calculateFortuneScore('직장'), color: 'blue' },
|
||||
{ name: '학업운', icon: '📚', score: calculateFortuneScore('학업'), color: 'purple' },
|
||||
];
|
||||
|
||||
const getScoreText = (score: number): string => {
|
||||
if (score >= 90) return '최고';
|
||||
if (score >= 80) return '좋음';
|
||||
if (score >= 70) return '보통';
|
||||
if (score >= 60) return '주의';
|
||||
return '나쁨';
|
||||
};
|
||||
|
||||
const getScoreColor = (score: number): string => {
|
||||
if (score >= 90) return 'text-green-600';
|
||||
if (score >= 80) return 'text-blue-600';
|
||||
if (score >= 70) return 'text-yellow-600';
|
||||
if (score >= 60) return 'text-orange-600';
|
||||
return 'text-red-600';
|
||||
};
|
||||
|
||||
// 행운의 방향과 색깔 (일간 기준)
|
||||
const getLuckyDirection = (stem: string): string => {
|
||||
const directions: { [key: string]: string } = {
|
||||
'甲': '동쪽', '乙': '동쪽',
|
||||
'丙': '남쪽', '丁': '남쪽',
|
||||
'戊': '중앙', '己': '중앙',
|
||||
'庚': '서쪽', '辛': '서쪽',
|
||||
'壬': '북쪽', '癸': '북쪽',
|
||||
};
|
||||
return directions[stem] || '동쪽';
|
||||
};
|
||||
|
||||
const getLuckyColor = (element: string): string => {
|
||||
const colors: { [key: string]: string } = {
|
||||
'木': '녹색',
|
||||
'火': '빨강색',
|
||||
'土': '노란색',
|
||||
'金': '흰색',
|
||||
'水': '검정색',
|
||||
};
|
||||
return colors[element] || '녹색';
|
||||
};
|
||||
|
||||
const getLuckyNumber = (stem: string): number => {
|
||||
return (stem.charCodeAt(0) % 9) + 1;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50">
|
||||
{/* Navigation */}
|
||||
<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 */}
|
||||
<div className="max-w-6xl mx-auto px-4 py-12">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
||||
오늘의 운세
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600">
|
||||
{todayYear}년 {todayMonth}월 {todayDay}일 ({todayGanzi.day.stem}{todayGanzi.day.branch})
|
||||
</p>
|
||||
<p className="text-lg text-gray-500 mt-2">
|
||||
{sajuData.birthDate.year}년생 {gender === 'male' ? '남성' : '여성'}의 오늘 운세
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 운세 점수 카드들 */}
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
|
||||
{fortuneCategories.map((category) => (
|
||||
<div key={category.name} className="bg-white rounded-2xl shadow-lg p-6 hover:shadow-xl transition">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<span className="text-4xl">{category.icon}</span>
|
||||
<h3 className="text-xl font-bold text-gray-900">{category.name}</h3>
|
||||
</div>
|
||||
<span className={`text-2xl font-bold ${getScoreColor(category.score)}`}>
|
||||
{category.score}점
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full bg-gray-200 rounded-full h-3 mb-2">
|
||||
<div
|
||||
className={`bg-gradient-to-r from-${category.color}-400 to-${category.color}-600 h-3 rounded-full transition-all duration-500`}
|
||||
style={{ width: `${category.score}%` }}
|
||||
></div>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 text-right">{getScoreText(category.score)}</p>
|
||||
</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">
|
||||
<h2 className="text-3xl font-bold mb-6 text-center">💬 오늘의 한마디</h2>
|
||||
<p className="text-xl leading-relaxed text-center">
|
||||
{sajuData.day.element === '木' && '나무가 자라듯 꾸준히 노력하면 좋은 결과가 있을 것입니다. 새로운 시작에 좋은 날입니다.'}
|
||||
{sajuData.day.element === '火' && '활발한 기운이 가득한 날입니다. 적극적으로 행동하면 좋은 기회를 잡을 수 있습니다.'}
|
||||
{sajuData.day.element === '土' && '안정적인 하루가 될 것입니다. 차근차근 계획을 세우고 실행하면 좋습니다.'}
|
||||
{sajuData.day.element === '金' && '명확한 판단이 필요한 날입니다. 원칙을 지키며 행동하면 좋은 결과가 있을 것입니다.'}
|
||||
{sajuData.day.element === '水' && '유연한 사고가 도움이 되는 날입니다. 주변 사람들과의 소통을 중요하게 여기세요.'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 행운의 요소들 */}
|
||||
<div className="grid md:grid-cols-3 gap-8 mb-8">
|
||||
{/* 행운의 방향 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8 text-center">
|
||||
<div className="text-5xl mb-4">🧭</div>
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">행운의 방향</h3>
|
||||
<p className="text-3xl font-bold text-indigo-600">{getLuckyDirection(sajuData.day.stem)}</p>
|
||||
<p className="text-sm text-gray-600 mt-2">이 방향으로 외출하면 좋습니다</p>
|
||||
</div>
|
||||
|
||||
{/* 행운의 색깔 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8 text-center">
|
||||
<div className="text-5xl mb-4">🎨</div>
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">행운의 색깔</h3>
|
||||
<p className="text-3xl font-bold text-purple-600">{getLuckyColor(sajuData.day.element)}</p>
|
||||
<p className="text-sm text-gray-600 mt-2">이 색깔의 옷을 입으면 좋습니다</p>
|
||||
</div>
|
||||
|
||||
{/* 행운의 숫자 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8 text-center">
|
||||
<div className="text-5xl mb-4">🎲</div>
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-3">행운의 숫자</h3>
|
||||
<p className="text-3xl font-bold text-pink-600">{getLuckyNumber(sajuData.day.stem)}</p>
|
||||
<p className="text-sm text-gray-600 mt-2">오늘의 행운을 가져다 줄 숫자</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 주의사항 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8 mb-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-6 flex items-center">
|
||||
<span className="text-3xl mr-3">⚠️</span>
|
||||
오늘 주의할 점
|
||||
</h3>
|
||||
<ul className="space-y-3 text-gray-700">
|
||||
<li className="flex items-start">
|
||||
<span className="text-indigo-600 mr-2">•</span>
|
||||
<span>중요한 결정은 오전보다 오후에 하는 것이 좋습니다.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-indigo-600 mr-2">•</span>
|
||||
<span>감정적인 대화는 피하고 침착하게 대응하세요.</span>
|
||||
</li>
|
||||
<li className="flex items-start">
|
||||
<span className="text-indigo-600 mr-2">•</span>
|
||||
<span>건강 관리에 신경 쓰고 무리하지 마세요.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 다른 메뉴 */}
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<Link
|
||||
href={`/result?${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="/"
|
||||
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="/"
|
||||
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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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>
|
||||
);
|
||||
}
|
||||
257
app/page.tsx
257
app/page.tsx
@@ -1,65 +1,214 @@
|
||||
import Image from "next/image";
|
||||
import Link from 'next/link';
|
||||
import SajuForm from './components/SajuForm';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
|
||||
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/next.svg"
|
||||
alt="Next.js logo"
|
||||
width={100}
|
||||
height={20}
|
||||
priority
|
||||
/>
|
||||
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
|
||||
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
|
||||
To get started, edit the page.tsx file.
|
||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50">
|
||||
{/* Navigation */}
|
||||
<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">
|
||||
<div className="text-2xl font-bold bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">
|
||||
🔮 사주보기
|
||||
</div>
|
||||
<div className="hidden md:flex space-x-6">
|
||||
<Link href="#saju" className="text-gray-700 hover:text-indigo-600 transition font-medium">사주팔자</Link>
|
||||
<Link href="/compatibility" className="text-gray-700 hover:text-indigo-600 transition font-medium">궁합</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="pt-20 pb-32 px-4">
|
||||
<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>
|
||||
|
||||
<h1 className="text-5xl md:text-7xl font-bold text-gray-900 mb-6 leading-tight">
|
||||
나의 <span className="bg-gradient-to-r from-indigo-600 to-purple-600 bg-clip-text text-transparent">사주팔자</span>를<br />
|
||||
확인하세요
|
||||
</h1>
|
||||
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
|
||||
Looking for a starting point or more instructions? Head over to{" "}
|
||||
<a
|
||||
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Templates
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
className="font-medium text-zinc-950 dark:text-zinc-50"
|
||||
>
|
||||
Learning
|
||||
</a>{" "}
|
||||
center.
|
||||
|
||||
<p className="text-xl text-gray-600 mb-12 max-w-2xl mx-auto">
|
||||
생년월일시를 입력하면 무료로 사주팔자, 운세, 궁합을 확인할 수 있습니다.
|
||||
쉽고 빠르게 나의 운명을 알아보세요.
|
||||
</p>
|
||||
|
||||
{/* Main Input Card */}
|
||||
<div className="bg-white rounded-3xl shadow-2xl p-8 md:p-12 max-w-2xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-gray-900 mb-8">생년월일시 입력</h2>
|
||||
|
||||
<SajuForm />
|
||||
{/* 생년월일 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
생년월일
|
||||
</label>
|
||||
<div className="grid grid-cols-3 gap-3">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="년 (예: 1990)"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
min="1900"
|
||||
max="2100"
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="월 (1-12)"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="12"
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
placeholder="일 (1-31)"
|
||||
className="px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition"
|
||||
min="1"
|
||||
max="31"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 태어난 시간 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
태어난 시간 (선택)
|
||||
</label>
|
||||
<select className="w-full px-4 py-3 border-2 border-gray-200 rounded-xl focus:border-indigo-500 focus:outline-none transition">
|
||||
<option value="">모름 / 시간 선택 안함</option>
|
||||
<option value="23-01">자시 (子時) 23:00 - 01:00</option>
|
||||
<option value="01-03">축시 (丑時) 01:00 - 03:00</option>
|
||||
<option value="03-05">인시 (寅時) 03:00 - 05:00</option>
|
||||
<option value="05-07">묘시 (卯時) 05:00 - 07:00</option>
|
||||
<option value="07-09">진시 (辰時) 07:00 - 09:00</option>
|
||||
<option value="09-11">사시 (巳時) 09:00 - 11:00</option>
|
||||
<option value="11-13">오시 (午時) 11:00 - 13:00</option>
|
||||
<option value="13-15">미시 (未時) 13:00 - 15:00</option>
|
||||
<option value="15-17">신시 (申時) 15:00 - 17:00</option>
|
||||
<option value="17-19">유시 (酉時) 17:00 - 19:00</option>
|
||||
<option value="19-21">술시 (戌時) 19:00 - 21:00</option>
|
||||
<option value="21-23">해시 (亥時) 21:00 - 23:00</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* 양력/음력 선택 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
생일 구분
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
className="px-6 py-3 bg-indigo-600 text-white rounded-xl font-semibold hover:bg-indigo-700 transition"
|
||||
>
|
||||
양력
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="px-6 py-3 bg-white border-2 border-gray-200 text-gray-700 rounded-xl font-semibold hover:border-indigo-500 hover:text-indigo-600 transition"
|
||||
>
|
||||
음력
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 성별 선택 */}
|
||||
<div>
|
||||
<label className="block text-left text-sm font-semibold text-gray-700 mb-2">
|
||||
성별
|
||||
</label>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<button
|
||||
type="button"
|
||||
className="px-6 py-3 bg-indigo-600 text-white rounded-xl font-semibold hover:bg-indigo-700 transition"
|
||||
>
|
||||
남성
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="px-6 py-3 bg-white border-2 border-gray-200 text-gray-700 rounded-xl font-semibold hover:border-indigo-500 hover:text-indigo-600 transition"
|
||||
>
|
||||
여성
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 제출 버튼 */}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Image
|
||||
className="dark:invert"
|
||||
src="/vercel.svg"
|
||||
alt="Vercel logomark"
|
||||
width={16}
|
||||
height={16}
|
||||
/>
|
||||
Deploy Now
|
||||
</a>
|
||||
<a
|
||||
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
|
||||
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Documentation
|
||||
</section>
|
||||
|
||||
{/* Features Section */}
|
||||
<section className="py-20 px-4 bg-white">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">무엇을 확인할 수 있나요?</h2>
|
||||
<p className="text-xl text-gray-600">다양한 사주 정보를 한 번에 확인하세요</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{/* Feature 1 */}
|
||||
<div className="text-center p-6 rounded-2xl hover:bg-indigo-50 transition">
|
||||
<div className="text-5xl mb-4">📜</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">사주팔자</h3>
|
||||
<p className="text-gray-600">
|
||||
나의 천간, 지지, 십성, 십이운성을 확인하고 운명의 흐름을 파악하세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Feature 2 */}
|
||||
<div className="text-center p-6 rounded-2xl hover:bg-purple-50 transition">
|
||||
<div className="text-5xl mb-4">🌟</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">오늘의 운세</h3>
|
||||
<p className="text-gray-600">
|
||||
사주를 확인한 후 오늘 하루의 운세를 확인하고 행운의 방향을 찾아보세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Feature 3 */}
|
||||
<Link href="/compatibility" className="text-center p-6 rounded-2xl hover:bg-pink-50 transition block">
|
||||
<div className="text-5xl mb-4">💕</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-3">궁합</h3>
|
||||
<p className="text-gray-600">
|
||||
두 사람의 사주를 비교하여 궁합을 확인하세요.
|
||||
</p>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 px-4 bg-gradient-to-r from-indigo-600 to-purple-600">
|
||||
<div className="max-w-4xl mx-auto text-center text-white">
|
||||
<h2 className="text-4xl md:text-5xl font-bold mb-6">
|
||||
지금 바로 내 사주를 확인해보세요
|
||||
</h2>
|
||||
<p className="text-xl mb-8 opacity-90">
|
||||
무료로 제공되는 정확한 사주 정보로 나의 운명을 알아보세요
|
||||
</p>
|
||||
<a href="#" className="inline-block bg-white text-indigo-600 px-8 py-4 rounded-xl text-lg font-bold hover:bg-gray-100 transition shadow-lg">
|
||||
무료로 시작하기
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
</section>
|
||||
|
||||
{/* 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>
|
||||
);
|
||||
}
|
||||
|
||||
260
app/result/page.tsx
Normal file
260
app/result/page.tsx
Normal file
@@ -0,0 +1,260 @@
|
||||
import { calculateSaju } from '@/lib/saju-calculator';
|
||||
import Link from 'next/link';
|
||||
|
||||
interface PageProps {
|
||||
searchParams: Promise<{
|
||||
year: string;
|
||||
month: string;
|
||||
day: string;
|
||||
hour?: string;
|
||||
gender: 'male' | 'female';
|
||||
calendarType: 'solar' | 'lunar';
|
||||
}>;
|
||||
}
|
||||
|
||||
export default async function ResultPage({ searchParams }: PageProps) {
|
||||
const params = await searchParams;
|
||||
const { year, month, day, hour, gender } = params;
|
||||
|
||||
const yearNum = parseInt(year);
|
||||
const monthNum = parseInt(month);
|
||||
const dayNum = parseInt(day);
|
||||
const hourNum = hour ? parseInt(hour) : null;
|
||||
|
||||
const sajuData = calculateSaju(yearNum, monthNum, dayNum, hourNum, gender);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-indigo-50 via-purple-50 to-pink-50">
|
||||
{/* Navigation */}
|
||||
<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>
|
||||
<Link
|
||||
href="/"
|
||||
className="text-gray-700 hover:text-indigo-600 transition font-medium"
|
||||
>
|
||||
다시 보기
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Result Content */}
|
||||
<div className="max-w-6xl mx-auto px-4 py-12">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-12">
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4">
|
||||
내 사주팔자
|
||||
</h1>
|
||||
<p className="text-xl text-gray-600">
|
||||
{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">
|
||||
<h2 className="text-3xl font-bold text-gray-900 mb-8 text-center">사주팔자 (四柱八字)</h2>
|
||||
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full border-collapse">
|
||||
<thead>
|
||||
<tr className="bg-gradient-to-r from-indigo-600 to-purple-600 text-white">
|
||||
<th className="py-4 px-6 text-center font-bold text-lg">구분</th>
|
||||
{sajuData.hour && <th className="py-4 px-6 text-center font-bold text-lg">시주 (時柱)</th>}
|
||||
<th className="py-4 px-6 text-center font-bold text-lg">일주 (日柱)</th>
|
||||
<th className="py-4 px-6 text-center font-bold text-lg">월주 (月柱)</th>
|
||||
<th className="py-4 px-6 text-center font-bold text-lg">년주 (年柱)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{/* 천간 */}
|
||||
<tr className="border-b border-gray-200 hover:bg-indigo-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-3xl font-bold text-indigo-600">{sajuData.hour.stem}</div>
|
||||
<div className="text-sm text-gray-600 mt-1">{sajuData.hour.stemKr}</div>
|
||||
</td>
|
||||
)}
|
||||
<td className="py-4 px-6 text-center bg-blue-50">
|
||||
<div className="text-3xl font-bold text-blue-600">{sajuData.day.stem}</div>
|
||||
<div className="text-sm text-gray-600 mt-1">{sajuData.day.stemKr}</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>
|
||||
|
||||
{/* 지지 */}
|
||||
<tr className="border-b border-gray-200 hover:bg-purple-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-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>
|
||||
|
||||
{/* 십성 */}
|
||||
<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>
|
||||
|
||||
<div className="mt-6 p-4 bg-blue-50 rounded-xl">
|
||||
<p className="text-sm text-gray-700">
|
||||
<strong className="text-blue-600">일간 (日干):</strong> {sajuData.day.stem}({sajuData.day.stemKr}) - 나 자신을 나타내는 중심 기둥입니다.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 사주 해석 */}
|
||||
<div className="grid md:grid-cols-2 gap-8 mb-8">
|
||||
{/* 성격 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
||||
<span className="text-3xl mr-3">👤</span>
|
||||
성격 특징
|
||||
</h3>
|
||||
<div className="space-y-3 text-gray-700">
|
||||
<p className="leading-relaxed">
|
||||
일간이 <strong className="text-indigo-600">{sajuData.day.stem}({sajuData.day.stemKr})</strong>인 사람은
|
||||
{sajuData.day.element === '木' && ' 나무처럼 성장하고 발전하려는 의지가 강합니다. 창의적이고 진취적인 성향을 가지고 있습니다.'}
|
||||
{sajuData.day.element === '火' && ' 불처럼 열정적이고 활동적입니다. 리더십이 있고 사교성이 뛰어납니다.'}
|
||||
{sajuData.day.element === '土' && ' 흙처럼 안정적이고 신뢰감 있습니다. 포용력이 있고 책임감이 강합니다.'}
|
||||
{sajuData.day.element === '金' && ' 금속처럼 강인하고 원칙적입니다. 결단력 있고 의리를 중시합니다.'}
|
||||
{sajuData.day.element === '水' && ' 물처럼 유연하고 지혜롭습니다. 적응력이 뛰어나고 사려 깊습니다.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 운세 */}
|
||||
<div className="bg-white rounded-2xl shadow-lg p-8">
|
||||
<h3 className="text-2xl font-bold text-gray-900 mb-4 flex items-center">
|
||||
<span className="text-3xl mr-3">🌟</span>
|
||||
운세 흐름
|
||||
</h3>
|
||||
<div className="space-y-3 text-gray-700">
|
||||
<p className="leading-relaxed">
|
||||
현재 십이운성이 <strong className="text-purple-600">{sajuData.day.fortune}</strong>으로,
|
||||
{sajuData.day.fortune === '장생' && ' 새로운 시작과 성장의 시기입니다.'}
|
||||
{sajuData.day.fortune === '목욕' && ' 정화와 준비의 시기입니다.'}
|
||||
{sajuData.day.fortune === '관대' && ' 사회적으로 인정받는 시기입니다.'}
|
||||
{sajuData.day.fortune === '건록' && ' 안정되고 왕성한 활동의 시기입니다.'}
|
||||
{sajuData.day.fortune === '제왕' && ' 최고의 전성기를 맞이하는 시기입니다.'}
|
||||
{sajuData.day.fortune === '쇠' && ' 조금씩 힘이 약해지는 시기입니다.'}
|
||||
{sajuData.day.fortune === '병' && ' 어려움이 있을 수 있는 시기입니다.'}
|
||||
{sajuData.day.fortune === '사' && ' 끝과 새 시작을 준비하는 시기입니다.'}
|
||||
{sajuData.day.fortune === '묘' && ' 잠시 휴식이 필요한 시기입니다.'}
|
||||
{sajuData.day.fortune === '절' && ' 극복과 인내가 필요한 시기입니다.'}
|
||||
{sajuData.day.fortune === '태' && ' 새로운 기운이 싹트는 시기입니다.'}
|
||||
{sajuData.day.fortune === '양' && ' 성장을 준비하는 시기입니다.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 추가 기능 버튼 */}
|
||||
<div className="grid md:grid-cols-3 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>
|
||||
|
||||
<button className="bg-gradient-to-r from-indigo-600 to-purple-600 text-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 mb-2">PDF 저장</h3>
|
||||
<p className="text-sm opacity-90">내 사주 저장하기</p>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user