94 lines
3.8 KiB
TypeScript
94 lines
3.8 KiB
TypeScript
/**
|
|
* UserReportPage — `/clinics/:clinicId/report/:id`
|
|
*
|
|
* 계약된 병원 유저가 워크스페이스 안에서 보는 리포트 화면.
|
|
* 본문은 GuestReportPage 와 동일하지만:
|
|
* - 상단에 워크스페이스 액션바 (워크스페이스로 돌아가기, 플랜 생성, 다시 분석)
|
|
* - 하단의 도입 문의 CTA 없음
|
|
*/
|
|
import { Link, useParams } from 'react-router';
|
|
import { ArrowLeft, Sparkles, RefreshCw } from 'lucide-react';
|
|
import { useReportPageData } from '../hooks/useReportPageData';
|
|
import { ReportNav } from '../components/ReportNav';
|
|
import { ScreenshotProvider } from '../stores/ScreenshotContext';
|
|
import { REPORT_SECTIONS } from '@/shared/constants/reportSections';
|
|
import ReportBody from '../components/ReportBody';
|
|
import { DownloadMenuButton } from '../components/DownloadMenuButton';
|
|
|
|
export default function UserReportPage() {
|
|
const { clinicId, id } = useParams<{ clinicId: string; id: string }>();
|
|
const { data, isLoading, error, enrichStatus } = useReportPageData(id);
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center pt-20">
|
|
<div className="flex flex-col items-center gap-4">
|
|
<div className="w-10 h-10 border-4 border-[#6C5CE7] border-t-transparent rounded-full animate-spin" />
|
|
<p className="text-slate-500 text-sm">리포트를 불러오는 중...</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (error || !data) {
|
|
return (
|
|
<div className="min-h-screen flex items-center justify-center pt-20">
|
|
<div className="text-center">
|
|
<p className="text-[#7C3A4B] font-medium mb-2">오류가 발생했습니다</p>
|
|
<p className="text-slate-500 text-sm">{error ?? '리포트를 찾을 수 없습니다.'}</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<ScreenshotProvider screenshots={data.screenshots ?? []}>
|
|
<div className="pt-20">
|
|
<ReportNav
|
|
sections={REPORT_SECTIONS}
|
|
leftSlot={
|
|
<Link
|
|
to={`/clinics/${clinicId}`}
|
|
className="inline-flex items-center gap-1.5 text-xs font-medium text-slate-500 hover:text-primary-900 transition-colors"
|
|
>
|
|
<ArrowLeft size={14} />
|
|
워크스페이스로
|
|
</Link>
|
|
}
|
|
rightSlot={
|
|
<div className="flex items-center gap-2">
|
|
<DownloadMenuButton
|
|
filename={`${data.clinicSnapshot.name}_Marketing_Intelligence_Report`}
|
|
report={data}
|
|
/>
|
|
<Link
|
|
to={`/report/loading`}
|
|
className="inline-flex items-center gap-1.5 px-3.5 py-2 rounded-full text-xs font-medium text-slate-600 bg-slate-50 border border-slate-200 hover:bg-white hover:border-slate-300 transition-all"
|
|
>
|
|
<RefreshCw size={12} />
|
|
다시 분석
|
|
</Link>
|
|
<Link
|
|
to={`/clinics/${clinicId}/plan/${id}`}
|
|
className="inline-flex items-center gap-1.5 px-4 py-2 rounded-full text-xs font-semibold text-white bg-gradient-to-r from-[#4F1DA1] to-[#021341] shadow-sm hover:opacity-90 transition-all"
|
|
>
|
|
<Sparkles size={12} />
|
|
마케팅 기획 보기
|
|
</Link>
|
|
</div>
|
|
}
|
|
/>
|
|
|
|
{enrichStatus === 'loading' && (
|
|
<div className="fixed bottom-6 right-6 z-50 flex items-center gap-3 px-4 py-3 bg-white rounded-xl shadow-[3px_4px_12px_rgba(0,0,0,0.06)] border border-slate-100">
|
|
<div className="w-4 h-4 border-2 border-[#6C5CE7] border-t-transparent rounded-full animate-spin" />
|
|
<span className="text-xs text-slate-500">채널 데이터 보강 중...</span>
|
|
</div>
|
|
)}
|
|
|
|
<ReportBody data={data} />
|
|
</div>
|
|
</ScreenshotProvider>
|
|
);
|
|
}
|