- 음력 변환 기능 구현 - lunar-calendar 라이브러리 추가 - 음력-양력 변환 유틸리티 생성 - 모든 입력 폼에 양력/음력 선택 및 윤달 옵션 추가 - SajuForm, CompatibilityForm에 음력 지원 - 대운(大運) 계산 기능 구현 - 10년 단위 대운 계산 알고리즘 - 현재 대운 표시 및 해석 - 사주팔자 결과 페이지에 대운 섹션 추가 - 8개 대운 (80년치) 표시 - 소셜 공유 기능 구현 - ShareButtons 컴포넌트 생성 - 카카오톡, 페이스북, 트위터 공유 - 네이티브 공유 API 지원 - 링크 복사 기능 - 모든 결과 페이지에 공유 버튼 추가 - 메타데이터 개선 - 사이트 제목 및 설명 최적화 - 한국어(ko) 설정 - 카카오 SDK 추가 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
221 lines
7.5 KiB
TypeScript
221 lines
7.5 KiB
TypeScript
'use client';
|
|
|
|
import { useState } from 'react';
|
|
import { useRouter } from 'next/navigation';
|
|
import { lunarToSolar } from '@/lib/lunar-utils';
|
|
|
|
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 [isLeapMonth, setIsLeapMonth] = useState(false);
|
|
|
|
const handleSubmit = (e: React.FormEvent) => {
|
|
e.preventDefault();
|
|
|
|
if (!year || !month || !day) {
|
|
alert('생년월일을 모두 입력해주세요.');
|
|
return;
|
|
}
|
|
|
|
let finalYear = year;
|
|
let finalMonth = month;
|
|
let finalDay = day;
|
|
|
|
// 음력인 경우 양력으로 변환
|
|
if (calendarType === 'lunar') {
|
|
const solar = lunarToSolar(
|
|
parseInt(year),
|
|
parseInt(month),
|
|
parseInt(day),
|
|
isLeapMonth
|
|
);
|
|
finalYear = solar.year.toString();
|
|
finalMonth = solar.month.toString();
|
|
finalDay = solar.day.toString();
|
|
}
|
|
|
|
// URL 파라미터로 전달
|
|
const params = new URLSearchParams({
|
|
year: finalYear,
|
|
month: finalMonth,
|
|
day: finalDay,
|
|
gender,
|
|
calendarType,
|
|
originalYear: year,
|
|
originalMonth: month,
|
|
originalDay: day,
|
|
});
|
|
|
|
if (hour) {
|
|
params.append('hour', hour);
|
|
}
|
|
|
|
if (calendarType === 'lunar') {
|
|
params.append('isLeapMonth', isLeapMonth.toString());
|
|
}
|
|
|
|
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>
|
|
{calendarType === 'lunar' && (
|
|
<div className="mt-3">
|
|
<label className="flex items-center justify-center gap-2 text-sm text-gray-600 cursor-pointer">
|
|
<input
|
|
type="checkbox"
|
|
checked={isLeapMonth}
|
|
onChange={(e) => setIsLeapMonth(e.target.checked)}
|
|
className="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500"
|
|
/>
|
|
<span>윤달</span>
|
|
</label>
|
|
</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>
|
|
);
|
|
}
|