From 938ebacbf941d7da76a1bf0c28da754d31b79e34 Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Fri, 17 Apr 2026 09:01:41 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20PART=20III=20=EB=9E=9C=EB=94=A9=20?= =?UTF-8?q?=ED=94=BC=EB=B4=87=20=E2=80=94=20=EB=8B=A4=EC=B1=84=EB=84=90=20?= =?UTF-8?q?URL=20=EC=9E=85=EB=A0=A5=20+=20Strategic=20Planner=20=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=EC=85=94=EB=8B=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MultiChannelInput: URL 뭉치 붙여넣기 → classifyUrls로 7개 채널 자동 분류 (homepage·YouTube·Instagram·Facebook·네이버플레이스·블로그·강남언니) · "Analyze" pill 버튼 복원 + variant별 색 분기 (hero=dark brand, cta=#fff3eb→#e4cfff→#f5f9ff warm 3-stop) · placeholder 중앙 정렬 + "한 줄씩" 규칙 제거 (유연 파싱 노출) - Navbar: Free Report CTA 제거 → Login + 문의하기 (contact@o2o.kr) duo - LoginPage: 계약 고객용 스캐폴딩 페이지 신규 추가 - PricingPage: 계약 기반 영업 반영, FAQ에서 해지·환불 항목 제거 (세부 정책 미확정 → 후속 추가) - Landing 카피 Strategic Planner 포지셔닝 피봇: · Hero sub: "10분 진단 → 12개월 전략 설계" · Solution AGDP: Audit / Generation / Direction / Planning 재해석 · Modules: Intelligence + Planning Available, 나머지 Coming Soon 정직화 · TargetAudience: 전략 파트너 / 전략 자문 + Partner Program 신청 waitlist · Problems: 콘텐츠 소진 / 경쟁사 분석 부재 / 데이터 부족 3축 · UseCases: 진단·전략·KPI(Medical) · 수주·자문·포트폴리오(Agency) - discover-channels Edge Function: manualChannels 수용 — 사용자 붙여넣은 URL이 Firecrawl 스크래핑보다 우선, naverPlace/gangnamUnni 직접 주입 Co-Authored-By: Claude Opus 4.6 --- .../clinic_registry_working.csv | 6 +- src/components/CTA.tsx | 61 +-- src/components/Hero.tsx | 46 +- src/components/Modules.tsx | 77 +-- src/components/MultiChannelInput.tsx | 213 +++++++++ src/components/Navbar.tsx | 65 ++- src/components/Problems.tsx | 11 +- src/components/Solution.tsx | 37 +- src/components/TargetAudience.tsx | 22 +- src/components/UseCases.tsx | 19 +- src/components/pricing/FAQ.tsx | 134 ++++++ .../pricing/FeatureComparisonTable.tsx | 271 +++++++++++ src/lib/classifyUrls.ts | 259 ++++++++++ src/lib/contact.ts | 23 + src/lib/supabase.ts | 27 +- src/main.tsx | 4 + src/pages/AnalysisLoadingPage.tsx | 13 +- src/pages/LoginPage.tsx | 130 +++++ src/pages/PricingPage.tsx | 451 ++++++++++++++++++ supabase/functions/discover-channels/index.ts | 51 +- 20 files changed, 1774 insertions(+), 146 deletions(-) create mode 100644 src/components/MultiChannelInput.tsx create mode 100644 src/components/pricing/FAQ.tsx create mode 100644 src/components/pricing/FeatureComparisonTable.tsx create mode 100644 src/lib/classifyUrls.ts create mode 100644 src/lib/contact.ts create mode 100644 src/pages/LoginPage.tsx create mode 100644 src/pages/PricingPage.tsx diff --git a/data/clinic-registry/clinic_registry_working.csv b/data/clinic-registry/clinic_registry_working.csv index a7c689d..f9ef1f9 100644 --- a/data/clinic-registry/clinic_registry_working.csv +++ b/data/clinic-registry/clinic_registry_working.csv @@ -1,6 +1,6 @@ -hospital_name,brand_group,district,branches,website_kr,website_en,youtube_url,youtube_note,instagram_kr_url,instagram_followers,instagram_posts,instagram_kr_note,instagram_en_url,instagram_en_note,facebook_url,facebook_note,tiktok_url,tiktok_note,gangnam_unni_url,gangnam_unni_note,gangnam_unni_rating,gangnam_unni_reviews,gangnam_unni_badges,gangnam_unni_procedures,lead_doctor,naver_blog_url,naver_blog_note,naver_place_url,naver_place_reviews_note,google_maps_url,google_reviews_note +hospital_name,brand_group,district,branches,website_kr,website_en,youtube_url,youtube_note,instagram_kr_url,instagram_followers,instagram_posts,instagram_kr_note,instagram_en_url,instagram_en_note,facebook_url,facebook_note,tiktok_url,tiktok_note,gangnam_unni_url,gangnam_unni_note,gangnam_unni_rating,gangnam_unni_reviews,gangnam_unni_badges,gangnam_unni_procedures,lead_doctor,naver_blog_url,naver_blog_note,naver_place_url,naver_place_reviews_note,google_maps_url,google_reviews_note 바노바기성형외과,프리미엄/하이타깃 후보,강남,,https://www.banobagi.com,,https://www.youtube.com/c/banobagips,,https://www.instagram.com/banobagi_ps/,4124,196,,,,https://www.facebook.com/BanobagiPlasticSurgery,,,,https://www.gangnamunni.com/hospitals/23,,9.2,6843,수술실 CCTV;마취과 전문의 상주;여성 의사 진료;분야별 공동 진료;시술 후 관리;의료진 실명 공개;환자 숙박 정보 제공;전용 휴식 공간;입원 시설;응급 대응 체계;미용 의료 시술 진료;야간진료,눈성형;코성형;안면윤곽/양악;가슴성형;지방성형;필러;보톡스;리프팅;모발이식,반재상,https://blog.naver.com/banobagips,,https://m.place.naver.com/hospital/21033469,리뷰 773개,, -뷰성형외과,프리미엄/하이타깃 후보,강남,뷰성형외과 역삼센터(역삼),https://www.viewclinic.com,,https://www.youtube.com/@ViewclinicKR,,https://www.instagram.com/viewplastic/,14072,1417,,,,https://www.facebook.com/viewps1/,,,,https://www.gangnamunni.com/hospitals/189,,9.1,18840,수술실 CCTV;마취과 전문의 상주;분야별 공동 진료;의료진 실명 공개;야간진료;여성 의사 진료;응급 대응 체계;시술 후 관리;입원 시설;전용 휴식 공간,눈성형;코성형;안면윤곽/양악;가슴성형;지방성형;필러;보톡스;피부리프팅;기타,최순우,https://blog.naver.com/viewclinicps,,https://m.place.naver.com/hospital/11709005,리뷰 776개,, +뷰성형외과,프리미엄/하이타깃 후보,강남,뷰성형외과 역삼센터(역삼),https://www.viewclinic.com,,https://www.youtube.com/@ViewclinicKR,,https://www.instagram.com/viewplastic/,14072,1417,,,,https://www.facebook.com/viewps1/,,,,https://www.gangnamunni.com/hospitals/189,,9.5,19007,수술실 CCTV;마취과 전문의 상주;분야별 공동 진료;의료진 실명 공개;야간진료;여성 의사 진료;응급 대응 체계;시술 후 관리;입원 시설;전용 휴식 공간,눈성형;코성형;안면윤곽/양악;가슴성형;지방성형;필러;보톡스;피부리프팅;기타,최순우,https://blog.naver.com/viewclinicps,,https://m.place.naver.com/hospital/11709005,리뷰 776개,, 아이디병원,프리미엄/하이타깃 후보,강남,아이디병원 별관(역삼),https://www.idhospital.com,,https://www.youtube.com/user/IDhospital,,https://www.instagram.com/idhospital,10120,811,,,,https://www.facebook.com/idhospital0050,,,,https://www.gangnamunni.com/hospitals/257,,9.5,14933,수술실 CCTV;시술 후 관리;의료진 실명 공개;여성 의사 진료;분야별 공동 진료;입원 시설;전용 휴식 공간;환자 숙박 정보 제공;야간진료;마취과 전문의 상주;응급 대응 체계,양악수술;안면윤곽;눈/코성형;가슴성형;리프팅;피부클리닉;쁘띠성형;치과,박상훈,https://blog.naver.com/idfacial,,https://m.place.naver.com/hospital/11548359,,, 그랜드성형외과,프리미엄/하이타깃 후보,강남,,https://www.grandsurgery.com,,https://www.youtube.com/channel/UCU2o_aHqsNFuqwtdzVM3xbQ,,https://www.instagram.com/grand_korea/,4015,1148,,,,https://www.facebook.com/grandps.korea,,,,https://www.gangnamunni.com/hospitals/62,,9.8,1531,분야별 공동 진료;응급 대응 체계;시술 후 관리;전용 휴식 공간;입원 시설;마취과 전문의 상주;의료진 실명 공개;성형외과 전문의 진료;여성 의사 진료;미용 의료 시술 진료;환자 숙박 정보 제공;역에서 도보 5분;학회 활동 의사,피부;코성형;눈성형;보톡스;필러;리프팅;가슴성형;지방성형,이세환,https://blog.naver.com/grandprs,,https://m.place.naver.com/hospital/12322994,,, 원진성형외과,프리미엄/하이타깃 후보,강남,,https://www.k-wonjin.co.kr,,https://www.youtube.com/@wjwonjin,,https://www.instagram.com/wonjin_official/,23445,1844,,,,https://www.facebook.com/KwonjinPS,,https://www.tiktok.com/@wonjin_official,,https://www.gangnamunni.com/hospitals/2500,,9.3,11789,고객평가우수병원;분야별 공동 진료;응급 대응 체계;시술 후 관리;전용 휴식 공간;수술실 CCTV;여성 의사 진료;마취과 전문의 상주;야간진료;의료진 실명 공개,눈성형;코성형;안면윤곽/양악;가슴성형;지방성형;기타;모발이식;리프팅;보톡스;필러,강문석,https://blog.naver.com/popokpop,,https://m.place.naver.com/hospital/11887873,리뷰 9개,, @@ -71,4 +71,4 @@ 마노성형외과,프리미엄/하이타깃 후보,서초,,https://manops.co.kr,,https://www.youtube.com/@mano_ps,,https://www.instagram.com/manops_official,1006,239,,,,,,,,https://www.gangnamunni.com/hospitals/3429,,9.5,1034,응급 대응 체계;시술 후 관리;전용 휴식 공간;입원 시설;의료진 실명 공개;환자 숙박 정보 제공;분야별 공동 진료;야간진료,입술성형;귀성형;인중축소;안면윤곽;가슴성형;눈성형;코성형;리프팅;지방성형;기타,정태광,https://blog.naver.com/tkhr4747,,,,, 에스엠성형외과,프리미엄/하이타깃 후보,서초,,https://www.sm-ps.co.kr,,https://www.youtube.com/@smpsclinic,,https://www.instagram.com/smps_plastic_surgery/,1866,222,,,,https://www.facebook.com/thammySM3707,,,,https://www.gangnamunni.com/hospitals/413,,9.6,883,고객평가우수병원;시술 후 관리;의료진 실명 공개,눈성형;코성형;지방성형;가슴성형,이무영,https://blog.naver.com/smps1004,,https://m.place.naver.com/hospital/32876182,,, 서울미작성형외과,프리미엄/하이타깃 후보,서초,,https://mijakclinic.co.kr,,https://www.youtube.com/channel/UCld-NgVeydtDRVTt6xQRbmA,,https://www.instagram.com/mijak2444/,4990,2487,,,,https://www.facebook.com/mijaknose,,,,,,,,,,,https://blog.naver.com/mijak3444,,,,, -더원성형외과,프리미엄/하이타깃 후보,서초,,https://www.theoneclinic.co.kr,,,,https://www.instagram.com/theone_plastic_surgery/,13127,372,,,,https://www.facebook.com/pages/category/Hospital/더원성형외과-1539415639613021/,,,,https://www.gangnamunni.com/hospitals/5636,,10,1,고객평가우수병원,코성형;눈성형;안면윤곽/양악;보톡스;필러;리프팅;가슴성형;지방성형;제모;기타;치아;모발이식;한방,방난석,https://blog.naver.com/brs0714,,,,, +더원성형외과,프리미엄/하이타깃 후보,서초,,https://www.theoneclinic.co.kr,,,,https://www.instagram.com/theone_plastic_surgery/,13127,372,,,,https://www.facebook.com/pages/category/Hospital/더원성형외과-1539415639613021/,,,,https://www.gangnamunni.com/hospitals/5636,,10,1,고객평가우수병원,코성형;눈성형;안면윤곽/양악;보톡스;필러;리프팅;가슴성형;지방성형;제모;기타;치아;모발이식;한방,방난석,https://blog.naver.com/brs0714,,,,, \ No newline at end of file diff --git a/src/components/CTA.tsx b/src/components/CTA.tsx index 0f6f544..86e0bd1 100644 --- a/src/components/CTA.tsx +++ b/src/components/CTA.tsx @@ -1,14 +1,27 @@ -import { useState } from 'react'; -import { useNavigate } from 'react-router'; +/** + * CTA — 랜딩 페이지 하단 최종 전환 섹션. + * + * PART III 피봇: + * - Hero와 동일한 입력 로직(url state/navigate)을 중복 구현하던 문제 해소. + * 이제 `` 한 줄로 통일. + * - "무료 진단" 언급 삭제 — 계약 기반 모델 반영. + * - 헤드라인은 전략 소유권 메시지로 피봇 ("Own Your Marketing Strategy."). + * - 보조 CTA "가격 플랜 보기" 추가 (/pricing?from=cta). + */ +import { useNavigate, Link } from 'react-router'; import { motion } from 'motion/react'; -import { ArrowRight } from 'lucide-react'; +import MultiChannelInput, { type AnalyzePayload } from './MultiChannelInput'; export default function CTA() { - const [url, setUrl] = useState(''); const navigate = useNavigate(); - const handleAnalyze = () => { - if (url.trim()) navigate('/report/loading', { state: { url } }); + const handleAnalyze = (payload: AnalyzePayload) => { + navigate('/report/loading', { + state: { + url: payload.primaryUrl, + manualChannels: payload.manualChannels, + }, + }); }; return ( @@ -24,7 +37,7 @@ export default function CTA() { transition={{ duration: 0.6 }} className="text-4xl md:text-5xl font-serif font-bold mb-4 leading-tight text-transparent bg-clip-text bg-gradient-to-r from-[#fff3eb] via-[#e4cfff] to-[#f5f9ff]" > - Ready to Transform Your Marketing? + Own Your Marketing Strategy. - URL 하나로 시작하는 완벽한 마케팅 자동화. 지금 바로 무료 진단을 받아보세요. + URL 하나로 시작하는 AI 마케팅 전략 플래너. - setUrl(e.target.value)} - onKeyDown={(e) => e.key === 'Enter' && handleAnalyze()} - className="w-full px-8 py-4 text-base font-medium bg-gradient-to-r from-[#fff3eb] via-[#e4cfff] to-[#f5f9ff] border border-white/20 rounded-full focus:outline-none focus:ring-2 focus:ring-white/50 shadow-sm text-center text-primary-900 placeholder:text-primary-900/60" - /> - -

- 네이버 블로그, 플레이스, 소셜미디어 종합 분석 리포트 받아보기 -

+ + + {/* 보조 CTA — 가격 플랜 */} +
+ + 가격 플랜 보기 → + +
diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx index 0602ea9..c0490ad 100644 --- a/src/components/Hero.tsx +++ b/src/components/Hero.tsx @@ -1,15 +1,18 @@ -import { useState } from 'react'; import { useNavigate } from 'react-router'; import { motion } from 'motion/react'; -import { ArrowRight } from 'lucide-react'; import { PrismFilled } from './icons/FilledIcons'; +import MultiChannelInput, { type AnalyzePayload } from './MultiChannelInput'; export default function Hero() { - const [url, setUrl] = useState(''); const navigate = useNavigate(); - const handleAnalyze = () => { - if (url.trim()) navigate('/report/loading', { state: { url } }); + const handleAnalyze = (payload: AnalyzePayload) => { + navigate('/report/loading', { + state: { + url: payload.primaryUrl, + manualChannels: payload.manualChannels, + }, + }); }; return ( @@ -25,7 +28,7 @@ export default function Hero() { className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/60 backdrop-blur-sm border border-white/40 shadow-sm mb-8" > - Agentic AI Marketing Automation for Premium Medical Business & Marketing Agency + AI Marketing Strategist · Built for Premium Clinics Marketing Engine. + {/* 서브 카피 — PART II 피봇: Strategic Planner 포지셔닝 + ▸ 이전 "Marketing that learns... 쓸수록 더 정교해지는..." 은 풀스택 자동화 약속이 + Generation/Distribution Mock 상태와 맞지 않았음. + ▸ Phase 1-4 (Discover→Collect→Report→Plan) 실제 구현 범위에 정직하게 일치시킴. */} - Marketing that learns, improves, and accelerates — automatically.
- 쓸수록 더 정교해지는{' '}AI 마케팅 엔진.{' '}콘텐츠 기획,{' '}생성,{' '}영상 제작,{' '}채널 배포,{' '}데이터 분석까지{' '}하나로. + The Strategic Planner for Premium Medical Marketing.
+ 유튜브·인스타·네이버·강남언니를{' '} + 10분 만에 진단하고,{' '} + 병원의 12개월 마케팅 전략을{' '} + 설계합니다.
-
- setUrl(e.target.value)} - onKeyDown={(e) => e.key === 'Enter' && handleAnalyze()} - className="w-full px-8 py-5 text-base font-medium bg-white/80 backdrop-blur-sm border border-slate-200 rounded-2xl focus:outline-none focus:ring-2 focus:ring-accent/20 focus:border-accent/40 shadow-sm text-center text-primary-900 placeholder:text-slate-400 transition-all group-hover:border-slate-300" - /> -
- -

- 네이버 블로그, 플레이스, 소셜미디어 등 Online Presence 종합 분석 리포트를 제공합니다. -

+
diff --git a/src/components/Modules.tsx b/src/components/Modules.tsx index 0784cda..ba6cd2a 100644 --- a/src/components/Modules.tsx +++ b/src/components/Modules.tsx @@ -1,74 +1,76 @@ import React from 'react'; import { motion } from 'motion/react'; +// PART II 피봇: 1·5번은 Product 1.0 Available, 2·3·4는 Coming Soon. +// 카피는 Intelligence + Planning 중심으로 조정 (구조 5개 카드는 유지). const modules = [ { step: "1", title: "Marketing Intelligence", items: [ - "브랜딩, 마케팅 현황 분석", - "타겟 고객 분석", - "키워드 분석", - "경쟁 및 포지셔닝 분석", - "SEO 전략 & 채널별 콘텐츠 기획" + "브랜드·온라인 프레즌스 진단", + "유튜브·인스타·네이버·강남언니 실측", + "경쟁 병원 벤치마크 (최대 10곳)", + "키워드·해시태그 트렌드 분석", + "Vision AI 기반 의료진·슬로건 추출", ], - highlight: "AI 기반 시장 통찰력 도출", + highlight: "10분 진단 → 전략 기획의 출발점", color: "bg-[#021341]", textColor: "text-indigo-600" }, { step: "2", - title: "Content Creation", + title: "Strategic Planning", items: [ - "블로그 콘텐츠 생성", - "SEO 콘텐츠 생성", - "SNS 콘텐츠 생성", - "마케팅 카피 생성", - "Human-in-the loop 프로세스" + "12개월 마케팅 로드맵", + "4~8주 콘텐츠 캘린더 + 필러 5종", + "KPI 대시보드 (3·12개월 목표)", + "주간 KPI 달성도 → 전략 조정 제안", + "브랜드 가이드 (톤·컬러·로고) 자동 추출", ], - highlight: "고품질 맞춤형 콘텐츠 자동화", + highlight: "관찰을 실행 가능한 전략으로 전환", color: "bg-[#021341]", textColor: "text-indigo-600" }, { step: "3", - title: "Video Automation", + title: "Content Creation", items: [ - "블로그 → 영상 변환", - "숏폼 콘텐츠 생성", - "유튜브 콘텐츠 제작", - "SNS 영상 제작", - "멀티모달 AI 엔진: 영상 + 음악 + 카피" + "블로그·SEO·SNS 카피 자동 생성", + "브랜드 톤 일관성 보장", + "Human-in-the-loop 편집 워크플로우", + "콘텐츠 필러·시즌별 테마 매핑", + "Coming Soon · Q4 2026", ], - highlight: "원클릭 영상 제작 시스템", + highlight: "전략을 실행 가능한 콘텐츠로", color: "bg-[#021341]", textColor: "text-indigo-600" }, { step: "4", - title: "Distribution Engine", + title: "Video Automation", items: [ - "블로그 게시", - "SNS 자동 게시", - "유튜브 업로드", - "콘텐츠 일정 관리", - "SEO, AEO 자동 최적화" + "블로그 → 숏폼·유튜브 영상 변환", + "Creatomate 기반 자동 렌더링", + "음악·자막·썸네일 AI 생성", + "시즌별 템플릿 + 병원 CI 반영", + "Coming Soon · Q4 2026", ], - highlight: "전 채널 통합 배포 및 최적화", + highlight: "영상 제작 리소스 부담 해소", color: "bg-[#021341]", textColor: "text-indigo-600" }, { step: "5", - title: "Performance Intelligence", + title: "Distribution & Performance", items: [ - "SEO 성과 분석", - "콘텐츠 성과 분석", - "채널 성과 분석", - "AI 콘텐츠 개선 전략 추천", - "데이터 기반 효과 검증" + "멀티 채널 자동 게시 (블로그·SNS·유튜브)", + "SEO·AEO 자동 최적화", + "실시간 성과 트래킹 + 리포트", + "KPI 달성 → 다음 주기 전략 피드백", + "Coming Soon · Q4 2026", ], - highlight: "실시간 성과 추적 및 개선", + highlight: "전략-실행-성과의 자율 루프 완성", color: "bg-[#021341]", textColor: "text-indigo-600" } @@ -133,8 +135,11 @@ export default function Modules() {

Core Modules

-

- 성능 개선 반영 자율 순환 마케팅 시스템 + {/* PART II 피봇: "자율 순환 마케팅 시스템" → 실제 Phase 1-4 구현 범위로 정직하게 조정. + Product 1.0 Available 모듈 2개(Marketing Intelligence + Strategic Planning)와 + Coming Soon 모듈 3개(Content/Video/Distribution)로 완성도 신호를 분명히. */} +

+ 진단부터 전략 설계까지 Product 1.0 으로 출시된 모듈과 콘텐츠 실행을 위한 후속 로드맵입니다.

diff --git a/src/components/MultiChannelInput.tsx b/src/components/MultiChannelInput.tsx new file mode 100644 index 0000000..87d4b53 --- /dev/null +++ b/src/components/MultiChannelInput.tsx @@ -0,0 +1,213 @@ +/** + * MultiChannelInput — 랜딩 Hero / CTA 공용 멀티 URL 입력 컴포넌트. + * + * 설계 배경 (PART III 피봇): + * - 기존 Hero/CTA의 단일 URL input은 "홈페이지 URL → 자동 SNS 발견"을 전제로 했지만, + * 영업 현장에서는 병원이 본인들의 YouTube/Instagram/FB/네이버플레이스/블로그/강남언니 URL을 + * 이미 알고 있는 경우가 많아 이를 직접 받는 편이 정확도·속도 면에서 우월합니다. + * - Hero와 CTA가 동일한 입력 로직(url state + handleAnalyze + navigate)을 **중복 구현**하던 + * 문제를 이 컴포넌트 하나로 해소합니다. + * + * 동작: + * 1) Textarea에 URL을 공백/쉼표/줄바꿈으로 구분해 붙여넣기 + * 2) `classifyUrls()`로 실시간 7채널 분류 (`useMemo`) + * 3) 채널별 칩 프리뷰 — 검출 건수 표시, unknown URL은 경고 + * 4) "채널 분석 시작" 버튼 클릭 → onAnalyze(payload) 호출 (부모가 navigation 처리) + * + * DS 준수: + * - Filled Icons Only (lucide 무단 사용 금지 — 이모지·outlined 금지) + * - DS Primary pill: rounded-full + gradient `from-[#4F1DA1] to-[#021341]` + * - variant='hero': 글래스 배경 (랜딩 Hero) + * - variant='cta': 다크 배경 (CTA 섹션) + */ + +import { useMemo, useState, type ReactElement } from 'react'; +import { ArrowRight } from 'lucide-react'; +import { + GlobeFilled, + YoutubeFilled, + InstagramFilled, + FacebookFilled, + DatabaseFilled, + FileTextFilled, + MessageFilled, + WarningFilled, +} from './icons/FilledIcons'; +import { + classifyUrls, + hasAnalyzableChannels, + pickPrimaryUrl, + type ClassifiedUrls, +} from '../lib/classifyUrls'; + +/** discover-channels Edge Function에 전달되는 수동 채널 URL 묶음. */ +export interface ManualChannels { + youtube?: string[]; + instagram?: string[]; + facebook?: string[]; + naverPlace?: string[]; + naverBlog?: string[]; + gangnamUnni?: string[]; +} + +export interface AnalyzePayload { + /** discover-channels `url` 필드 (필수) — 홈페이지 우선, 없으면 첫 SNS URL. */ + primaryUrl: string; + /** 사용자가 제공한 채널별 URL — Edge Function이 Firecrawl discovery를 스킵. */ + manualChannels: ManualChannels; + /** 사용자 원본 입력 (디버깅·재실행용) */ + rawInput: string; +} + +interface MultiChannelInputProps { + variant?: 'hero' | 'cta'; + onAnalyze: (payload: AnalyzePayload) => void; +} + +/** 채널 칩 메타 — 렌더링 순서·아이콘·한글명. */ +const CHANNEL_META: Array<{ + key: keyof Omit; + label: string; + Icon: (props: { size?: number; className?: string }) => ReactElement; + color: string; // 활성화 시 텍스트/아이콘 색 +}> = [ + { key: 'homepage', label: '홈페이지', Icon: GlobeFilled, color: 'text-[#4F1DA1]' }, + { key: 'youtube', label: 'YouTube', Icon: YoutubeFilled, color: 'text-[#FF0000]' }, + { key: 'instagram', label: 'Instagram', Icon: InstagramFilled,color: 'text-[#E1306C]' }, + { key: 'facebook', label: 'Facebook', Icon: FacebookFilled, color: 'text-[#1877F2]' }, + { key: 'naverPlace', label: '네이버 플레이스', Icon: DatabaseFilled, color: 'text-[#03C75A]' }, + { key: 'naverBlog', label: '네이버 블로그', Icon: FileTextFilled, color: 'text-[#03C75A]' }, + { key: 'gangnamUnni', label: '강남언니', Icon: MessageFilled, color: 'text-[#FF5C89]' }, +]; + +export default function MultiChannelInput({ variant = 'hero', onAnalyze }: MultiChannelInputProps) { + const [text, setText] = useState(''); + + // 실시간 분류 — text가 바뀔 때만 재계산. + const classified = useMemo(() => classifyUrls(text), [text]); + + const canAnalyze = hasAnalyzableChannels(classified); + const primaryUrl = pickPrimaryUrl(classified); + + const handleSubmit = () => { + if (!canAnalyze || !primaryUrl) return; + const payload: AnalyzePayload = { + primaryUrl, + manualChannels: { + // homepage는 primaryUrl로 들어가므로 manualChannels에서는 제외 (Edge Function에서 `url`을 쓰므로) + youtube: classified.youtube.length ? classified.youtube : undefined, + instagram: classified.instagram.length ? classified.instagram : undefined, + facebook: classified.facebook.length ? classified.facebook : undefined, + naverPlace: classified.naverPlace.length ? classified.naverPlace : undefined, + naverBlog: classified.naverBlog.length ? classified.naverBlog : undefined, + gangnamUnni: classified.gangnamUnni.length ? classified.gangnamUnni : undefined, + }, + rawInput: text, + }; + onAnalyze(payload); + }; + + // variant별 스타일 토큰 + // ▸ `text-center` 추가 (원본 Hero 단일 URL input과 일관): Form 필드가 아닌 + // "검색창 같은 자유 입력" 시그널로 전환. placeholder 여러 줄도 중앙 정렬. + const isHero = variant === 'hero'; + const textareaClass = isHero + ? 'w-full px-6 py-4 text-sm md:text-base text-center bg-white/80 backdrop-blur-sm border border-slate-200 rounded-2xl focus:outline-none focus:ring-2 focus:ring-accent/20 focus:border-accent/40 shadow-sm text-primary-900 placeholder:text-slate-400 transition-all resize-none leading-relaxed' + : 'w-full px-6 py-4 text-sm md:text-base text-center bg-white/5 backdrop-blur-sm border border-white/15 rounded-2xl focus:outline-none focus:ring-2 focus:ring-accent/30 focus:border-accent/60 text-white placeholder:text-white/40 transition-all resize-none leading-relaxed'; + + const helperClass = isHero ? 'text-slate-500' : 'text-white/60'; + const chipInactiveBg = isHero ? 'bg-slate-50 border-slate-100' : 'bg-white/5 border-white/10'; + const chipInactiveText = isHero ? 'text-slate-400' : 'text-white/40'; + const chipActiveBg = isHero ? 'bg-white border-slate-200 shadow-sm' : 'bg-white/10 border-white/25'; + const chipActiveText = isHero ? 'text-primary-900' : 'text-white'; + + return ( +
+ {/* URL Textarea + Placeholder 카피 원칙: "한 줄씩" 같은 입력 규칙 제거. + classifyUrls.ts가 공백·쉼표·줄바꿈·임의 텍스트 섞임 모두 처리하므로 + 사용자에게 입력 형식 고민을 넘기지 않고, "뭉치 → 자동 분류" 를 제품 약속으로 선언. + 정렬: `text-center` — 원본 Hero의 단일 URL input과 일관, Form 필드 인상을 줄여 + "검색창 같은 자유 입력" 느낌으로 전환. */} +