castad-pre-v0.3/castad-data/src/components/DNACard.tsx

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;