절기 날짜 정밀화: - solarlunar 라이브러리 추가 - 천문학적 계산 기반 정확한 절기 날짜 계산 - 각 절기별 정확한 날짜 범위 검색 - 폴백 메커니즘으로 안정성 확보 AI 상세 해석 시스템: - ai-interpretation.ts 라이브러리 생성 - 일간 기반 성격 분석 (10개 천간별 상세 해석) - 오행 균형 분석 및 점수 계산 - 십성 기반 다차원 분석 - 직업 운세 (오행 + 십성 조합) - 대인 관계 (십성 기반) - 재물 운세 (정재/편재 분석) - 건강 운세 (오행 균형) - 맞춤형 조언 생성 결과 페이지 AI 해석 섹션: - 오행 균형 시각화 (막대 그래프) - 장점/주의할 점 구분 표시 - 4가지 운세 카드 (직업/대인/재물/건강) - AI 조언 그리드 레이아웃 - 전문가 상담 권장 안내 공유 기능 개선: - localhost 감지 로직 추가 - localhost인 경우: - 카카오톡: 텍스트 형식으로 사주 정보 공유 - 링크 복사: 사주 정보 텍스트 복사 - 사용자에게 개발 환경임을 안내 - 배포 환경: 기존대로 URL 공유 - 더 나은 사용자 경험 제공 기술 개선: - solarlunar 라이브러리 (정밀 절기 계산) - 타입 안전성 강화 - 모듈화된 해석 로직 - 성능 최적화 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
192 lines
6.7 KiB
TypeScript
192 lines
6.7 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
|
||
interface ShareButtonsProps {
|
||
title: string;
|
||
description: string;
|
||
url?: string;
|
||
}
|
||
|
||
export default function ShareButtons({ title, description, url }: ShareButtonsProps) {
|
||
const [showShareMenu, setShowShareMenu] = useState(false);
|
||
const shareUrl = url || (typeof window !== 'undefined' ? window.location.href : '');
|
||
|
||
// localhost 체크
|
||
const isLocalhost = shareUrl.includes('localhost') || shareUrl.includes('127.0.0.1');
|
||
|
||
const handleKakaoShare = () => {
|
||
if (isLocalhost) {
|
||
// localhost인 경우 텍스트로 공유
|
||
const shareText = `${title}\n\n${description}\n\n🔮 사주보기 - 쟁승메이드\n(배포 후 링크가 제공됩니다)`;
|
||
|
||
if (typeof window !== 'undefined' && (window as any).Kakao) {
|
||
(window as any).Kakao.Share.sendDefault({
|
||
objectType: 'text',
|
||
text: shareText,
|
||
link: {
|
||
mobileWebUrl: 'https://jaengseung-made.com',
|
||
webUrl: 'https://jaengseung-made.com',
|
||
},
|
||
});
|
||
} else {
|
||
alert('카카오톡 공유 기능을 사용할 수 없습니다.');
|
||
}
|
||
} else {
|
||
// 배포된 URL인 경우 정상 공유
|
||
if (typeof window !== 'undefined' && (window as any).Kakao) {
|
||
(window as any).Kakao.Share.sendDefault({
|
||
objectType: 'feed',
|
||
content: {
|
||
title: title,
|
||
description: description,
|
||
imageUrl: 'https://developers.kakao.com/assets/img/about/logos/kakaolink/kakaolink_btn_medium.png',
|
||
link: {
|
||
mobileWebUrl: shareUrl,
|
||
webUrl: shareUrl,
|
||
},
|
||
},
|
||
buttons: [
|
||
{
|
||
title: '자세히 보기',
|
||
link: {
|
||
mobileWebUrl: shareUrl,
|
||
webUrl: shareUrl,
|
||
},
|
||
},
|
||
],
|
||
});
|
||
} else {
|
||
alert('카카오톡 공유 기능을 사용할 수 없습니다.');
|
||
}
|
||
}
|
||
};
|
||
|
||
const handleFacebookShare = () => {
|
||
const facebookUrl = `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(shareUrl)}`;
|
||
window.open(facebookUrl, '_blank', 'width=600,height=400');
|
||
};
|
||
|
||
const handleTwitterShare = () => {
|
||
const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(title)}&url=${encodeURIComponent(shareUrl)}`;
|
||
window.open(twitterUrl, '_blank', 'width=600,height=400');
|
||
};
|
||
|
||
const handleCopyLink = async () => {
|
||
try {
|
||
if (isLocalhost) {
|
||
// localhost인 경우 텍스트 정보 복사
|
||
const shareText = `${title}\n\n${description}\n\n🔮 사주보기 - 쟁승메이드\n(배포 후 링크가 제공됩니다)`;
|
||
await navigator.clipboard.writeText(shareText);
|
||
alert('사주 정보가 복사되었습니다!\n(개발 환경이므로 URL 대신 텍스트 정보가 복사됩니다)');
|
||
} else {
|
||
await navigator.clipboard.writeText(shareUrl);
|
||
alert('링크가 복사되었습니다!');
|
||
}
|
||
setShowShareMenu(false);
|
||
} catch (err) {
|
||
alert('복사에 실패했습니다.');
|
||
}
|
||
};
|
||
|
||
const handleNativeShare = async () => {
|
||
if (navigator.share) {
|
||
try {
|
||
await navigator.share({
|
||
title: title,
|
||
text: description,
|
||
url: shareUrl,
|
||
});
|
||
setShowShareMenu(false);
|
||
} catch (err) {
|
||
console.log('Share cancelled or failed', err);
|
||
}
|
||
} else {
|
||
setShowShareMenu(true);
|
||
}
|
||
};
|
||
|
||
return (
|
||
<div className="relative">
|
||
<button
|
||
onClick={handleNativeShare}
|
||
className="bg-white rounded-xl p-6 shadow-lg hover:shadow-xl transition text-center group w-full"
|
||
>
|
||
<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>
|
||
</button>
|
||
|
||
{/* 공유 메뉴 (모바일에서 네이티브 공유가 안 될 때) */}
|
||
{showShareMenu && (
|
||
<>
|
||
{/* 배경 오버레이 */}
|
||
<div
|
||
className="fixed inset-0 bg-black bg-opacity-50 z-40"
|
||
onClick={() => setShowShareMenu(false)}
|
||
></div>
|
||
|
||
{/* 공유 메뉴 */}
|
||
<div className="fixed bottom-0 left-0 right-0 bg-white rounded-t-3xl shadow-2xl z-50 p-6 animate-slide-up">
|
||
<div className="flex justify-between items-center mb-6">
|
||
<h3 className="text-xl font-bold text-gray-900">공유하기</h3>
|
||
<button
|
||
onClick={() => setShowShareMenu(false)}
|
||
className="text-gray-500 hover:text-gray-700 text-2xl"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-4 gap-4 mb-4">
|
||
{/* 카카오톡 */}
|
||
<button
|
||
onClick={handleKakaoShare}
|
||
className="flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-gray-50 transition"
|
||
>
|
||
<div className="w-12 h-12 bg-yellow-400 rounded-full flex items-center justify-center text-2xl">
|
||
💬
|
||
</div>
|
||
<span className="text-xs text-gray-700">카카오톡</span>
|
||
</button>
|
||
|
||
{/* 페이스북 */}
|
||
<button
|
||
onClick={handleFacebookShare}
|
||
className="flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-gray-50 transition"
|
||
>
|
||
<div className="w-12 h-12 bg-blue-600 rounded-full flex items-center justify-center text-2xl text-white">
|
||
f
|
||
</div>
|
||
<span className="text-xs text-gray-700">페이스북</span>
|
||
</button>
|
||
|
||
{/* 트위터 */}
|
||
<button
|
||
onClick={handleTwitterShare}
|
||
className="flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-gray-50 transition"
|
||
>
|
||
<div className="w-12 h-12 bg-blue-400 rounded-full flex items-center justify-center text-2xl text-white">
|
||
𝕏
|
||
</div>
|
||
<span className="text-xs text-gray-700">트위터</span>
|
||
</button>
|
||
|
||
{/* 링크 복사 */}
|
||
<button
|
||
onClick={handleCopyLink}
|
||
className="flex flex-col items-center gap-2 p-3 rounded-xl hover:bg-gray-50 transition"
|
||
>
|
||
<div className="w-12 h-12 bg-gray-600 rounded-full flex items-center justify-center text-2xl text-white">
|
||
🔗
|
||
</div>
|
||
<span className="text-xs text-gray-700">링크 복사</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|