diff --git a/src/components/report/ClinicSnapshot.tsx b/src/components/report/ClinicSnapshot.tsx index 86e312a..0c0b48e 100644 --- a/src/components/report/ClinicSnapshot.tsx +++ b/src/components/report/ClinicSnapshot.tsx @@ -1,5 +1,5 @@ import { motion } from 'motion/react'; -import { Calendar, Users, MapPin, Phone, Award, Star, Globe } from 'lucide-react'; +import { Calendar, Users, MapPin, Phone, Award, Star, Globe, ExternalLink } from 'lucide-react'; import { SectionWrapper } from './ui/SectionWrapper'; import type { ClinicSnapshot as ClinicSnapshotType } from '../../types/report'; @@ -11,16 +11,22 @@ function formatNumber(n: number): string { return n.toLocaleString(); } -const infoFields = (data: ClinicSnapshotType) => [ +interface InfoField { + label: string; + value: string; + icon: typeof Calendar; + href?: string; +} + +const infoFields = (data: ClinicSnapshotType): InfoField[] => [ data.established ? { label: '개원', value: `${data.established} (${data.yearsInBusiness}년)`, icon: Calendar } : null, data.staffCount > 0 ? { label: '의료진', value: `${data.staffCount}명`, icon: Users } : null, data.overallRating > 0 ? { label: '강남언니 평점', value: data.overallRating > 5 ? `${data.overallRating} / 10` : `${data.overallRating} / 5.0`, icon: Star } : null, data.totalReviews > 0 ? { label: '리뷰 수', value: formatNumber(data.totalReviews), icon: Star } : null, - data.priceRange.min !== '-' ? { label: '시술 가격대', value: `${data.priceRange.min} ~ ${data.priceRange.max}`, icon: Globe } : null, data.location ? { label: '위치', value: data.nearestStation ? `${data.location} (${data.nearestStation})` : data.location, icon: MapPin } : null, - data.phone ? { label: '전화', value: data.phone, icon: Phone } : null, - data.domain ? { label: '도메인', value: data.domain, icon: Globe } : null, -].filter((f): f is NonNullable => f !== null); + data.phone ? { label: '전화', value: data.phone, icon: Phone, href: `tel:${data.phone.replace(/[^+0-9]/g, '')}` } : null, + data.domain ? { label: '도메인', value: data.domain, icon: Globe, href: `https://${data.domain.replace(/^https?:\/\//, '')}` } : null, +].filter((f): f is NonNullable => f !== null); export default function ClinicSnapshot({ data }: ClinicSnapshotProps) { const fields = infoFields(data); @@ -45,7 +51,19 @@ export default function ClinicSnapshot({ data }: ClinicSnapshotProps) {

{field.label}

-

{field.value}

+ {field.href ? ( + + {field.value} + {!field.href.startsWith('tel:') && } + + ) : ( +

{field.value}

+ )}
diff --git a/src/components/report/InstagramAudit.tsx b/src/components/report/InstagramAudit.tsx index 3588abd..fa56b13 100644 --- a/src/components/report/InstagramAudit.tsx +++ b/src/components/report/InstagramAudit.tsx @@ -1,5 +1,5 @@ import { motion } from 'motion/react'; -import { Instagram, AlertCircle, FileText, Users, Eye } from 'lucide-react'; +import { Instagram, AlertCircle, FileText, Users, Eye, ExternalLink } from 'lucide-react'; import { SectionWrapper } from './ui/SectionWrapper'; import { EmptyState } from './ui/EmptyState'; import { MetricCard } from './ui/MetricCard'; @@ -37,7 +37,19 @@ function AccountCard({ account, index }: { key?: string | number; account: Insta -

{account.handle}

+

+ {account.handle ? ( + + {account.handle} + + + ) : account.handle} +

{account.category}

{/* Compact metrics */} diff --git a/src/components/report/YouTubeAudit.tsx b/src/components/report/YouTubeAudit.tsx index 28ff22e..072bb98 100644 --- a/src/components/report/YouTubeAudit.tsx +++ b/src/components/report/YouTubeAudit.tsx @@ -68,7 +68,19 @@ export default function YouTubeAudit({ data }: YouTubeAuditProps) {

{data.channelName}

-

{data.handle}

+ {data.handle ? ( + + {data.handle} + + + ) : ( +

{data.handle}

+ )}

{data.channelDescription}

diff --git a/src/lib/transformReport.ts b/src/lib/transformReport.ts index 6e090e5..0695118 100644 --- a/src/lib/transformReport.ts +++ b/src/lib/transformReport.ts @@ -994,7 +994,7 @@ export function mergeEnrichment( name: '구글 지도', status: 'active' as const, details: `평점: ${gm.rating ?? '-'} / 리뷰: ${gm.reviewCount ?? '-'}`, - url: '', + url: gm.website || (gm.name ? `https://www.google.com/maps/search/${encodeURIComponent(String(gm.name))}` : ''), }; if (gmChannelIdx >= 0) { merged.otherChannels[gmChannelIdx] = gmChannel; @@ -1089,7 +1089,7 @@ export function mergeEnrichment( name: '네이버 블로그', status: 'active' as const, details: `검색 결과: ${nb.totalResults?.toLocaleString() ?? '-'}건 / 최근 포스트 ${nb.posts?.length ?? 0}개`, - url: '', + url: nb.posts?.[0]?.link || (nb.searchQuery ? `https://search.naver.com/search.naver?query=${encodeURIComponent(String(nb.searchQuery))}` : ''), }; if (nbChannelIdx >= 0) { merged.otherChannels[nbChannelIdx] = nbChannel;