o2o-castad-frontend/src/pages/Analysis/AnalysisResultSection.tsx

178 lines
7.7 KiB
TypeScript
Executable File

import React from 'react';
import { useTranslation } from 'react-i18next';
import { CrawlingResponse, TargetPersona } from '../../types/api';
import { GeometricChart } from './GeometricChart';
interface AnalysisResultSectionProps {
onBack: () => void;
onGenerate?: () => void;
data: CrawlingResponse;
}
const AnalysisResultSection: React.FC<AnalysisResultSectionProps> = ({ onBack, onGenerate, data }) => {
const { t } = useTranslation();
const { processed_info, marketing_analysis } = data;
const brandIdentity = marketing_analysis?.brand_identity;
const marketPositioning = marketing_analysis?.market_positioning;
const targetPersonas = marketing_analysis?.target_persona || [];
const sellingPoints = marketing_analysis?.selling_points || [];
const targetKeywords = marketing_analysis?.target_keywords || [];
// 셀링 포인트를 score 내림차순으로 정렬
const sortedSellingPoints = [...sellingPoints].sort((a, b) => b.score - a.score);
return (
<div className="bi2-page">
{/* Header */}
<div className="bi2-header">
<button onClick={onBack} className="bi2-back-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
<path d="M15 18l-6-6 6-6" />
</svg>
<span>{t('analysis.back')}</span>
</button>
</div>
{/* Page Title */}
<div className="bi2-page-title-section">
<div className="bi2-title-icon">
<img src="/assets/images/star-icon.svg" alt="" className="bi2-star-icon" />
</div>
<div className="bi2-title-text">
<h1 className="bi2-main-title">{t('analysis.pageTitle')}</h1>
<p className="bi2-subtitle">
<span style={{ color: 'var(--Color-mint-500, #94FBE0)' }}>{t('analysis.pageDescHighlight')}</span>{t('analysis.pageDescBefore')}{processed_info?.customer_name || t('analysis.defaultBrandName')}{t('analysis.pageDescAfter')}
</p>
</div>
</div>
{/* Main Content Container */}
<div className="bi2-main-container">
{/* 매장명 & 주소 */}
<div className="bi2-store-header">
<h2 className="bi2-store-name">{processed_info?.customer_name || t('analysis.brandNameFallback')}</h2>
<p className="bi2-store-address">{processed_info?.detail_region_info || t('analysis.addressFallback')}</p>
</div>
{/* 브랜드 정체성 */}
<div className="bi2-section">
<h3 className="bi2-section-title">{t('analysis.brandIdentity')}</h3>
<div className="bi2-identity-card">
<div className="bi2-identity-top">
<div className="bi2-identity-core">
<span className="bi2-label-sm">{t('analysis.coreValue')}</span>
<p className="bi2-core-value">{marketPositioning?.core_value || t('analysis.noInfo')}</p>
</div>
<p className="bi2-category-text">{t('analysis.categoryDefinition')} : {marketPositioning?.category_definition || t('analysis.noInfo')}</p>
</div>
<div className="bi2-identity-divider"></div>
<div className="bi2-identity-bottom">
<div className="bi2-identity-col">
<span className="bi2-label-sm">{t('analysis.locationAnalysis')}</span>
<p className="bi2-body-text">{brandIdentity?.location_feature_analysis || t('analysis.noInfo')}</p>
</div>
<div className="bi2-identity-col">
<span className="bi2-label-sm">{t('analysis.conceptScalability')}</span>
<p className="bi2-body-text">{brandIdentity?.concept_scalability || t('analysis.noInfo')}</p>
</div>
</div>
</div>
</div>
{/* 주요 셀링 포인트 */}
<div className="bi2-section">
<h3 className="bi2-section-title">{t('analysis.sellingPoints')}</h3>
<div className="bi2-selling-card">
{/* 레이더 차트 */}
<div className="bi2-selling-chart">
{sellingPoints.length > 0 && (
<GeometricChart data={sellingPoints} />
)}
</div>
{/* 셀링 포인트 리스트 */}
<div className="bi2-selling-list">
{sortedSellingPoints.map((sp, idx) => {
const rank = idx + 1;
const isTopThree = rank <= 3;
return (
<div key={idx} className="bi2-selling-item">
<div className={`bi2-rank-badge ${isTopThree ? 'top' : ''}`}>
{rank}
</div>
<div className="bi2-selling-item-text">
<span className="bi2-selling-name">{sp.korean_category}</span>
<span className="bi2-selling-desc">{sp.description}</span>
</div>
</div>
);
})}
</div>
</div>
</div>
{/* 주요 고객 유형 */}
<div className="bi2-section">
<h3 className="bi2-section-title">{t('analysis.targetPersona')}</h3>
<div className="bi2-persona-grid">
{targetPersonas.map((persona: TargetPersona, idx: number) => (
<div key={idx} className="bi2-persona-card">
<div className="bi2-persona-header">
<div className="bi2-persona-info">
<span className="bi2-persona-name">{persona.persona}</span>
<span className="bi2-persona-age">{persona.age.min_age}~{persona.age.max_age}{t('analysis.ageSuffix')}</span>
</div>
<p className="bi2-persona-desc">
{persona.decision_trigger}
</p>
</div>
<div className="bi2-persona-divider"></div>
<div className="bi2-persona-detail grow">
<span className="bi2-label-xs">{t('analysis.favorKeywords', { defaultValue: '선호 키워드' })}</span>
<p className="bi2-persona-detail-text">
{persona.favor_target.join('\n')}
</p>
</div>
<div className="bi2-persona-divider"></div>
<div className="bi2-persona-detail">
<span className="bi2-label-xs">{t('analysis.decisionTrigger', { defaultValue: '예약 결정 포인트' })}</span>
<p className="bi2-persona-detail-text">{persona.decision_trigger}</p>
</div>
</div>
))}
</div>
</div>
{/* 추천 타겟 키워드 */}
<div className="bi2-section">
<div className="bi2-keyword-header">
<h3 className="bi2-section-title">{t('analysis.recommendedKeywords')}</h3>
<p className="bi2-keyword-subtitle">{t('analysis.keywordHint', { defaultValue: '이런 키워드로 찾을 가능성이 높아요' })}</p>
</div>
<div className="bi2-keyword-tags">
{targetKeywords.map((keyword: string, idx: number) => (
<span key={idx} className="bi2-keyword-pill">#{keyword}</span>
))}
</div>
</div>
</div>
{/* 콘텐츠 생성 버튼 */}
<div className="bi2-bottom-button-container">
<button
onClick={onGenerate}
className="bi2-generate-btn"
>
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden className="w-5 h-5">
<path d="M12 2l2.4 6.8L22 12l-7.6 3.2L12 22l-2.4-6.8L2 12l7.6-3.2L12 2z" />
</svg>
{t('analysis.generateContent')}
</button>
</div>
</div>
);
};
export default AnalysisResultSection;