144 lines
5.6 KiB
TypeScript
144 lines
5.6 KiB
TypeScript
import { motion } from 'motion/react';
|
|
import { Calendar, Globe, MapPin } from 'lucide-react';
|
|
import { ScoreRing } from './ui/ScoreRing';
|
|
|
|
interface ReportHeaderProps {
|
|
clinicName: string;
|
|
clinicNameEn: string;
|
|
overallScore: number;
|
|
date: string;
|
|
targetUrl: string;
|
|
location: string;
|
|
logoImage?: string;
|
|
brandColors?: { primary: string; accent: string; text: string };
|
|
}
|
|
|
|
export default function ReportHeader({
|
|
clinicName,
|
|
logoImage,
|
|
brandColors,
|
|
clinicNameEn,
|
|
overallScore,
|
|
date,
|
|
targetUrl,
|
|
location,
|
|
}: ReportHeaderProps) {
|
|
return (
|
|
<section className="relative overflow-hidden bg-[radial-gradient(ellipse_at_top_left,#e0e7ff,transparent_50%),radial-gradient(ellipse_at_bottom_right,#fce7f3,transparent_50%),radial-gradient(ellipse_at_center,#f5f3ff,transparent_60%)] py-20 px-6">
|
|
{/* Animated blobs */}
|
|
<motion.div
|
|
className="absolute top-10 left-10 w-72 h-72 rounded-full bg-indigo-200/30 blur-3xl"
|
|
animate={{ x: [0, 30, 0], y: [0, -20, 0] }}
|
|
transition={{ duration: 8, repeat: Infinity, ease: 'easeInOut' }}
|
|
/>
|
|
<motion.div
|
|
className="absolute bottom-10 right-10 w-96 h-96 rounded-full bg-pink-200/30 blur-3xl"
|
|
animate={{ x: [0, -20, 0], y: [0, 30, 0] }}
|
|
transition={{ duration: 10, repeat: Infinity, ease: 'easeInOut' }}
|
|
/>
|
|
<motion.div
|
|
className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-80 h-80 rounded-full bg-purple-200/20 blur-3xl"
|
|
animate={{ scale: [1, 1.1, 1] }}
|
|
transition={{ duration: 6, repeat: Infinity, ease: 'easeInOut' }}
|
|
/>
|
|
|
|
<div className="relative max-w-7xl mx-auto">
|
|
<div className="flex flex-col md:flex-row items-center md:items-start justify-between gap-10">
|
|
{/* Left: Text content */}
|
|
<motion.div
|
|
className="flex-1 text-center md:text-left"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5 }}
|
|
>
|
|
<motion.p
|
|
className="font-serif text-3xl md:text-4xl font-normal text-[#6C5CE7] mb-4 tracking-wide"
|
|
initial={{ opacity: 0, y: 10 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: 0.1 }}
|
|
>
|
|
Marketing Intelligence Report
|
|
</motion.p>
|
|
|
|
{logoImage && (
|
|
<motion.div
|
|
className="mb-4"
|
|
initial={{ opacity: 0, scale: 0.9 }}
|
|
whileInView={{ opacity: 1, scale: 1 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: 0.15 }}
|
|
>
|
|
<img
|
|
src={logoImage}
|
|
alt={clinicName}
|
|
className="h-16 md:h-20 w-auto object-contain md:mx-0 mx-auto"
|
|
onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}
|
|
/>
|
|
</motion.div>
|
|
)}
|
|
|
|
<motion.h1
|
|
className="font-serif text-4xl md:text-5xl font-bold text-[#0A1128] mb-3"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: 0.2 }}
|
|
>
|
|
{clinicName}
|
|
</motion.h1>
|
|
|
|
<motion.p
|
|
className="text-lg text-slate-600 mb-8"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: 0.3 }}
|
|
>
|
|
{clinicNameEn}
|
|
</motion.p>
|
|
|
|
<motion.div
|
|
className="flex flex-wrap gap-3 justify-center md:justify-start"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.5, delay: 0.4 }}
|
|
>
|
|
<span className="inline-flex items-center gap-2 rounded-full bg-white/60 backdrop-blur-sm border border-white/40 px-3 py-1 text-sm font-medium text-slate-700">
|
|
<Calendar size={14} className="text-slate-400" />
|
|
{date}
|
|
</span>
|
|
<span className="inline-flex items-center gap-2 rounded-full bg-white/60 backdrop-blur-sm border border-white/40 px-3 py-1 text-sm font-medium text-slate-700">
|
|
<Globe size={14} className="text-slate-400" />
|
|
{targetUrl}
|
|
</span>
|
|
<span className="inline-flex items-center gap-2 rounded-full bg-white/60 backdrop-blur-sm border border-white/40 px-3 py-1 text-sm font-medium text-slate-700">
|
|
<MapPin size={14} className="text-slate-400" />
|
|
{location}
|
|
</span>
|
|
</motion.div>
|
|
</motion.div>
|
|
|
|
{/* Right: Score ring */}
|
|
<motion.div
|
|
className="shrink-0"
|
|
initial={{ opacity: 0, scale: 0.8 }}
|
|
whileInView={{ opacity: 1, scale: 1 }}
|
|
viewport={{ once: true }}
|
|
transition={{ duration: 0.6, delay: 0.3 }}
|
|
>
|
|
<div className="bg-white/60 backdrop-blur-sm border border-white/40 rounded-3xl p-8 shadow-lg">
|
|
<p className="text-xs text-slate-500 uppercase tracking-wide text-center mb-4">
|
|
Overall Score
|
|
</p>
|
|
<ScoreRing score={overallScore} size={160} label="종합 점수" />
|
|
</div>
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|