297 lines
10 KiB
TypeScript
297 lines
10 KiB
TypeScript
import React from 'react';
|
|
import { BusinessDNA } from '../../types';
|
|
import { Badge } from './ui/badge';
|
|
import {
|
|
Palette,
|
|
Users,
|
|
Sparkles,
|
|
Eye,
|
|
Target,
|
|
Hash,
|
|
Star,
|
|
TrendingUp,
|
|
ExternalLink,
|
|
Camera,
|
|
Home,
|
|
Heart
|
|
} from 'lucide-react';
|
|
import { cn } from '../lib/utils';
|
|
|
|
interface DNACardProps {
|
|
dna: BusinessDNA;
|
|
className?: string;
|
|
compact?: boolean;
|
|
}
|
|
|
|
const DNACard: React.FC<DNACardProps> = ({ dna, className, compact = false }) => {
|
|
if (compact) {
|
|
return (
|
|
<div className={cn("bg-card rounded-xl border border-border p-4", className)}>
|
|
<div className="flex items-center gap-3 mb-3">
|
|
<div
|
|
className="w-10 h-10 rounded-lg flex items-center justify-center"
|
|
style={{ backgroundColor: dna.brandColors.primary + '20' }}
|
|
>
|
|
<Sparkles className="w-5 h-5" style={{ color: dna.brandColors.primary }} />
|
|
</div>
|
|
<div>
|
|
<h3 className="font-semibold">{dna.name}</h3>
|
|
{dna.tagline && (
|
|
<p className="text-xs text-muted-foreground">{dna.tagline}</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Color Palette (mini) */}
|
|
<div className="flex gap-1 mb-3">
|
|
{dna.brandColors.palette?.slice(0, 5).map((color, idx) => (
|
|
<div
|
|
key={idx}
|
|
className="w-6 h-6 rounded-md border border-border/50"
|
|
style={{ backgroundColor: color }}
|
|
title={color}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
{/* Keywords (mini) */}
|
|
<div className="flex flex-wrap gap-1">
|
|
{dna.keywords.primary.slice(0, 4).map((keyword, idx) => (
|
|
<Badge key={idx} variant="secondary" className="text-xs">
|
|
{keyword}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className={cn("bg-card rounded-2xl border border-border overflow-hidden", className)}>
|
|
{/* Header with gradient */}
|
|
<div
|
|
className="p-6 text-white"
|
|
style={{
|
|
background: `linear-gradient(135deg, ${dna.brandColors.primary}, ${dna.brandColors.secondary || dna.brandColors.primary})`
|
|
}}
|
|
>
|
|
<div className="flex items-center justify-between mb-2">
|
|
<div className="flex items-center gap-2">
|
|
<Sparkles className="w-5 h-5" />
|
|
<span className="text-sm font-medium opacity-90">Business DNA</span>
|
|
</div>
|
|
{dna.confidence && (
|
|
<Badge variant="secondary" className="bg-white/20 text-white border-0">
|
|
신뢰도 {Math.round(dna.confidence * 100)}%
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
<h2 className="text-2xl font-bold">{dna.name}</h2>
|
|
{dna.tagline && (
|
|
<p className="text-white/80 mt-1">{dna.tagline}</p>
|
|
)}
|
|
</div>
|
|
|
|
<div className="p-6 space-y-6">
|
|
{/* Tone & Manner */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Heart className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">톤 & 매너</h3>
|
|
</div>
|
|
<div className="flex flex-wrap gap-2 mb-2">
|
|
<Badge>{dna.toneAndManner.primary}</Badge>
|
|
{dna.toneAndManner.secondary && (
|
|
<Badge variant="outline">{dna.toneAndManner.secondary}</Badge>
|
|
)}
|
|
</div>
|
|
<p className="text-sm text-muted-foreground">{dna.toneAndManner.description}</p>
|
|
</div>
|
|
|
|
{/* Target Customers */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Users className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">타겟 고객</h3>
|
|
</div>
|
|
<div className="flex flex-wrap gap-2 mb-2">
|
|
<Badge variant="default">{dna.targetCustomers.primary}</Badge>
|
|
{dna.targetCustomers.secondary?.map((target, idx) => (
|
|
<Badge key={idx} variant="outline">{target}</Badge>
|
|
))}
|
|
</div>
|
|
{dna.targetCustomers.ageRange && (
|
|
<p className="text-xs text-muted-foreground mb-1">
|
|
예상 연령대: {dna.targetCustomers.ageRange}
|
|
</p>
|
|
)}
|
|
{dna.targetCustomers.characteristics && (
|
|
<div className="flex flex-wrap gap-1 mt-2">
|
|
{dna.targetCustomers.characteristics.map((char, idx) => (
|
|
<span key={idx} className="text-xs bg-muted px-2 py-0.5 rounded">
|
|
{char}
|
|
</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Brand Colors */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Palette className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">브랜드 컬러</h3>
|
|
</div>
|
|
<div className="flex gap-2 mb-2">
|
|
{dna.brandColors.palette?.map((color, idx) => (
|
|
<div key={idx} className="flex flex-col items-center">
|
|
<div
|
|
className="w-10 h-10 rounded-lg border border-border shadow-sm"
|
|
style={{ backgroundColor: color }}
|
|
/>
|
|
<span className="text-[10px] text-muted-foreground mt-1">{color}</span>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<p className="text-xs text-muted-foreground">
|
|
{dna.brandColors.mood}
|
|
</p>
|
|
</div>
|
|
|
|
{/* Visual Style */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Camera className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">시각적 스타일</h3>
|
|
</div>
|
|
<div className="grid grid-cols-2 gap-3">
|
|
<div className="bg-muted/50 rounded-lg p-3">
|
|
<div className="flex items-center gap-1 mb-1">
|
|
<Home className="w-3 h-3 text-muted-foreground" />
|
|
<span className="text-xs text-muted-foreground">인테리어</span>
|
|
</div>
|
|
<p className="text-sm font-medium">{dna.visualStyle.interior}</p>
|
|
</div>
|
|
<div className="bg-muted/50 rounded-lg p-3">
|
|
<div className="flex items-center gap-1 mb-1">
|
|
<Eye className="w-3 h-3 text-muted-foreground" />
|
|
<span className="text-xs text-muted-foreground">외관</span>
|
|
</div>
|
|
<p className="text-sm font-medium">{dna.visualStyle.exterior}</p>
|
|
</div>
|
|
</div>
|
|
<div className="mt-3 p-3 bg-muted/30 rounded-lg">
|
|
<p className="text-xs text-muted-foreground mb-1">분위기</p>
|
|
<p className="text-sm">{dna.visualStyle.atmosphere}</p>
|
|
<p className="text-xs text-muted-foreground mt-2">추천 사진 스타일: {dna.visualStyle.photoStyle}</p>
|
|
{dna.visualStyle.suggestedFilters && (
|
|
<div className="flex gap-1 mt-2">
|
|
{dna.visualStyle.suggestedFilters.map((filter, idx) => (
|
|
<Badge key={idx} variant="outline" className="text-xs">
|
|
{filter}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Keywords & Hashtags */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Hash className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">키워드 & 해시태그</h3>
|
|
</div>
|
|
<div className="flex flex-wrap gap-1 mb-2">
|
|
{dna.keywords.primary.map((keyword, idx) => (
|
|
<Badge key={idx} className="bg-primary/10 text-primary border-0">
|
|
{keyword}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
{dna.keywords.secondary && (
|
|
<div className="flex flex-wrap gap-1 mb-3">
|
|
{dna.keywords.secondary.map((keyword, idx) => (
|
|
<Badge key={idx} variant="outline" className="text-xs">
|
|
{keyword}
|
|
</Badge>
|
|
))}
|
|
</div>
|
|
)}
|
|
{dna.keywords.hashtags && (
|
|
<div className="flex flex-wrap gap-1">
|
|
{dna.keywords.hashtags.map((tag, idx) => (
|
|
<span key={idx} className="text-xs text-primary">
|
|
{tag}
|
|
</span>
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Unique Selling Points */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Star className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">차별화 포인트</h3>
|
|
</div>
|
|
<ul className="space-y-2">
|
|
{dna.uniqueSellingPoints.map((usp, idx) => (
|
|
<li key={idx} className="flex items-start gap-2 text-sm">
|
|
<TrendingUp className="w-4 h-4 text-green-500 shrink-0 mt-0.5" />
|
|
{usp}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
|
|
{/* Mood */}
|
|
<div>
|
|
<div className="flex items-center gap-2 mb-3">
|
|
<Target className="w-4 h-4 text-primary" />
|
|
<h3 className="font-semibold text-sm">분위기 & 감정</h3>
|
|
</div>
|
|
<Badge className="mb-2">{dna.mood.primary}</Badge>
|
|
<div className="flex flex-wrap gap-1">
|
|
{dna.mood.emotions.map((emotion, idx) => (
|
|
<span key={idx} className="text-xs bg-muted px-2 py-1 rounded-full">
|
|
{emotion}
|
|
</span>
|
|
))}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Sources */}
|
|
{dna.sources && dna.sources.length > 0 && (
|
|
<div className="pt-4 border-t border-border">
|
|
<p className="text-xs text-muted-foreground mb-2">분석 소스</p>
|
|
<div className="flex flex-wrap gap-2">
|
|
{dna.sources.map((source, idx) => (
|
|
<a
|
|
key={idx}
|
|
href={source}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="inline-flex items-center gap-1 text-xs text-primary hover:underline"
|
|
>
|
|
<ExternalLink className="w-3 h-3" />
|
|
{new URL(source).hostname}
|
|
</a>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Analyzed At */}
|
|
{dna.analyzedAt && (
|
|
<p className="text-xs text-muted-foreground text-right">
|
|
분석 시간: {new Date(dna.analyzedAt).toLocaleString('ko-KR')}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default DNACard;
|