diff --git a/src/features/dev/pages/ClinicsPage.tsx b/src/features/dev/pages/ClinicsPage.tsx index b2e7e21..2402118 100644 --- a/src/features/dev/pages/ClinicsPage.tsx +++ b/src/features/dev/pages/ClinicsPage.tsx @@ -1,12 +1,12 @@ /** * Dev: 클리닉 리스트 페이지. * - * 백엔드 `GET /api/clinics` (listClinics) 응답을 표로 확인하는 개발용 화면. + * 백엔드 `GET /api/clinics` (getClinics) 응답을 표로 확인하는 개발용 화면. * 운영 도메인 노출 방지는 라우트 단의 DevOnly 가드에 위임. */ import { useState } from 'react'; import { Link } from 'react-router'; -import { useListClinics } from '@/shared/api/generated/clinics/clinics'; +import { useGetClinics } from '@/shared/api/generated/clinics/clinics'; import { PageContainer } from '@/shared/ui/page-container'; import { Spinner } from '@/shared/ui/spinner'; import { EmptyState } from '@/shared/ui/empty-state'; @@ -31,12 +31,13 @@ function formatDate(raw: string): string { export default function ClinicsPage() { const [offset, setOffset] = useState(0); - const { data, isLoading, error, refetch, isFetching } = useListClinics( + const { data, isLoading, error, refetch, isFetching } = useGetClinics( { limit: PAGE_SIZE, offset }, { query: { staleTime: 0 } }, ); - const items = data?.status === 200 ? data.data : []; + const items = data?.status === 200 ? data.data.items : []; + const total = data?.status === 200 ? data.data.total : 0; return (
@@ -50,7 +51,7 @@ export default function ClinicsPage() { 클리닉 리스트

- GET /api/clinics · limit={PAGE_SIZE} · offset={offset} + GET /api/clinics · limit={PAGE_SIZE} · offset={offset} · total={total}

@@ -131,8 +132,10 @@ export default function ClinicsPage() {
)} - {/* 페이지네이션 — 정확한 total 이 없어서 단순 prev/next 만 노출 */}
+ + {total > 0 ? `${offset + 1}-${Math.min(offset + items.length, total)} / ${total}` : ''} + diff --git a/src/features/dev/routes.tsx b/src/features/dev/routes.tsx index 0f0505f..9ec7c18 100644 --- a/src/features/dev/routes.tsx +++ b/src/features/dev/routes.tsx @@ -2,8 +2,7 @@ import { lazy } from 'react' import DevOnly from './components/DevOnly' const ComponentsPage = lazy(() => import('./pages/ComponentsPage')) -// TODO: SDK 재생성으로 useListClinics 가 제거됨. 백엔드에 list 엔드포인트 재추가 후 복구. -// const ClinicsPage = lazy(() => import('./pages/ClinicsPage')) +const ClinicsPage = lazy(() => import('./pages/ClinicsPage')) // `/dev/*` 는 DevOnly 가드를 거쳐 로컬호스트에서만 접근 가능. export const devRoutes = [ @@ -11,7 +10,7 @@ export const devRoutes = [ element: , children: [ { path: 'dev/components', element: }, - // { path: 'dev/clinics', element: }, + { path: 'dev/clinics', element: }, ], }, ] diff --git a/src/features/plan/components/MyAssetUpload.tsx b/src/features/plan/components/MyAssetUpload.tsx index 3dd2489..6b6d6a0 100644 --- a/src/features/plan/components/MyAssetUpload.tsx +++ b/src/features/plan/components/MyAssetUpload.tsx @@ -1,10 +1,26 @@ -import { useState, useRef, useCallback, type DragEvent, type ChangeEvent } from 'react'; +import { useState, useRef, useCallback, useEffect, type DragEvent, type ChangeEvent } from 'react'; import { motion, AnimatePresence } from 'motion/react'; import { SectionWrapper } from '@/features/report/components/ui/SectionWrapper'; import { VideoFilled, FileTextFilled } from '@/shared/icons/FilledIcons'; import { Button } from '@/shared/ui/button'; +import { Spinner } from '@/shared/ui/spinner'; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/shared/ui/dialog'; +import { + useUploadAnalysisRunFile, + useGetAnalysisRunFiles, + useDeleteAnalysisRunFile, +} from '@/shared/api/generated/analysis/analysis'; +import type { FileListItem } from '@/shared/api/model/fileListItem'; import { type UploadCategory, + type AssetCategory, categoryConfig, categoryBadge, ALL_ACCEPT, @@ -15,43 +31,141 @@ import { // ─── Types ─── +type AssetStatus = 'idle' | 'uploading' | 'done' | 'error'; + interface UploadedAsset { id: string; - file: File; - category: 'image' | 'video' | 'text'; + /** 로컬 업로드 직후엔 File 보유, 서버에서 받은 항목은 null. */ + file: File | null; + category: AssetCategory; previewUrl: string | null; name: string; size: string; uploadedAt: Date; + status: AssetStatus; + remoteId?: number; + errorMessage?: string; +} + +interface MyAssetUploadProps { + /** 업로드 대상 analysis run id. 없으면 로컬 미리보기만 동작. */ + analysisRunId?: string; +} + +// 백엔드 FileType ('image'|'video'|'audio'|'document'|'file') → 로컬 AssetCategory 1:1. +function mapFileTypeToCategory(fileType: string): AssetCategory { + if (fileType === 'image' || fileType === 'video' || fileType === 'audio' || fileType === 'document') { + return fileType; + } + return 'file'; +} + +function serverFileToAsset(item: FileListItem): UploadedAsset { + const cat = mapFileTypeToCategory(item.file_type); + return { + id: `remote-${item.id}`, + file: null, + category: cat, + previewUrl: cat === 'image' || cat === 'video' ? item.file_url : null, + name: item.file_name, + size: typeof item.size_bytes === 'number' ? formatSize(item.size_bytes) : '', + uploadedAt: new Date(item.created_at), + status: 'done', + remoteId: item.id, + }; } // ─── Component ─── -export default function MyAssetUpload() { +export default function MyAssetUpload({ analysisRunId }: MyAssetUploadProps = {}) { const [assets, setAssets] = useState([]); const [activeFilter, setActiveFilter] = useState('all'); const [isDragOver, setIsDragOver] = useState(false); + const [pendingDeleteId, setPendingDeleteId] = useState(null); + const [isDeleting, setIsDeleting] = useState(false); const inputRef = useRef(null); - const processFiles = useCallback((files: FileList | File[]) => { - const newAssets: UploadedAsset[] = Array.from(files).map((file) => { - const cat = categorize(file); - const previewUrl = - cat === 'image' || cat === 'video' - ? URL.createObjectURL(file) - : null; - return { - id: uid(), - file, - category: cat, - previewUrl, - name: file.name, - size: formatSize(file.size), - uploadedAt: new Date(), - }; + const { mutateAsync: uploadFile } = useUploadAnalysisRunFile(); + const { mutateAsync: deleteFile } = useDeleteAnalysisRunFile(); + const filesQuery = useGetAnalysisRunFiles( + analysisRunId ?? '', + { query: { enabled: !!analysisRunId } }, + ); + + // 서버 파일 목록 → 로컬 assets 머지. 진행 중/실패 로컬 항목은 보존. + useEffect(() => { + if (filesQuery.data?.status !== 200) return; + const serverAssets = filesQuery.data.data.map(serverFileToAsset); + const serverIds = new Set(serverAssets.map((a) => a.remoteId)); + setAssets((prev) => { + const localPending = prev.filter( + (a) => a.remoteId == null || !serverIds.has(a.remoteId), + ); + return [...localPending, ...serverAssets]; }); - setAssets((prev) => [...newAssets, ...prev]); - }, []); + }, [filesQuery.data]); + + const processFiles = useCallback( + (files: FileList | File[]) => { + const newAssets: UploadedAsset[] = Array.from(files).map((file) => { + const cat = categorize(file); + const previewUrl = + cat === 'image' || cat === 'video' ? URL.createObjectURL(file) : null; + return { + id: uid(), + file, + category: cat, + previewUrl, + name: file.name, + size: formatSize(file.size), + uploadedAt: new Date(), + status: analysisRunId ? 'uploading' : 'idle', + }; + }); + setAssets((prev) => [...newAssets, ...prev]); + + if (!analysisRunId) return; + + newAssets.forEach(async (asset) => { + try { + const res = await uploadFile({ + runId: analysisRunId, + // orval 이 binary 필드를 string 으로 타입 생성하므로 캐스팅 필요. 런타임은 FormData 로 정상 처리. + data: { file: asset.file as unknown as string, file_type: asset.category }, + }); + if (res.status === 201) { + setAssets((prev) => + prev.map((a) => + a.id === asset.id ? { ...a, status: 'done', remoteId: res.data.id } : a, + ), + ); + filesQuery.refetch(); + } else { + setAssets((prev) => + prev.map((a) => + a.id === asset.id + ? { ...a, status: 'error', errorMessage: '업로드 검증 실패' } + : a, + ), + ); + } + } catch (err) { + setAssets((prev) => + prev.map((a) => + a.id === asset.id + ? { + ...a, + status: 'error', + errorMessage: err instanceof Error ? err.message : '업로드 실패', + } + : a, + ), + ); + } + }); + }, + [analysisRunId, uploadFile, filesQuery], + ); const handleDrop = useCallback( (e: DragEvent) => { @@ -72,22 +186,48 @@ export default function MyAssetUpload() { [processFiles], ); - const removeAsset = useCallback((id: string) => { - setAssets((prev) => { - const found = prev.find((a) => a.id === id); - if (found?.previewUrl) URL.revokeObjectURL(found.previewUrl); - return prev.filter((a) => a.id !== id); - }); - }, []); + const confirmDelete = useCallback(async () => { + if (!pendingDeleteId) return; + const target = assets.find((a) => a.id === pendingDeleteId); + if (!target) { + setPendingDeleteId(null); + return; + } + + setIsDeleting(true); + + if (target.file && target.previewUrl) URL.revokeObjectURL(target.previewUrl); + + if (analysisRunId && target.remoteId != null) { + try { + await deleteFile({ runId: analysisRunId, fileId: target.remoteId }); + filesQuery.refetch(); + } catch { + setIsDeleting(false); + setPendingDeleteId(null); + return; + } + } + + setAssets((prev) => prev.filter((a) => a.id !== pendingDeleteId)); + setIsDeleting(false); + setPendingDeleteId(null); + }, [pendingDeleteId, assets, analysisRunId, deleteFile, filesQuery]); + + const pendingDeleteAsset = pendingDeleteId + ? assets.find((a) => a.id === pendingDeleteId) ?? null + : null; const filtered = activeFilter === 'all' ? assets : assets.filter((a) => a.category === activeFilter); - const counts = { + const counts: Record = { all: assets.length, image: assets.filter((a) => a.category === 'image').length, video: assets.filter((a) => a.category === 'video').length, - text: assets.filter((a) => a.category === 'text').length, + audio: assets.filter((a) => a.category === 'audio').length, + document: assets.filter((a) => a.category === 'document').length, + file: assets.filter((a) => a.category === 'file').length, }; return ( @@ -143,17 +283,17 @@ export default function MyAssetUpload() { 파일을 드래그하거나 클릭하여 업로드

- Image, Video, Text 파일 지원 (JPG, PNG, MP4, MOV, TXT, PDF, DOC 등) + Image, Video, Audio, Document, File 지원 (JPG, MP4, MP3, PDF, DOCX, ZIP 등)

{/* File Type Badges */} -
- {(['image', 'video', 'text'] as const).map((cat) => ( +
+ {(['image', 'video', 'audio', 'document', 'file'] as const).map((cat) => ( - {cat === 'image' ? 'Image' : cat === 'video' ? 'Video' : 'Text'} + {categoryConfig[cat].label} ))}
@@ -216,7 +356,9 @@ export default function MyAssetUpload() { }} /> )} - {asset.category === 'text' && ( + {(asset.category === 'audio' || + asset.category === 'document' || + asset.category === 'file') && (
@@ -230,7 +372,7 @@ export default function MyAssetUpload() { type="button" variant="ghost" size="icon-sm" - onClick={() => removeAsset(asset.id)} + onClick={() => setPendingDeleteId(asset.id)} className="absolute top-2 right-2 w-7 h-7 size-7 rounded-full bg-white/90 backdrop-blur-sm border border-slate-100 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity shadow-sm hover:bg-brand-rose-bg" > @@ -242,11 +384,7 @@ export default function MyAssetUpload() { - {asset.category === 'image' - ? 'Image' - : asset.category === 'video' - ? 'Video' - : 'Text'} + {categoryConfig[asset.category].label} {/* Video Duration Overlay */} @@ -263,7 +401,28 @@ export default function MyAssetUpload() {

{asset.name}

-

{asset.size}

+
+

+ {asset.size || categoryConfig[asset.category].label} +

+ {asset.status === 'uploading' && ( + + + 업로드 중 + + )} + {asset.status === 'done' && ( + 완료 + )} + {asset.status === 'error' && ( + + 업로드 실패 + + )} +
))} @@ -271,6 +430,43 @@ export default function MyAssetUpload() {
)} + + { + if (!open && !isDeleting) setPendingDeleteId(null); + }} + > + + + 파일을 삭제할까요? + + {pendingDeleteAsset + ? `"${pendingDeleteAsset.name}" 을(를) 삭제합니다. 이 동작은 되돌릴 수 없습니다.` + : '이 동작은 되돌릴 수 없습니다.'} + + + + + + + + ); } diff --git a/src/features/plan/data/myAssetUploadConstants.ts b/src/features/plan/data/myAssetUploadConstants.ts index bc5e4d8..4db1831 100644 --- a/src/features/plan/data/myAssetUploadConstants.ts +++ b/src/features/plan/data/myAssetUploadConstants.ts @@ -1,30 +1,54 @@ -export type UploadCategory = 'all' | 'image' | 'video' | 'text'; +/** + * 백엔드 FileType 과 1:1 매칭되는 5종 분류. + * image — jpg, png, gif, webp, heic + * video — mp4, mov, avi, webm + * audio — mp3, wav, m4a, ogg + * document — pdf, docx, xlsx, pptx, txt, csv, hwp + * file — 그 외/분류 애매 (zip, json 등) + */ +export type AssetCategory = 'image' | 'video' | 'audio' | 'document' | 'file'; +export type UploadCategory = 'all' | AssetCategory; export const categoryConfig: Record = { all: { label: '전체' }, image: { label: 'Image' }, video: { label: 'Video' }, - text: { label: 'Text' }, + audio: { label: 'Audio' }, + document: { label: 'Document' }, + file: { label: 'File' }, }; -export const categoryBadge: Record<'image' | 'video' | 'text', string> = { +export const categoryBadge: Record = { image: 'bg-brand-tint-purple text-brand-purple-muted shadow-[2px_3px_6px_rgba(155,138,212,0.12)]', video: 'bg-brand-rose-bg text-brand-rose shadow-[2px_3px_6px_rgba(212,136,154,0.12)]', - text: 'bg-brand-earth-bg text-brand-earth shadow-[2px_3px_6px_rgba(212,168,114,0.12)]', + audio: 'bg-sky-50 text-sky-700 shadow-[2px_3px_6px_rgba(56,189,248,0.12)]', + document: 'bg-brand-earth-bg text-brand-earth shadow-[2px_3px_6px_rgba(212,168,114,0.12)]', + file: 'bg-slate-100 text-slate-600 shadow-[2px_3px_6px_rgba(100,116,139,0.10)]', }; -export const ACCEPT_MAP: Record = { - 'image/*': '.jpg,.jpeg,.png,.gif,.webp,.svg', - 'video/*': '.mp4,.mov,.webm,.avi', - 'text/*': '.txt,.md,.doc,.docx,.pdf,.csv,.json', +// 확장자 → 카테고리. 백엔드 분류 규칙과 동일. +const EXT_BY_CATEGORY: Record = { + image: ['jpg', 'jpeg', 'png', 'gif', 'webp', 'heic'], + video: ['mp4', 'mov', 'avi', 'webm'], + audio: ['mp3', 'wav', 'm4a', 'ogg'], + document: ['pdf', 'docx', 'xlsx', 'pptx', 'txt', 'csv', 'hwp'], + file: [], // 폴백 }; -export const ALL_ACCEPT = Object.values(ACCEPT_MAP).join(','); +export const ALL_ACCEPT = (Object.entries(EXT_BY_CATEGORY) as [AssetCategory, string[]][]) + .flatMap(([, exts]) => exts.map((e) => `.${e}`)) + .join(','); -export function categorize(file: File): 'image' | 'video' | 'text' { +export function categorize(file: File): AssetCategory { + const ext = file.name.split('.').pop()?.toLowerCase() ?? ''; + for (const [cat, exts] of Object.entries(EXT_BY_CATEGORY) as [AssetCategory, string[]][]) { + if (exts.includes(ext)) return cat; + } + // MIME 폴백 — 확장자 누락된 케이스 보완. if (file.type.startsWith('image/')) return 'image'; if (file.type.startsWith('video/')) return 'video'; - return 'text'; + if (file.type.startsWith('audio/')) return 'audio'; + return 'file'; } export function formatSize(bytes: number): string { diff --git a/src/features/plan/hooks/useMarketingPlan.ts b/src/features/plan/hooks/useMarketingPlan.ts index f7357a6..d15a07f 100644 --- a/src/features/plan/hooks/useMarketingPlan.ts +++ b/src/features/plan/hooks/useMarketingPlan.ts @@ -1,6 +1,6 @@ import { useState, useEffect } from 'react'; import type { MarketingPlan } from '@/features/plan/types/plan'; -import { getPlan } from '@/shared/api/generated/plans/plans'; +import { getPlan } from '@/shared/api/generated/plan/plan'; interface UseMarketingPlanResult { data: MarketingPlan | null; @@ -32,19 +32,14 @@ export function useMarketingPlan(id: string | undefined): UseMarketingPlanResult throw new Error('마케팅 기획이 아직 생성되지 않았습니다.'); } + // SDK PlanApiResponse 가 MarketingPlan 과 사실상 동일 — 패스스루. + // reportId/workflow 는 SDK 에 없는 로컬 전용 필드. setData({ - id: id!, + ...(planOutput as unknown as MarketingPlan), + id: planOutput.id || id!, reportId: id!, - clinicName: '', - clinicNameEn: '', - createdAt: '', - targetUrl: '', - brandGuide: planOutput.brandGuide as MarketingPlan['brandGuide'], - channelStrategies: planOutput.channelStrategies as MarketingPlan['channelStrategies'], - contentStrategy: planOutput.contentStrategy as MarketingPlan['contentStrategy'], - calendar: planOutput.calendar as MarketingPlan['calendar'], - assetCollection: planOutput.assetCollection as MarketingPlan['assetCollection'], - repurposingProposals: (planOutput.repurposingProposals ?? undefined) as MarketingPlan['repurposingProposals'], + clinicName: planOutput.clinicName ?? '', + clinicNameEn: planOutput.clinicNameEn ?? '', }); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch marketing plan'); diff --git a/src/features/plan/pages/GuestPlanPage.tsx b/src/features/plan/pages/GuestPlanPage.tsx deleted file mode 100644 index c77cc05..0000000 --- a/src/features/plan/pages/GuestPlanPage.tsx +++ /dev/null @@ -1,64 +0,0 @@ -/** - * GuestPlanPage — `/plan/:id` - * - * 손님(비계약 방문자)이 보는 플랜 미리보기. 본문은 UserPlanPage 와 동일하나, - * 인터랙티브 섹션(자산 업로드/전략 조정/워크플로우)은 노출되지 않고 - * 하단에 도입 문의 CTA(PlanCTA) 가 붙습니다. - */ -import { useEffect } from 'react'; -import { useParams, useLocation } from 'react-router'; -import { useMarketingPlan } from '../hooks/useMarketingPlan'; -import { ReportNav } from '@/features/report/components/ReportNav'; -import { PLAN_SECTIONS } from '@/shared/constants/planSections'; -import PlanBody from '../components/PlanBody'; - -export default function GuestPlanPage() { - const { id } = useParams<{ id: string }>(); - const location = useLocation(); - const { data, isLoading, error } = useMarketingPlan(id); - - // 해시 기반 스크롤: /plan/:id#section-id → 렌더링 후 해당 섹션으로 - useEffect(() => { - if (isLoading || !location.hash) return; - const sectionId = location.hash.slice(1); - const timer = setTimeout(() => { - const el = document.getElementById(sectionId); - if (!el) return; - const STICKY_OFFSET = 128; - const y = el.getBoundingClientRect().top + window.scrollY - STICKY_OFFSET; - window.scrollTo({ top: y, behavior: 'smooth' }); - }, 300); - return () => clearTimeout(timer); - }, [isLoading, location.hash]); - - if (isLoading) { - return ( -
-
-
-

마케팅 기획을 불러오는 중...

-
-
- ); - } - - if (error || !data) { - return ( -
-
-

오류가 발생했습니다

-

- {error ?? '마케팅 기획을 찾을 수 없습니다.'} -

-
-
- ); - } - - return ( -
- - -
- ); -} diff --git a/src/features/plan/pages/UserPlanPage.tsx b/src/features/plan/pages/PlanPage.tsx similarity index 66% rename from src/features/plan/pages/UserPlanPage.tsx rename to src/features/plan/pages/PlanPage.tsx index 4c6df6f..67e5c29 100644 --- a/src/features/plan/pages/UserPlanPage.tsx +++ b/src/features/plan/pages/PlanPage.tsx @@ -1,12 +1,12 @@ /** - * UserPlanPage — `/clinics/:clinicId/plan/:id` + * PlanPage — 마케팅 기획 화면 (단일 페이지). * - * 계약된 병원 유저가 워크스페이스에서 운영하는 마케팅 기획 화면. - * GuestPlanPage 의 본문 + 워크스페이스 액션바 + 인터랙티브 섹션 - * (MyAssetUpload / WorkflowTracker). + * 두 경로에서 동일 컴포넌트로 진입: + * - `/plan/:id` (랜딩 → 분석 → 리포트 → 플랜) + * - `/clinics/:clinicId/plan/:id` (워크스페이스 진입) * - * NOTE: StrategyAdjustmentSection(성과 기반 전략 조정) 은 성과 데이터 파이프라인 의존 → - * 본 차수 미포함, 후속 모듈로 이관. 아래 import/render 주석 처리. + * 본문(PlanBody) + 인터랙티브 섹션(MyAssetUpload / WorkflowTracker) + 도입 문의 CTA 모두 노출. + * 업로드는 analysisRunId(=URL :id) 를 항상 넘기므로 어디서 들어와도 SDK 호출. */ import { useEffect } from 'react'; import { useParams, useLocation } from 'react-router'; @@ -15,15 +15,15 @@ import { ReportNav } from '@/features/report/components/ReportNav'; import { PLAN_SECTIONS } from '@/shared/constants/planSections'; import PlanBody from '../components/PlanBody'; import MyAssetUpload from '../components/MyAssetUpload'; -// import StrategyAdjustmentSection from '../components/StrategyAdjustmentSection'; import WorkflowTracker from '../components/WorkflowTracker'; +import PlanCTA from '../components/PlanCTA'; -export default function UserPlanPage() { - const { id } = useParams<{ clinicId: string; id: string }>(); +export default function PlanPage() { + const { id } = useParams<{ clinicId?: string; id: string }>(); const location = useLocation(); - // const stateClinicId = (location.state as { clinicId?: string } | undefined)?.clinicId || null; const { data, isLoading, error } = useMarketingPlan(id); + // 해시 기반 스크롤: /plan/:id#section-id → 렌더링 후 해당 섹션으로 useEffect(() => { if (isLoading || !location.hash) return; const sectionId = location.hash.slice(1); @@ -65,7 +65,6 @@ export default function UserPlanPage() { - {/* 유저 전용 인터랙티브 섹션 */} {data.workflow && (
@@ -73,13 +72,10 @@ export default function UserPlanPage() { )}
- +
- {/* 성과 기반 전략 조정 — 본 차수 미포함, 후속 모듈 이관 */} - {/*
- -
*/} +
); } diff --git a/src/features/plan/routes.tsx b/src/features/plan/routes.tsx index e2c038d..ee7d1cd 100644 --- a/src/features/plan/routes.tsx +++ b/src/features/plan/routes.tsx @@ -1,9 +1,10 @@ import { lazy } from 'react' import type { RouteObject } from 'react-router' -const GuestPlanPage = lazy(() => import('./pages/GuestPlanPage')) +const PlanPage = lazy(() => import('./pages/PlanPage')) export const planRoutes: RouteObject[] = [ - // 손님(랜딩→분석→리포트→플랜) 흐름. 유저 워크스페이스 경로는 features/clinics/routes.tsx 참조. - { path: 'plan/:id', element: }, + // `/plan/:id` 와 `/clinics/:clinicId/plan/:id` 모두 동일 PlanPage 사용. + // 워크스페이스 경로 정의는 features/clinics/routes.tsx 참조. + { path: 'plan/:id', element: }, ] diff --git a/src/features/report/hooks/useReport.ts b/src/features/report/hooks/useReport.ts index 3dbc882..df4fb76 100644 --- a/src/features/report/hooks/useReport.ts +++ b/src/features/report/hooks/useReport.ts @@ -1,7 +1,6 @@ import { useState, useEffect } from 'react'; import type { MarketingReport } from '@/features/report/types/report'; -import { getReport } from '@/shared/api/generated/reports/reports'; -import { transformReportOutput } from '@/features/report/lib/transformReport'; +import { getReport } from '@/shared/api/generated/report/report'; interface UseReportResult { data: MarketingReport | null; @@ -33,8 +32,9 @@ export function useReport(id: string | undefined): UseReportResult { if (!output) { throw new Error('리포트 데이터가 비어있습니다.'); } - const transformed = transformReportOutput(id, output, { url: '', generatedAt: '' }); - setData(transformed); + // SDK MarketingReportResponse 가 사실상 MarketingReport 와 같은 shape — 그대로 사용. + // 미세한 차이(ScreenshotEvidence 등)는 컴포넌트 단에서 옵셔널로 처리됨. + setData(output as unknown as MarketingReport); }) .catch((err) => { setError(err instanceof Error ? err.message : 'Failed to fetch report'); diff --git a/src/features/report/lib/transformReport.ts b/src/features/report/lib/transformReport.ts index 5aa887d..385b17f 100644 --- a/src/features/report/lib/transformReport.ts +++ b/src/features/report/lib/transformReport.ts @@ -1,6 +1,4 @@ import type { MarketingReport, Severity, ChannelScore, DiagnosisItem, TopVideo } from '@/features/report/types/report'; -import type { ReportOutput } from '@/shared/api/model/reportOutput'; -import type { ChannelScore as SdkChannelScore } from '@/shared/api/model/channelScore'; /** * generate-report Edge Function의 API 응답. @@ -1269,203 +1267,5 @@ export function mergeEnrichment( return merged; } -// ════════════════════════════════════════════════════════════════════════════ -// SDK ReportOutput → MarketingReport 변환 -// 백엔드 OpenAPI 스펙(ReportOutput)을 그대로 받아 프론트엔드 컴포넌트가 기대하는 -// MarketingReport 형태로 매핑. ReportOutput에 없는 풍부한 메타(clinicSnapshot, -// topVideos 등)는 빈 값으로 둠. -// ════════════════════════════════════════════════════════════════════════════ - -interface ReportMetadata { - url: string; - generatedAt?: string; - clinicName?: string; -} - -function channelScoreToScoreCard( - channel: string, - icon: string, - ch: SdkChannelScore, -): ChannelScore { - return { - channel, - icon, - score: ch.score, - maxScore: 100, - status: scoreToSeverity(ch.score), - headline: ch.summary, - }; -} - -function channelScoreToDiagnosis( - category: string, - ch: SdkChannelScore | null | undefined, -): DiagnosisItem[] { - if (!ch) return []; - const items: DiagnosisItem[] = []; - for (const weakness of ch.weaknesses) { - items.push({ category, detail: weakness, severity: scoreToSeverity(ch.score) }); - } - return items; -} - -/** "1주차: 채널 역할 정의" → { month: 1, title: '1주차', subtitle: '채널 역할 정의' } */ -function parseRoadmapLine(line: string, index: number): import('../types/report').RoadmapMonth { - const colonIdx = line.indexOf(':'); - if (colonIdx === -1) { - return { month: index + 1, title: `Week ${index + 1}`, subtitle: line.trim(), tasks: [] }; - } - return { - month: index + 1, - title: line.slice(0, colonIdx).trim(), - subtitle: line.slice(colonIdx + 1).trim(), - tasks: [], - }; -} - -/** - * 백엔드 SDK의 ReportOutput을 그대로 받아 MarketingReport로 변환. - * - ReportOutput에 있는 필드: overall_score, {youtube,instagram,facebook,naver_blog,gangnam_unni}, conversion_strategy, roadmap, kpis - * - 그 외 풍부한 메타(clinicSnapshot, topVideos, followers 등)는 SDK에 없으므로 빈/기본값 - */ -export function transformReportOutput( - reportId: string, - output: ReportOutput, - metadata: ReportMetadata, -): MarketingReport { - const domain = (() => { - try { return new URL(metadata.url).hostname; } catch { return metadata.url || ''; } - })(); - - // 채널별 score card — SDK에 값이 있는 채널만 - const channelScores: ChannelScore[] = []; - if (output.youtube) channelScores.push(channelScoreToScoreCard('YouTube', 'youtube', output.youtube)); - if (output.instagram) channelScores.push(channelScoreToScoreCard('Instagram', 'instagram', output.instagram)); - if (output.facebook) channelScores.push(channelScoreToScoreCard('Facebook', 'facebook', output.facebook)); - if (output.naver_blog) channelScores.push(channelScoreToScoreCard('네이버 블로그', 'blog', output.naver_blog)); - if (output.gangnam_unni) channelScores.push(channelScoreToScoreCard('강남언니', 'star', output.gangnam_unni)); - - // 전체 약점을 problemDiagnosis로 모음 - const problemDiagnosis: DiagnosisItem[] = [ - ...channelScoreToDiagnosis('YouTube', output.youtube), - ...channelScoreToDiagnosis('Instagram', output.instagram), - ...channelScoreToDiagnosis('Facebook', output.facebook), - ...channelScoreToDiagnosis('네이버 블로그', output.naver_blog), - ...channelScoreToDiagnosis('강남언니', output.gangnam_unni), - ]; - - return { - id: reportId, - createdAt: metadata.generatedAt || new Date().toISOString(), - targetUrl: metadata.url, - overallScore: output.overall_score, - - clinicSnapshot: { - name: metadata.clinicName || '', - nameEn: '', - established: '', - yearsInBusiness: 0, - staffCount: 0, - leadDoctor: { name: '', credentials: '', rating: 0, reviewCount: 0 }, - overallRating: 0, - totalReviews: 0, - priceRange: { min: '-', max: '-', currency: '₩' }, - certifications: [], - mediaAppearances: [], - medicalTourism: [], - location: '', - nearestStation: '', - phone: '', - domain, - }, - - channelScores, - - youtubeAudit: { - channelName: '', - handle: '', - subscribers: 0, - totalVideos: 0, - totalViews: 0, - weeklyViewGrowth: { absolute: 0, percentage: 0 }, - estimatedMonthlyRevenue: { min: 0, max: 0 }, - avgVideoLength: '-', - uploadFrequency: '-', - channelCreatedDate: '', - subscriberRank: '-', - channelDescription: output.youtube?.summary || '', - linkedUrls: [], - playlists: [], - topVideos: [], - diagnosis: channelScoreToDiagnosis('YouTube', output.youtube), - }, - - instagramAudit: { - accounts: output.instagram ? [{ - handle: '', - language: 'KR', - label: '메인', - posts: 0, - followers: 0, - following: 0, - category: '의료/건강', - profileLink: '', - highlights: [], - reelsCount: 0, - contentFormat: '', - profilePhoto: '', - bio: output.instagram.summary, - }] : [], - diagnosis: channelScoreToDiagnosis('Instagram', output.instagram), - }, - - facebookAudit: { - pages: [], - diagnosis: channelScoreToDiagnosis('Facebook', output.facebook), - brandInconsistencies: [], - consolidationRecommendation: '', - }, - - otherChannels: [ - ...(output.naver_blog ? [{ - name: '네이버 블로그', - status: 'active' as const, - details: output.naver_blog.summary, - }] : []), - ...(output.gangnam_unni ? [{ - name: '강남언니', - status: 'active' as const, - details: output.gangnam_unni.summary, - }] : []), - ], - - websiteAudit: { - primaryDomain: domain, - additionalDomains: [], - snsLinksOnSite: false, - trackingPixels: [], - mainCTA: '', - }, - - problemDiagnosis, - - transformation: { - brandIdentity: [], - contentStrategy: [], - platformStrategies: [], - websiteImprovements: [], - newChannelProposals: [], - }, - - roadmap: output.roadmap.map(parseRoadmapLine), - - kpiDashboard: output.kpis.map((kpi) => ({ - metric: kpi, - current: '-', - target3Month: '-', - target12Month: '-', - })), - - screenshots: [], - }; -} +// SDK MarketingReportResponse ≈ MarketingReport — 별도 변환 함수 없이 useReport 에서 +// 직접 캐스팅해 사용. (구버전 ReportOutput 매핑 코드 제거) diff --git a/src/shared/api/generated/analysis/analysis.ts b/src/shared/api/generated/analysis/analysis.ts index b5f59ec..af47985 100644 --- a/src/shared/api/generated/analysis/analysis.ts +++ b/src/shared/api/generated/analysis/analysis.ts @@ -27,6 +27,9 @@ import type { AnalysisCreate, AnalysisStartResponse, AnalysisStatusResponse, + BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost, + FileListItem, + FileUploadResponse, HTTPValidationError } from '../../model'; @@ -128,6 +131,312 @@ export const useStartAnalysis = { + + + + + return `/api/analysis/${runId}/files` +} + +export const uploadAnalysisRunFile = async (runId: string, + bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost: BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost, options?: RequestInit): Promise => { + const formData = new FormData(); +formData.append(`file`, bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost.file) +if(bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost.file_type !== undefined) { + formData.append(`file_type`, bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost.file_type) + } + + return customFetcher(getUploadAnalysisRunFileUrl(runId), + { + ...options, + method: 'POST' + , + body: + formData, + } +);} + + + + +export const getUploadAnalysisRunFileMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{runId: string;data: BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{runId: string;data: BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost}, TContext> => { + +const mutationKey = ['uploadAnalysisRunFile']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {runId: string;data: BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost}> = (props) => { + const {runId,data} = props ?? {}; + + return uploadAnalysisRunFile(runId,data,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type UploadAnalysisRunFileMutationResult = NonNullable>> + export type UploadAnalysisRunFileMutationBody = BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost + export type UploadAnalysisRunFileMutationError = HTTPValidationError + + /** + * @summary Upload Analysis Run File + */ +export const useUploadAnalysisRunFile = (options?: { mutation?:UseMutationOptions>, TError,{runId: string;data: BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {runId: string;data: BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost}, + TContext + > => { + + const mutationOptions = getUploadAnalysisRunFileMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** + * @summary Get Analysis Run Files + */ +export type getAnalysisRunFilesResponse200 = { + data: FileListItem[] + status: 200 +} + +export type getAnalysisRunFilesResponse422 = { + data: HTTPValidationError + status: 422 +} + +export type getAnalysisRunFilesResponseSuccess = (getAnalysisRunFilesResponse200) & { + headers: Headers; +}; +export type getAnalysisRunFilesResponseError = (getAnalysisRunFilesResponse422) & { + headers: Headers; +}; + +export type getAnalysisRunFilesResponse = (getAnalysisRunFilesResponseSuccess | getAnalysisRunFilesResponseError) + +export const getGetAnalysisRunFilesUrl = (runId: string,) => { + + + + + return `/api/analysis/${runId}/files` +} + +export const getAnalysisRunFiles = async (runId: string, options?: RequestInit): Promise => { + + return customFetcher(getGetAnalysisRunFilesUrl(runId), + { + ...options, + method: 'GET' + + + } +);} + + + + + +export const getGetAnalysisRunFilesQueryKey = (runId?: string,) => { + return [ + `/api/analysis/${runId}/files` + ] as const; + } + + +export const getGetAnalysisRunFilesQueryOptions = >, TError = HTTPValidationError>(runId: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} +) => { + +const {query: queryOptions, request: requestOptions} = options ?? {}; + + const queryKey = queryOptions?.queryKey ?? getGetAnalysisRunFilesQueryKey(runId); + + + + const queryFn: QueryFunction>> = () => getAnalysisRunFiles(runId, requestOptions); + + + + + + return { queryKey, queryFn, enabled: !!(runId), staleTime: 60000, ...queryOptions} as UseQueryOptions>, TError, TData> & { queryKey: DataTag } +} + +export type GetAnalysisRunFilesQueryResult = NonNullable>> +export type GetAnalysisRunFilesQueryError = HTTPValidationError + + +export function useGetAnalysisRunFiles>, TError = HTTPValidationError>( + runId: string, options: { query:Partial>, TError, TData>> & Pick< + DefinedInitialDataOptions< + Awaited>, + TError, + Awaited> + > , 'initialData' + >, request?: SecondParameter} + , queryClient?: QueryClient + ): DefinedUseQueryResult & { queryKey: DataTag } +export function useGetAnalysisRunFiles>, TError = HTTPValidationError>( + runId: string, options?: { query?:Partial>, TError, TData>> & Pick< + UndefinedInitialDataOptions< + Awaited>, + TError, + Awaited> + > , 'initialData' + >, request?: SecondParameter} + , queryClient?: QueryClient + ): UseQueryResult & { queryKey: DataTag } +export function useGetAnalysisRunFiles>, TError = HTTPValidationError>( + runId: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} + , queryClient?: QueryClient + ): UseQueryResult & { queryKey: DataTag } +/** + * @summary Get Analysis Run Files + */ + +export function useGetAnalysisRunFiles>, TError = HTTPValidationError>( + runId: string, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} + , queryClient?: QueryClient + ): UseQueryResult & { queryKey: DataTag } { + + const queryOptions = getGetAnalysisRunFilesQueryOptions(runId,options) + + const query = useQuery(queryOptions, queryClient) as UseQueryResult & { queryKey: DataTag }; + + query.queryKey = queryOptions.queryKey ; + + return query; +} + + + + +/** + * @summary Delete Analysis Run File + */ +export type deleteAnalysisRunFileResponse204 = { + data: void + status: 204 +} + +export type deleteAnalysisRunFileResponse422 = { + data: HTTPValidationError + status: 422 +} + +export type deleteAnalysisRunFileResponseSuccess = (deleteAnalysisRunFileResponse204) & { + headers: Headers; +}; +export type deleteAnalysisRunFileResponseError = (deleteAnalysisRunFileResponse422) & { + headers: Headers; +}; + +export type deleteAnalysisRunFileResponse = (deleteAnalysisRunFileResponseSuccess | deleteAnalysisRunFileResponseError) + +export const getDeleteAnalysisRunFileUrl = (runId: string, + fileId: number,) => { + + + + + return `/api/analysis/${runId}/files/${fileId}` +} + +export const deleteAnalysisRunFile = async (runId: string, + fileId: number, options?: RequestInit): Promise => { + + return customFetcher(getDeleteAnalysisRunFileUrl(runId,fileId), + { + ...options, + method: 'DELETE' + + + } +);} + + + + +export const getDeleteAnalysisRunFileMutationOptions = (options?: { mutation?:UseMutationOptions>, TError,{runId: string;fileId: number}, TContext>, request?: SecondParameter} +): UseMutationOptions>, TError,{runId: string;fileId: number}, TContext> => { + +const mutationKey = ['deleteAnalysisRunFile']; +const {mutation: mutationOptions, request: requestOptions} = options ? + options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey ? + options + : {...options, mutation: {...options.mutation, mutationKey}} + : {mutation: { mutationKey, }, request: undefined}; + + + + + const mutationFn: MutationFunction>, {runId: string;fileId: number}> = (props) => { + const {runId,fileId} = props ?? {}; + + return deleteAnalysisRunFile(runId,fileId,requestOptions) + } + + + + + return { mutationFn, ...mutationOptions }} + + export type DeleteAnalysisRunFileMutationResult = NonNullable>> + + export type DeleteAnalysisRunFileMutationError = HTTPValidationError + + /** + * @summary Delete Analysis Run File + */ +export const useDeleteAnalysisRunFile = (options?: { mutation?:UseMutationOptions>, TError,{runId: string;fileId: number}, TContext>, request?: SecondParameter} + , queryClient?: QueryClient): UseMutationResult< + Awaited>, + TError, + {runId: string;fileId: number}, + TContext + > => { + + const mutationOptions = getDeleteAnalysisRunFileMutationOptions(options); + + return useMutation(mutationOptions, queryClient); + } + /** * @summary Get Analysis Status */ export type getAnalysisStatusResponse200 = { diff --git a/src/shared/api/generated/clinics/clinics.ts b/src/shared/api/generated/clinics/clinics.ts index 5b9fd76..90ac042 100644 --- a/src/shared/api/generated/clinics/clinics.ts +++ b/src/shared/api/generated/clinics/clinics.ts @@ -27,7 +27,9 @@ import type { ClinicCreate, ClinicCreateResponse, ClinicHistoryResponse, + ClinicListResponse, ClinicResponse, + GetClinicsParams, HTTPValidationError } from '../../model'; @@ -38,6 +40,132 @@ type SecondParameter unknown> = Parameters[1]; +/** + * @summary Get Clinics + */ +export type getClinicsResponse200 = { + data: ClinicListResponse + status: 200 +} + +export type getClinicsResponse422 = { + data: HTTPValidationError + status: 422 +} + +export type getClinicsResponseSuccess = (getClinicsResponse200) & { + headers: Headers; +}; +export type getClinicsResponseError = (getClinicsResponse422) & { + headers: Headers; +}; + +export type getClinicsResponse = (getClinicsResponseSuccess | getClinicsResponseError) + +export const getGetClinicsUrl = (params?: GetClinicsParams,) => { + const normalizedParams = new URLSearchParams(); + + Object.entries(params || {}).forEach(([key, value]) => { + + if (value !== undefined) { + normalizedParams.append(key, value === null ? 'null' : value.toString()) + } + }); + + const stringifiedParams = normalizedParams.toString(); + + return stringifiedParams.length > 0 ? `/api/clinics?${stringifiedParams}` : `/api/clinics` +} + +export const getClinics = async (params?: GetClinicsParams, options?: RequestInit): Promise => { + + return customFetcher(getGetClinicsUrl(params), + { + ...options, + method: 'GET' + + + } +);} + + + + + +export const getGetClinicsQueryKey = (params?: GetClinicsParams,) => { + return [ + `/api/clinics`, ...(params ? [params]: []) + ] as const; + } + + +export const getGetClinicsQueryOptions = >, TError = HTTPValidationError>(params?: GetClinicsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} +) => { + +const {query: queryOptions, request: requestOptions} = options ?? {}; + + const queryKey = queryOptions?.queryKey ?? getGetClinicsQueryKey(params); + + + + const queryFn: QueryFunction>> = () => getClinics(params, requestOptions); + + + + + + return { queryKey, queryFn, staleTime: 60000, ...queryOptions} as UseQueryOptions>, TError, TData> & { queryKey: DataTag } +} + +export type GetClinicsQueryResult = NonNullable>> +export type GetClinicsQueryError = HTTPValidationError + + +export function useGetClinics>, TError = HTTPValidationError>( + params: undefined | GetClinicsParams, options: { query:Partial>, TError, TData>> & Pick< + DefinedInitialDataOptions< + Awaited>, + TError, + Awaited> + > , 'initialData' + >, request?: SecondParameter} + , queryClient?: QueryClient + ): DefinedUseQueryResult & { queryKey: DataTag } +export function useGetClinics>, TError = HTTPValidationError>( + params?: GetClinicsParams, options?: { query?:Partial>, TError, TData>> & Pick< + UndefinedInitialDataOptions< + Awaited>, + TError, + Awaited> + > , 'initialData' + >, request?: SecondParameter} + , queryClient?: QueryClient + ): UseQueryResult & { queryKey: DataTag } +export function useGetClinics>, TError = HTTPValidationError>( + params?: GetClinicsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} + , queryClient?: QueryClient + ): UseQueryResult & { queryKey: DataTag } +/** + * @summary Get Clinics + */ + +export function useGetClinics>, TError = HTTPValidationError>( + params?: GetClinicsParams, options?: { query?:Partial>, TError, TData>>, request?: SecondParameter} + , queryClient?: QueryClient + ): UseQueryResult & { queryKey: DataTag } { + + const queryOptions = getGetClinicsQueryOptions(params,options) + + const query = useQuery(queryOptions, queryClient) as UseQueryResult & { queryKey: DataTag }; + + query.queryKey = queryOptions.queryKey ; + + return query; +} + + + + /** * @summary Create Clinic */ diff --git a/src/shared/api/generated/plans/plans.ts b/src/shared/api/generated/plan/plan.ts similarity index 97% rename from src/shared/api/generated/plans/plans.ts rename to src/shared/api/generated/plan/plan.ts index e31166f..f2b13f1 100644 --- a/src/shared/api/generated/plans/plans.ts +++ b/src/shared/api/generated/plan/plan.ts @@ -20,8 +20,8 @@ import type { } from '@tanstack/react-query'; import type { - GetPlan200, - HTTPValidationError + HTTPValidationError, + PlanApiResponse } from '../../model'; import { customFetcher } from '../../api'; @@ -35,7 +35,7 @@ type SecondParameter unknown> = Parameters[1]; * @summary Get Plan */ export type getPlanResponse200 = { - data: GetPlan200 + data: PlanApiResponse status: 200 } @@ -58,7 +58,7 @@ export const getGetPlanUrl = (runId: string,) => { - return `/api/plans/${runId}` + return `/api/plan/${runId}` } export const getPlan = async (runId: string, options?: RequestInit): Promise => { @@ -78,7 +78,7 @@ export const getPlan = async (runId: string, options?: RequestInit): Promise { return [ - `/api/plans/${runId}` + `/api/plan/${runId}` ] as const; } diff --git a/src/shared/api/generated/reports/reports.ts b/src/shared/api/generated/report/report.ts similarity index 96% rename from src/shared/api/generated/reports/reports.ts rename to src/shared/api/generated/report/report.ts index af1e3ee..73589f6 100644 --- a/src/shared/api/generated/reports/reports.ts +++ b/src/shared/api/generated/report/report.ts @@ -20,8 +20,8 @@ import type { } from '@tanstack/react-query'; import type { - GetReport200, - HTTPValidationError + HTTPValidationError, + MarketingReportResponse } from '../../model'; import { customFetcher } from '../../api'; @@ -35,7 +35,7 @@ type SecondParameter unknown> = Parameters[1]; * @summary Get Report */ export type getReportResponse200 = { - data: GetReport200 + data: MarketingReportResponse status: 200 } @@ -58,7 +58,7 @@ export const getGetReportUrl = (runId: string,) => { - return `/api/reports/${runId}` + return `/api/report/${runId}` } export const getReport = async (runId: string, options?: RequestInit): Promise => { @@ -78,7 +78,7 @@ export const getReport = async (runId: string, options?: RequestInit): Promise { return [ - `/api/reports/${runId}` + `/api/report/${runId}` ] as const; } diff --git a/src/shared/api/model/conversionStrategy.ts b/src/shared/api/model/additionalDomain.ts similarity index 59% rename from src/shared/api/model/conversionStrategy.ts rename to src/shared/api/model/additionalDomain.ts index 584280d..e99748b 100644 --- a/src/shared/api/model/conversionStrategy.ts +++ b/src/shared/api/model/additionalDomain.ts @@ -5,7 +5,7 @@ * OpenAPI spec version: 0.1.0 */ -export interface ConversionStrategy { - summary: string; - actions: string[]; +export interface AdditionalDomain { + domain: string; + purpose: string; } diff --git a/src/shared/api/model/annotationType.ts b/src/shared/api/model/annotationType.ts new file mode 100644 index 0000000..489688d --- /dev/null +++ b/src/shared/api/model/annotationType.ts @@ -0,0 +1,16 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type AnnotationType = typeof AnnotationType[keyof typeof AnnotationType]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const AnnotationType = { + highlight: 'highlight', + arrow: 'arrow', + text: 'text', +} as const; diff --git a/src/shared/api/model/getPlan200.ts b/src/shared/api/model/asIsToBeItem.ts similarity index 54% rename from src/shared/api/model/getPlan200.ts rename to src/shared/api/model/asIsToBeItem.ts index fb75f97..6e1b7ee 100644 --- a/src/shared/api/model/getPlan200.ts +++ b/src/shared/api/model/asIsToBeItem.ts @@ -4,6 +4,9 @@ * FastAPI * OpenAPI spec version: 0.1.0 */ -import type { PlanOutput } from './planOutput'; -export type GetPlan200 = PlanOutput | null; +export interface AsIsToBeItem { + area: string; + asIs: string; + toBe: string; +} diff --git a/src/shared/api/model/bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost.ts b/src/shared/api/model/bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost.ts new file mode 100644 index 0000000..5924056 --- /dev/null +++ b/src/shared/api/model/bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost.ts @@ -0,0 +1,14 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { FileType } from './fileType'; + +export interface BodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost { + /** 업로드할 파일 */ + file: string; + /** 파일 타입 (image/video/audio/document/file) */ + file_type?: FileType; +} diff --git a/src/shared/api/model/getReport200.ts b/src/shared/api/model/brandColors.ts similarity index 52% rename from src/shared/api/model/getReport200.ts rename to src/shared/api/model/brandColors.ts index 005c321..f1ce5b2 100644 --- a/src/shared/api/model/getReport200.ts +++ b/src/shared/api/model/brandColors.ts @@ -4,6 +4,9 @@ * FastAPI * OpenAPI spec version: 0.1.0 */ -import type { ReportOutput } from './reportOutput'; -export type GetReport200 = ReportOutput | null; +export interface BrandColors { + primary: string; + accent: string; + text: string; +} diff --git a/src/shared/api/model/brandGuide.ts b/src/shared/api/model/brandGuide.ts index b28a597..5a1cd93 100644 --- a/src/shared/api/model/brandGuide.ts +++ b/src/shared/api/model/brandGuide.ts @@ -9,7 +9,7 @@ import type { FontSpec } from './fontSpec'; import type { LogoUsageRule } from './logoUsageRule'; import type { ToneOfVoice } from './toneOfVoice'; import type { ChannelBrandingRule } from './channelBrandingRule'; -import type { BrandInconsistency } from './brandInconsistency'; +import type { BrandPlanInconsistency } from './brandPlanInconsistency'; export interface BrandGuide { colors: ColorSwatch[]; @@ -17,5 +17,5 @@ export interface BrandGuide { logoRules: LogoUsageRule[]; toneOfVoice: ToneOfVoice; channelBranding: ChannelBrandingRule[]; - brandInconsistencies: BrandInconsistency[]; + brandInconsistencies: BrandPlanInconsistency[]; } diff --git a/src/shared/api/model/brandPlanInconsistency.ts b/src/shared/api/model/brandPlanInconsistency.ts new file mode 100644 index 0000000..541f737 --- /dev/null +++ b/src/shared/api/model/brandPlanInconsistency.ts @@ -0,0 +1,14 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { BrandPlanInconsistencyValue } from './brandPlanInconsistencyValue'; + +export interface BrandPlanInconsistency { + field: string; + values: BrandPlanInconsistencyValue[]; + impact: string; + recommendation: string; +} diff --git a/src/shared/api/model/reportOutputYoutube.ts b/src/shared/api/model/brandPlanInconsistencyValue.ts similarity index 50% rename from src/shared/api/model/reportOutputYoutube.ts rename to src/shared/api/model/brandPlanInconsistencyValue.ts index b1dd5c3..15478f6 100644 --- a/src/shared/api/model/reportOutputYoutube.ts +++ b/src/shared/api/model/brandPlanInconsistencyValue.ts @@ -4,6 +4,9 @@ * FastAPI * OpenAPI spec version: 0.1.0 */ -import type { ChannelScore } from './channelScore'; -export type ReportOutputYoutube = ChannelScore | null; +export interface BrandPlanInconsistencyValue { + channel: string; + value: string; + isCorrect: boolean; +} diff --git a/src/shared/api/model/channelScore.ts b/src/shared/api/model/channelScore.ts index 924af16..8cd3275 100644 --- a/src/shared/api/model/channelScore.ts +++ b/src/shared/api/model/channelScore.ts @@ -4,10 +4,13 @@ * FastAPI * OpenAPI spec version: 0.1.0 */ +import type { Severity } from './severity'; export interface ChannelScore { + channel: string; + icon: string; score: number; - summary: string; - strengths: string[]; - weaknesses: string[]; + maxScore: number; + status: Severity; + headline: string; } diff --git a/src/shared/api/model/channelStatus.ts b/src/shared/api/model/channelStatus.ts new file mode 100644 index 0000000..5f8683b --- /dev/null +++ b/src/shared/api/model/channelStatus.ts @@ -0,0 +1,17 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ChannelStatus = typeof ChannelStatus[keyof typeof ChannelStatus]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const ChannelStatus = { + active: 'active', + inactive: 'inactive', + unknown: 'unknown', + not_found: 'not_found', +} as const; diff --git a/src/shared/api/model/clinicListItem.ts b/src/shared/api/model/clinicListItem.ts new file mode 100644 index 0000000..fee02b5 --- /dev/null +++ b/src/shared/api/model/clinicListItem.ts @@ -0,0 +1,20 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { ClinicListItemHospitalNameEn } from './clinicListItemHospitalNameEn'; +import type { ClinicListItemRoadAddress } from './clinicListItemRoadAddress'; +import type { ClinicListItemUrl } from './clinicListItemUrl'; + +export interface ClinicListItem { + hospital_id: string; + hospital_name: string; + hospital_name_en: ClinicListItemHospitalNameEn; + road_address: ClinicListItemRoadAddress; + url: ClinicListItemUrl; + status: string; + created_at: string; + updated_at: string; +} diff --git a/src/shared/api/model/clinicListItemHospitalNameEn.ts b/src/shared/api/model/clinicListItemHospitalNameEn.ts new file mode 100644 index 0000000..83953ae --- /dev/null +++ b/src/shared/api/model/clinicListItemHospitalNameEn.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ClinicListItemHospitalNameEn = string | null; diff --git a/src/shared/api/model/clinicListItemRoadAddress.ts b/src/shared/api/model/clinicListItemRoadAddress.ts new file mode 100644 index 0000000..ff9dd5d --- /dev/null +++ b/src/shared/api/model/clinicListItemRoadAddress.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ClinicListItemRoadAddress = string | null; diff --git a/src/shared/api/model/clinicListItemUrl.ts b/src/shared/api/model/clinicListItemUrl.ts new file mode 100644 index 0000000..d22f813 --- /dev/null +++ b/src/shared/api/model/clinicListItemUrl.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ClinicListItemUrl = string | null; diff --git a/src/shared/api/model/clinicListResponse.ts b/src/shared/api/model/clinicListResponse.ts new file mode 100644 index 0000000..2415476 --- /dev/null +++ b/src/shared/api/model/clinicListResponse.ts @@ -0,0 +1,12 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { ClinicListItem } from './clinicListItem'; + +export interface ClinicListResponse { + items: ClinicListItem[]; + total: number; +} diff --git a/src/shared/api/model/clinicSnapshot.ts b/src/shared/api/model/clinicSnapshot.ts new file mode 100644 index 0000000..2b0a32d --- /dev/null +++ b/src/shared/api/model/clinicSnapshot.ts @@ -0,0 +1,35 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { LeadDoctor } from './leadDoctor'; +import type { PriceRange } from './priceRange'; +import type { ClinicSnapshotLogoImages } from './clinicSnapshotLogoImages'; +import type { ClinicSnapshotBrandColors } from './clinicSnapshotBrandColors'; +import type { ClinicSnapshotSource } from './clinicSnapshotSource'; +import type { ClinicSnapshotRegistryData } from './clinicSnapshotRegistryData'; + +export interface ClinicSnapshot { + name: string; + nameEn: string; + established: string; + yearsInBusiness: number; + staffCount: number; + leadDoctor: LeadDoctor; + overallRating: number; + totalReviews: number; + priceRange: PriceRange; + certifications: string[]; + mediaAppearances: string[]; + medicalTourism: string[]; + location: string; + nearestStation: string; + phone: string; + domain: string; + logoImages?: ClinicSnapshotLogoImages; + brandColors?: ClinicSnapshotBrandColors; + source?: ClinicSnapshotSource; + registryData?: ClinicSnapshotRegistryData; +} diff --git a/src/shared/api/model/reportOutputFacebook.ts b/src/shared/api/model/clinicSnapshotBrandColors.ts similarity index 50% rename from src/shared/api/model/reportOutputFacebook.ts rename to src/shared/api/model/clinicSnapshotBrandColors.ts index 322910e..072074f 100644 --- a/src/shared/api/model/reportOutputFacebook.ts +++ b/src/shared/api/model/clinicSnapshotBrandColors.ts @@ -4,6 +4,6 @@ * FastAPI * OpenAPI spec version: 0.1.0 */ -import type { ChannelScore } from './channelScore'; +import type { BrandColors } from './brandColors'; -export type ReportOutputFacebook = ChannelScore | null; +export type ClinicSnapshotBrandColors = BrandColors | null; diff --git a/src/shared/api/model/clinicSnapshotLogoImages.ts b/src/shared/api/model/clinicSnapshotLogoImages.ts new file mode 100644 index 0000000..a3350f2 --- /dev/null +++ b/src/shared/api/model/clinicSnapshotLogoImages.ts @@ -0,0 +1,9 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { LogoImages } from './logoImages'; + +export type ClinicSnapshotLogoImages = LogoImages | null; diff --git a/src/shared/api/model/clinicSnapshotRegistryData.ts b/src/shared/api/model/clinicSnapshotRegistryData.ts new file mode 100644 index 0000000..70955f6 --- /dev/null +++ b/src/shared/api/model/clinicSnapshotRegistryData.ts @@ -0,0 +1,9 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { RegistryData } from './registryData'; + +export type ClinicSnapshotRegistryData = RegistryData | null; diff --git a/src/shared/api/model/clinicSnapshotSource.ts b/src/shared/api/model/clinicSnapshotSource.ts new file mode 100644 index 0000000..08957b4 --- /dev/null +++ b/src/shared/api/model/clinicSnapshotSource.ts @@ -0,0 +1,9 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { DataSource } from './dataSource'; + +export type ClinicSnapshotSource = DataSource | null; diff --git a/src/shared/api/model/contentPillar.ts b/src/shared/api/model/contentPillar.ts index c3bc6f4..9132c02 100644 --- a/src/shared/api/model/contentPillar.ts +++ b/src/shared/api/model/contentPillar.ts @@ -8,7 +8,7 @@ export interface ContentPillar { title: string; description: string; - relatedUSP: string; + relatedUsp: string; exampleTopics: string[]; color: string; } diff --git a/src/shared/api/model/dataSource.ts b/src/shared/api/model/dataSource.ts new file mode 100644 index 0000000..e0a38bd --- /dev/null +++ b/src/shared/api/model/dataSource.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type DataSource = typeof DataSource[keyof typeof DataSource]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const DataSource = { + registry: 'registry', + scrape: 'scrape', +} as const; diff --git a/src/shared/api/model/diagnosisItem.ts b/src/shared/api/model/diagnosisItem.ts new file mode 100644 index 0000000..c263902 --- /dev/null +++ b/src/shared/api/model/diagnosisItem.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { Severity } from './severity'; +import type { DiagnosisItemEvidenceIds } from './diagnosisItemEvidenceIds'; + +export interface DiagnosisItem { + category: string; + detail: string; + severity: Severity; + evidenceIds?: DiagnosisItemEvidenceIds; +} diff --git a/src/shared/api/model/diagnosisItemEvidenceIds.ts b/src/shared/api/model/diagnosisItemEvidenceIds.ts new file mode 100644 index 0000000..d59806b --- /dev/null +++ b/src/shared/api/model/diagnosisItemEvidenceIds.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type DiagnosisItemEvidenceIds = string[] | null; diff --git a/src/shared/api/model/estimatedRevenue.ts b/src/shared/api/model/estimatedRevenue.ts new file mode 100644 index 0000000..f31ce81 --- /dev/null +++ b/src/shared/api/model/estimatedRevenue.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface EstimatedRevenue { + min: number; + max: number; +} diff --git a/src/shared/api/model/facebookAudit.ts b/src/shared/api/model/facebookAudit.ts new file mode 100644 index 0000000..0e60b46 --- /dev/null +++ b/src/shared/api/model/facebookAudit.ts @@ -0,0 +1,16 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { FacebookPage } from './facebookPage'; +import type { DiagnosisItem } from './diagnosisItem'; +import type { BrandInconsistency } from './brandInconsistency'; + +export interface FacebookAudit { + pages: FacebookPage[]; + diagnosis: DiagnosisItem[]; + brandInconsistencies: BrandInconsistency[]; + consolidationRecommendation: string; +} diff --git a/src/shared/api/model/facebookPage.ts b/src/shared/api/model/facebookPage.ts new file mode 100644 index 0000000..08df9f4 --- /dev/null +++ b/src/shared/api/model/facebookPage.ts @@ -0,0 +1,31 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { Language } from './language'; +import type { FacebookPagePostFrequency } from './facebookPagePostFrequency'; +import type { FacebookPageTopContentType } from './facebookPageTopContentType'; +import type { FacebookPageEngagement } from './facebookPageEngagement'; + +export interface FacebookPage { + url: string; + pageName: string; + language: Language; + label: string; + followers: number; + following: number; + category: string; + bio: string; + logo: string; + logoDescription: string; + link: string; + linkedDomain: string; + reviews: number; + recentPostAge: string; + hasWhatsapp: boolean; + postFrequency?: FacebookPagePostFrequency; + topContentType?: FacebookPageTopContentType; + engagement?: FacebookPageEngagement; +} diff --git a/src/shared/api/model/facebookPageEngagement.ts b/src/shared/api/model/facebookPageEngagement.ts new file mode 100644 index 0000000..afeda68 --- /dev/null +++ b/src/shared/api/model/facebookPageEngagement.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type FacebookPageEngagement = string | null; diff --git a/src/shared/api/model/facebookPagePostFrequency.ts b/src/shared/api/model/facebookPagePostFrequency.ts new file mode 100644 index 0000000..1e5d9d5 --- /dev/null +++ b/src/shared/api/model/facebookPagePostFrequency.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type FacebookPagePostFrequency = string | null; diff --git a/src/shared/api/model/facebookPageTopContentType.ts b/src/shared/api/model/facebookPageTopContentType.ts new file mode 100644 index 0000000..5851807 --- /dev/null +++ b/src/shared/api/model/facebookPageTopContentType.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type FacebookPageTopContentType = string | null; diff --git a/src/shared/api/model/fileListItem.ts b/src/shared/api/model/fileListItem.ts new file mode 100644 index 0000000..c89d759 --- /dev/null +++ b/src/shared/api/model/fileListItem.ts @@ -0,0 +1,17 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { FileType } from './fileType'; +import type { FileListItemSizeBytes } from './fileListItemSizeBytes'; + +export interface FileListItem { + id: number; + file_type: FileType; + file_name: string; + file_url: string; + size_bytes?: FileListItemSizeBytes; + created_at: string; +} diff --git a/src/shared/api/model/fileListItemSizeBytes.ts b/src/shared/api/model/fileListItemSizeBytes.ts new file mode 100644 index 0000000..90c63c9 --- /dev/null +++ b/src/shared/api/model/fileListItemSizeBytes.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type FileListItemSizeBytes = number | null; diff --git a/src/shared/api/model/fileType.ts b/src/shared/api/model/fileType.ts new file mode 100644 index 0000000..dd6807d --- /dev/null +++ b/src/shared/api/model/fileType.ts @@ -0,0 +1,18 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type FileType = typeof FileType[keyof typeof FileType]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const FileType = { + image: 'image', + video: 'video', + audio: 'audio', + document: 'document', + file: 'file', +} as const; diff --git a/src/shared/api/model/fileUploadResponse.ts b/src/shared/api/model/fileUploadResponse.ts new file mode 100644 index 0000000..ac2533e --- /dev/null +++ b/src/shared/api/model/fileUploadResponse.ts @@ -0,0 +1,17 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { FileType } from './fileType'; +import type { FileUploadResponseSizeBytes } from './fileUploadResponseSizeBytes'; + +export interface FileUploadResponse { + id: number; + analysis_run_id: string; + file_type: FileType; + file_name: string; + file_url: string; + size_bytes?: FileUploadResponseSizeBytes; +} diff --git a/src/shared/api/model/fileUploadResponseSizeBytes.ts b/src/shared/api/model/fileUploadResponseSizeBytes.ts new file mode 100644 index 0000000..d1078a3 --- /dev/null +++ b/src/shared/api/model/fileUploadResponseSizeBytes.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type FileUploadResponseSizeBytes = number | null; diff --git a/src/shared/api/model/getClinicsParams.ts b/src/shared/api/model/getClinicsParams.ts new file mode 100644 index 0000000..b8c3608 --- /dev/null +++ b/src/shared/api/model/getClinicsParams.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type GetClinicsParams = { +limit?: number; +offset?: number; +}; diff --git a/src/shared/api/model/index.ts b/src/shared/api/model/index.ts index 62d19a4..12185b3 100644 --- a/src/shared/api/model/index.ts +++ b/src/shared/api/model/index.ts @@ -5,6 +5,7 @@ * OpenAPI spec version: 0.1.0 */ +export * from './additionalDomain'; export * from './analysisCreate'; export * from './analysisOptions'; export * from './analysisStartResponse'; @@ -12,14 +13,20 @@ export * from './analysisStatus'; export * from './analysisStatusResponse'; export * from './analysisStatusResponseChannelErrors'; export * from './analysisStatusResponseCompletedAt'; +export * from './annotationType'; +export * from './asIsToBeItem'; export * from './assetCard'; export * from './assetCardSource'; export * from './assetCardStatus'; export * from './assetCardType'; export * from './assetCollectionData'; +export * from './bodyUploadAnalysisRunFileApiAnalysisRunIdFilesPost'; +export * from './brandColors'; export * from './brandGuide'; export * from './brandInconsistency'; export * from './brandInconsistencyValue'; +export * from './brandPlanInconsistency'; +export * from './brandPlanInconsistencyValue'; export * from './calendarData'; export * from './calendarEntry'; export * from './calendarEntryAiPromptSeed'; @@ -33,6 +40,7 @@ export * from './calendarWeek'; export * from './channelBrandingRule'; export * from './channelBrandingRuleCurrentStatus'; export * from './channelScore'; +export * from './channelStatus'; export * from './channelStrategyCard'; export * from './channelStrategyCardCustomerJourneyStage'; export * from './channelStrategyCardPriority'; @@ -46,43 +54,111 @@ export * from './clinicCreate'; export * from './clinicCreateResponse'; export * from './clinicHistoryResponse'; export * from './clinicHistoryResponseMetricsTimeseries'; +export * from './clinicListItem'; +export * from './clinicListItemHospitalNameEn'; +export * from './clinicListItemRoadAddress'; +export * from './clinicListItemUrl'; +export * from './clinicListResponse'; export * from './clinicResponse'; export * from './clinicResponseHospitalNameEn'; export * from './clinicResponseRawData'; export * from './clinicResponseRawDataAnyOf'; export * from './clinicResponseRoadAddress'; export * from './clinicResponseUrl'; +export * from './clinicSnapshot'; +export * from './clinicSnapshotBrandColors'; +export * from './clinicSnapshotLogoImages'; +export * from './clinicSnapshotRegistryData'; +export * from './clinicSnapshotSource'; export * from './colorSwatch'; export * from './contentCountSummary'; export * from './contentCountSummaryType'; export * from './contentPillar'; export * from './contentStrategyData'; export * from './contentTypeRow'; -export * from './conversionStrategy'; +export * from './dataSource'; +export * from './diagnosisItem'; +export * from './diagnosisItemEvidenceIds'; +export * from './estimatedRevenue'; +export * from './facebookAudit'; +export * from './facebookPage'; +export * from './facebookPageEngagement'; +export * from './facebookPagePostFrequency'; +export * from './facebookPageTopContentType'; +export * from './fileListItem'; +export * from './fileListItemSizeBytes'; +export * from './fileType'; +export * from './fileUploadResponse'; +export * from './fileUploadResponseSizeBytes'; export * from './fontSpec'; -export * from './getPlan200'; -export * from './getReport200'; +export * from './getClinicsParams'; export * from './hTTPValidationError'; +export * from './instagramAccount'; +export * from './instagramAudit'; +export * from './kPIMetric'; +export * from './language'; +export * from './leadDoctor'; +export * from './linkedUrl'; +export * from './logoImages'; +export * from './logoImagesCircle'; +export * from './logoImagesHorizontal'; +export * from './logoImagesKorean'; export * from './logoUsageRule'; -export * from './planOutput'; -export * from './planOutputRepurposingProposals'; -export * from './reportOutput'; -export * from './reportOutputFacebook'; -export * from './reportOutputGangnamUnni'; -export * from './reportOutputInstagram'; -export * from './reportOutputNaverBlog'; -export * from './reportOutputYoutube'; +export * from './marketingReportResponse'; +export * from './marketingReportResponseClinicName'; +export * from './marketingReportResponseClinicNameEn'; +export * from './marketingReportResponseScreenshots'; +export * from './newChannelProposal'; +export * from './otherChannel'; +export * from './otherChannelUrl'; +export * from './planApiResponse'; +export * from './planApiResponseClinicName'; +export * from './planApiResponseClinicNameEn'; +export * from './planApiResponseRepurposingProposals'; +export * from './platformStrategy'; +export * from './priceRange'; +export * from './registryData'; +export * from './registryDataBranches'; +export * from './registryDataBrandGroup'; +export * from './registryDataDistrict'; +export * from './registryDataGangnamUnniUrl'; +export * from './registryDataGoogleMapsUrl'; +export * from './registryDataNaverPlaceUrl'; +export * from './registryDataWebsiteEn'; export * from './repurposingOutput'; export * from './repurposingProposalItem'; export * from './repurposingProposalItemEstimatedEffort'; export * from './repurposingProposalItemPriority'; +export * from './roadmapMonth'; +export * from './roadmapTask'; export * from './runSummary'; export * from './runSummaryCompletedAt'; export * from './runSummaryOverallScore'; +export * from './screenshotAnnotation'; +export * from './screenshotAnnotationColor'; +export * from './screenshotAnnotationHeight'; +export * from './screenshotAnnotationLabel'; +export * from './screenshotAnnotationWidth'; +export * from './screenshotEvidence'; +export * from './screenshotEvidenceAnnotations'; +export * from './screenshotEvidenceSourceUrl'; +export * from './severity'; +export * from './snsLink'; +export * from './strategyDetail'; export * from './toneOfVoice'; +export * from './topVideo'; +export * from './topVideoDuration'; +export * from './trackingPixel'; +export * from './trackingPixelDetails'; +export * from './transformationProposal'; export * from './validationError'; export * from './validationErrorCtx'; export * from './validationErrorLocItem'; +export * from './videoType'; +export * from './websiteAudit'; +export * from './websiteAuditSnsLinksDetail'; +export * from './weeklyViewGrowth'; export * from './workflowStep'; +export * from './youTubeAudit'; export * from './youTubeRepurposeItem'; export * from './youTubeRepurposeItemType'; \ No newline at end of file diff --git a/src/shared/api/model/instagramAccount.ts b/src/shared/api/model/instagramAccount.ts new file mode 100644 index 0000000..44cf3c4 --- /dev/null +++ b/src/shared/api/model/instagramAccount.ts @@ -0,0 +1,23 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { Language } from './language'; + +export interface InstagramAccount { + handle: string; + language: Language; + label: string; + posts: number; + followers: number; + following: number; + category: string; + profileLink: string; + highlights: string[]; + reelsCount: number; + contentFormat: string; + profilePhoto: string; + bio: string; +} diff --git a/src/shared/api/model/instagramAudit.ts b/src/shared/api/model/instagramAudit.ts new file mode 100644 index 0000000..863d71e --- /dev/null +++ b/src/shared/api/model/instagramAudit.ts @@ -0,0 +1,13 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { InstagramAccount } from './instagramAccount'; +import type { DiagnosisItem } from './diagnosisItem'; + +export interface InstagramAudit { + accounts: InstagramAccount[]; + diagnosis: DiagnosisItem[]; +} diff --git a/src/shared/api/model/kPIMetric.ts b/src/shared/api/model/kPIMetric.ts new file mode 100644 index 0000000..41bc7d1 --- /dev/null +++ b/src/shared/api/model/kPIMetric.ts @@ -0,0 +1,13 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface KPIMetric { + metric: string; + current: string; + target3Month: string; + target12Month: string; +} diff --git a/src/shared/api/model/language.ts b/src/shared/api/model/language.ts new file mode 100644 index 0000000..7cd3854 --- /dev/null +++ b/src/shared/api/model/language.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type Language = typeof Language[keyof typeof Language]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const Language = { + KR: 'KR', + EN: 'EN', +} as const; diff --git a/src/shared/api/model/leadDoctor.ts b/src/shared/api/model/leadDoctor.ts new file mode 100644 index 0000000..d770b42 --- /dev/null +++ b/src/shared/api/model/leadDoctor.ts @@ -0,0 +1,13 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface LeadDoctor { + name: string; + credentials: string; + rating: number; + reviewCount: number; +} diff --git a/src/shared/api/model/linkedUrl.ts b/src/shared/api/model/linkedUrl.ts new file mode 100644 index 0000000..3e4f841 --- /dev/null +++ b/src/shared/api/model/linkedUrl.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface LinkedUrl { + label: string; + url: string; +} diff --git a/src/shared/api/model/logoImages.ts b/src/shared/api/model/logoImages.ts new file mode 100644 index 0000000..980ce7b --- /dev/null +++ b/src/shared/api/model/logoImages.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { LogoImagesCircle } from './logoImagesCircle'; +import type { LogoImagesHorizontal } from './logoImagesHorizontal'; +import type { LogoImagesKorean } from './logoImagesKorean'; + +export interface LogoImages { + circle?: LogoImagesCircle; + horizontal?: LogoImagesHorizontal; + korean?: LogoImagesKorean; +} diff --git a/src/shared/api/model/logoImagesCircle.ts b/src/shared/api/model/logoImagesCircle.ts new file mode 100644 index 0000000..7e0979a --- /dev/null +++ b/src/shared/api/model/logoImagesCircle.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type LogoImagesCircle = string | null; diff --git a/src/shared/api/model/logoImagesHorizontal.ts b/src/shared/api/model/logoImagesHorizontal.ts new file mode 100644 index 0000000..96a064a --- /dev/null +++ b/src/shared/api/model/logoImagesHorizontal.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type LogoImagesHorizontal = string | null; diff --git a/src/shared/api/model/logoImagesKorean.ts b/src/shared/api/model/logoImagesKorean.ts new file mode 100644 index 0000000..5231f79 --- /dev/null +++ b/src/shared/api/model/logoImagesKorean.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type LogoImagesKorean = string | null; diff --git a/src/shared/api/model/marketingReportResponse.ts b/src/shared/api/model/marketingReportResponse.ts new file mode 100644 index 0000000..cdc4f27 --- /dev/null +++ b/src/shared/api/model/marketingReportResponse.ts @@ -0,0 +1,41 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { MarketingReportResponseClinicName } from './marketingReportResponseClinicName'; +import type { MarketingReportResponseClinicNameEn } from './marketingReportResponseClinicNameEn'; +import type { ClinicSnapshot } from './clinicSnapshot'; +import type { ChannelScore } from './channelScore'; +import type { YouTubeAudit } from './youTubeAudit'; +import type { InstagramAudit } from './instagramAudit'; +import type { FacebookAudit } from './facebookAudit'; +import type { OtherChannel } from './otherChannel'; +import type { WebsiteAudit } from './websiteAudit'; +import type { DiagnosisItem } from './diagnosisItem'; +import type { TransformationProposal } from './transformationProposal'; +import type { RoadmapMonth } from './roadmapMonth'; +import type { KPIMetric } from './kPIMetric'; +import type { MarketingReportResponseScreenshots } from './marketingReportResponseScreenshots'; + +export interface MarketingReportResponse { + id: string; + clinicName?: MarketingReportResponseClinicName; + clinicNameEn?: MarketingReportResponseClinicNameEn; + createdAt: string; + targetUrl: string; + overallScore: number; + clinicSnapshot: ClinicSnapshot; + channelScores: ChannelScore[]; + youtubeAudit: YouTubeAudit; + instagramAudit: InstagramAudit; + facebookAudit: FacebookAudit; + otherChannels: OtherChannel[]; + websiteAudit: WebsiteAudit; + problemDiagnosis: DiagnosisItem[]; + transformation: TransformationProposal; + roadmap: RoadmapMonth[]; + kpiDashboard: KPIMetric[]; + screenshots?: MarketingReportResponseScreenshots; +} diff --git a/src/shared/api/model/marketingReportResponseClinicName.ts b/src/shared/api/model/marketingReportResponseClinicName.ts new file mode 100644 index 0000000..f93426d --- /dev/null +++ b/src/shared/api/model/marketingReportResponseClinicName.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type MarketingReportResponseClinicName = string | null; diff --git a/src/shared/api/model/marketingReportResponseClinicNameEn.ts b/src/shared/api/model/marketingReportResponseClinicNameEn.ts new file mode 100644 index 0000000..685e2e1 --- /dev/null +++ b/src/shared/api/model/marketingReportResponseClinicNameEn.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type MarketingReportResponseClinicNameEn = string | null; diff --git a/src/shared/api/model/marketingReportResponseScreenshots.ts b/src/shared/api/model/marketingReportResponseScreenshots.ts new file mode 100644 index 0000000..5a985c2 --- /dev/null +++ b/src/shared/api/model/marketingReportResponseScreenshots.ts @@ -0,0 +1,9 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { ScreenshotEvidence } from './screenshotEvidence'; + +export type MarketingReportResponseScreenshots = ScreenshotEvidence[] | null; diff --git a/src/shared/api/model/newChannelProposal.ts b/src/shared/api/model/newChannelProposal.ts new file mode 100644 index 0000000..92e5402 --- /dev/null +++ b/src/shared/api/model/newChannelProposal.ts @@ -0,0 +1,12 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface NewChannelProposal { + channel: string; + priority: string; + rationale: string; +} diff --git a/src/shared/api/model/otherChannel.ts b/src/shared/api/model/otherChannel.ts new file mode 100644 index 0000000..9bd6b4d --- /dev/null +++ b/src/shared/api/model/otherChannel.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { ChannelStatus } from './channelStatus'; +import type { OtherChannelUrl } from './otherChannelUrl'; + +export interface OtherChannel { + name: string; + status: ChannelStatus; + details: string; + url?: OtherChannelUrl; +} diff --git a/src/shared/api/model/otherChannelUrl.ts b/src/shared/api/model/otherChannelUrl.ts new file mode 100644 index 0000000..21ec10e --- /dev/null +++ b/src/shared/api/model/otherChannelUrl.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type OtherChannelUrl = string | null; diff --git a/src/shared/api/model/planOutput.ts b/src/shared/api/model/planApiResponse.ts similarity index 54% rename from src/shared/api/model/planOutput.ts rename to src/shared/api/model/planApiResponse.ts index 449c771..7b3c40a 100644 --- a/src/shared/api/model/planOutput.ts +++ b/src/shared/api/model/planApiResponse.ts @@ -4,18 +4,25 @@ * FastAPI * OpenAPI spec version: 0.1.0 */ +import type { PlanApiResponseClinicName } from './planApiResponseClinicName'; +import type { PlanApiResponseClinicNameEn } from './planApiResponseClinicNameEn'; import type { BrandGuide } from './brandGuide'; import type { ChannelStrategyCard } from './channelStrategyCard'; import type { ContentStrategyData } from './contentStrategyData'; import type { CalendarData } from './calendarData'; import type { AssetCollectionData } from './assetCollectionData'; -import type { PlanOutputRepurposingProposals } from './planOutputRepurposingProposals'; +import type { PlanApiResponseRepurposingProposals } from './planApiResponseRepurposingProposals'; -export interface PlanOutput { +export interface PlanApiResponse { + id: string; + clinicName?: PlanApiResponseClinicName; + clinicNameEn?: PlanApiResponseClinicNameEn; + createdAt: string; + targetUrl: string; brandGuide: BrandGuide; channelStrategies: ChannelStrategyCard[]; contentStrategy: ContentStrategyData; calendar: CalendarData; assetCollection: AssetCollectionData; - repurposingProposals?: PlanOutputRepurposingProposals; + repurposingProposals?: PlanApiResponseRepurposingProposals; } diff --git a/src/shared/api/model/planApiResponseClinicName.ts b/src/shared/api/model/planApiResponseClinicName.ts new file mode 100644 index 0000000..1e5e295 --- /dev/null +++ b/src/shared/api/model/planApiResponseClinicName.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type PlanApiResponseClinicName = string | null; diff --git a/src/shared/api/model/planApiResponseClinicNameEn.ts b/src/shared/api/model/planApiResponseClinicNameEn.ts new file mode 100644 index 0000000..e772c88 --- /dev/null +++ b/src/shared/api/model/planApiResponseClinicNameEn.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type PlanApiResponseClinicNameEn = string | null; diff --git a/src/shared/api/model/planOutputRepurposingProposals.ts b/src/shared/api/model/planApiResponseRepurposingProposals.ts similarity index 68% rename from src/shared/api/model/planOutputRepurposingProposals.ts rename to src/shared/api/model/planApiResponseRepurposingProposals.ts index 53e6ac8..038f3ca 100644 --- a/src/shared/api/model/planOutputRepurposingProposals.ts +++ b/src/shared/api/model/planApiResponseRepurposingProposals.ts @@ -6,4 +6,4 @@ */ import type { RepurposingProposalItem } from './repurposingProposalItem'; -export type PlanOutputRepurposingProposals = RepurposingProposalItem[] | null; +export type PlanApiResponseRepurposingProposals = RepurposingProposalItem[] | null; diff --git a/src/shared/api/model/platformStrategy.ts b/src/shared/api/model/platformStrategy.ts new file mode 100644 index 0000000..f0dfc09 --- /dev/null +++ b/src/shared/api/model/platformStrategy.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { StrategyDetail } from './strategyDetail'; + +export interface PlatformStrategy { + platform: string; + icon: string; + currentMetric: string; + targetMetric: string; + strategies: StrategyDetail[]; +} diff --git a/src/shared/api/model/priceRange.ts b/src/shared/api/model/priceRange.ts new file mode 100644 index 0000000..28100c0 --- /dev/null +++ b/src/shared/api/model/priceRange.ts @@ -0,0 +1,12 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface PriceRange { + min: string; + max: string; + currency: string; +} diff --git a/src/shared/api/model/registryData.ts b/src/shared/api/model/registryData.ts new file mode 100644 index 0000000..87da8be --- /dev/null +++ b/src/shared/api/model/registryData.ts @@ -0,0 +1,23 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { RegistryDataDistrict } from './registryDataDistrict'; +import type { RegistryDataBranches } from './registryDataBranches'; +import type { RegistryDataBrandGroup } from './registryDataBrandGroup'; +import type { RegistryDataWebsiteEn } from './registryDataWebsiteEn'; +import type { RegistryDataNaverPlaceUrl } from './registryDataNaverPlaceUrl'; +import type { RegistryDataGangnamUnniUrl } from './registryDataGangnamUnniUrl'; +import type { RegistryDataGoogleMapsUrl } from './registryDataGoogleMapsUrl'; + +export interface RegistryData { + district?: RegistryDataDistrict; + branches?: RegistryDataBranches; + brandGroup?: RegistryDataBrandGroup; + websiteEn?: RegistryDataWebsiteEn; + naverPlaceUrl?: RegistryDataNaverPlaceUrl; + gangnamUnniUrl?: RegistryDataGangnamUnniUrl; + googleMapsUrl?: RegistryDataGoogleMapsUrl; +} diff --git a/src/shared/api/model/registryDataBranches.ts b/src/shared/api/model/registryDataBranches.ts new file mode 100644 index 0000000..f8552bf --- /dev/null +++ b/src/shared/api/model/registryDataBranches.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataBranches = string | null; diff --git a/src/shared/api/model/registryDataBrandGroup.ts b/src/shared/api/model/registryDataBrandGroup.ts new file mode 100644 index 0000000..1716ebf --- /dev/null +++ b/src/shared/api/model/registryDataBrandGroup.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataBrandGroup = string | null; diff --git a/src/shared/api/model/registryDataDistrict.ts b/src/shared/api/model/registryDataDistrict.ts new file mode 100644 index 0000000..6f387d7 --- /dev/null +++ b/src/shared/api/model/registryDataDistrict.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataDistrict = string | null; diff --git a/src/shared/api/model/registryDataGangnamUnniUrl.ts b/src/shared/api/model/registryDataGangnamUnniUrl.ts new file mode 100644 index 0000000..64aa11d --- /dev/null +++ b/src/shared/api/model/registryDataGangnamUnniUrl.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataGangnamUnniUrl = string | null; diff --git a/src/shared/api/model/registryDataGoogleMapsUrl.ts b/src/shared/api/model/registryDataGoogleMapsUrl.ts new file mode 100644 index 0000000..11eac8e --- /dev/null +++ b/src/shared/api/model/registryDataGoogleMapsUrl.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataGoogleMapsUrl = string | null; diff --git a/src/shared/api/model/registryDataNaverPlaceUrl.ts b/src/shared/api/model/registryDataNaverPlaceUrl.ts new file mode 100644 index 0000000..5514f74 --- /dev/null +++ b/src/shared/api/model/registryDataNaverPlaceUrl.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataNaverPlaceUrl = string | null; diff --git a/src/shared/api/model/registryDataWebsiteEn.ts b/src/shared/api/model/registryDataWebsiteEn.ts new file mode 100644 index 0000000..5aaa638 --- /dev/null +++ b/src/shared/api/model/registryDataWebsiteEn.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type RegistryDataWebsiteEn = string | null; diff --git a/src/shared/api/model/reportOutput.ts b/src/shared/api/model/reportOutput.ts deleted file mode 100644 index 6a05a44..0000000 --- a/src/shared/api/model/reportOutput.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Generated by orval v7.21.0 🍺 - * Do not edit manually. - * FastAPI - * OpenAPI spec version: 0.1.0 - */ -import type { ReportOutputInstagram } from './reportOutputInstagram'; -import type { ReportOutputFacebook } from './reportOutputFacebook'; -import type { ReportOutputNaverBlog } from './reportOutputNaverBlog'; -import type { ReportOutputYoutube } from './reportOutputYoutube'; -import type { ReportOutputGangnamUnni } from './reportOutputGangnamUnni'; -import type { ConversionStrategy } from './conversionStrategy'; - -export interface ReportOutput { - overall_score: number; - instagram?: ReportOutputInstagram; - facebook?: ReportOutputFacebook; - naver_blog?: ReportOutputNaverBlog; - youtube?: ReportOutputYoutube; - gangnam_unni?: ReportOutputGangnamUnni; - conversion_strategy: ConversionStrategy; - roadmap: string[]; - kpis: string[]; -} diff --git a/src/shared/api/model/reportOutputGangnamUnni.ts b/src/shared/api/model/reportOutputGangnamUnni.ts deleted file mode 100644 index 1105de4..0000000 --- a/src/shared/api/model/reportOutputGangnamUnni.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Generated by orval v7.21.0 🍺 - * Do not edit manually. - * FastAPI - * OpenAPI spec version: 0.1.0 - */ -import type { ChannelScore } from './channelScore'; - -export type ReportOutputGangnamUnni = ChannelScore | null; diff --git a/src/shared/api/model/reportOutputInstagram.ts b/src/shared/api/model/reportOutputInstagram.ts deleted file mode 100644 index fe0295b..0000000 --- a/src/shared/api/model/reportOutputInstagram.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Generated by orval v7.21.0 🍺 - * Do not edit manually. - * FastAPI - * OpenAPI spec version: 0.1.0 - */ -import type { ChannelScore } from './channelScore'; - -export type ReportOutputInstagram = ChannelScore | null; diff --git a/src/shared/api/model/reportOutputNaverBlog.ts b/src/shared/api/model/reportOutputNaverBlog.ts deleted file mode 100644 index 85e8429..0000000 --- a/src/shared/api/model/reportOutputNaverBlog.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Generated by orval v7.21.0 🍺 - * Do not edit manually. - * FastAPI - * OpenAPI spec version: 0.1.0 - */ -import type { ChannelScore } from './channelScore'; - -export type ReportOutputNaverBlog = ChannelScore | null; diff --git a/src/shared/api/model/roadmapMonth.ts b/src/shared/api/model/roadmapMonth.ts new file mode 100644 index 0000000..06f35b8 --- /dev/null +++ b/src/shared/api/model/roadmapMonth.ts @@ -0,0 +1,14 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { RoadmapTask } from './roadmapTask'; + +export interface RoadmapMonth { + month: number; + title: string; + subtitle: string; + tasks: RoadmapTask[]; +} diff --git a/src/shared/api/model/roadmapTask.ts b/src/shared/api/model/roadmapTask.ts new file mode 100644 index 0000000..a44519c --- /dev/null +++ b/src/shared/api/model/roadmapTask.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface RoadmapTask { + task: string; + completed: boolean; +} diff --git a/src/shared/api/model/screenshotAnnotation.ts b/src/shared/api/model/screenshotAnnotation.ts new file mode 100644 index 0000000..7294527 --- /dev/null +++ b/src/shared/api/model/screenshotAnnotation.ts @@ -0,0 +1,21 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { AnnotationType } from './annotationType'; +import type { ScreenshotAnnotationWidth } from './screenshotAnnotationWidth'; +import type { ScreenshotAnnotationHeight } from './screenshotAnnotationHeight'; +import type { ScreenshotAnnotationLabel } from './screenshotAnnotationLabel'; +import type { ScreenshotAnnotationColor } from './screenshotAnnotationColor'; + +export interface ScreenshotAnnotation { + type: AnnotationType; + x: number; + y: number; + width?: ScreenshotAnnotationWidth; + height?: ScreenshotAnnotationHeight; + label?: ScreenshotAnnotationLabel; + color?: ScreenshotAnnotationColor; +} diff --git a/src/shared/api/model/screenshotAnnotationColor.ts b/src/shared/api/model/screenshotAnnotationColor.ts new file mode 100644 index 0000000..3fdb65c --- /dev/null +++ b/src/shared/api/model/screenshotAnnotationColor.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ScreenshotAnnotationColor = string | null; diff --git a/src/shared/api/model/screenshotAnnotationHeight.ts b/src/shared/api/model/screenshotAnnotationHeight.ts new file mode 100644 index 0000000..43b8fbc --- /dev/null +++ b/src/shared/api/model/screenshotAnnotationHeight.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ScreenshotAnnotationHeight = number | null; diff --git a/src/shared/api/model/screenshotAnnotationLabel.ts b/src/shared/api/model/screenshotAnnotationLabel.ts new file mode 100644 index 0000000..ca03b7c --- /dev/null +++ b/src/shared/api/model/screenshotAnnotationLabel.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ScreenshotAnnotationLabel = string | null; diff --git a/src/shared/api/model/screenshotAnnotationWidth.ts b/src/shared/api/model/screenshotAnnotationWidth.ts new file mode 100644 index 0000000..4ab4d0e --- /dev/null +++ b/src/shared/api/model/screenshotAnnotationWidth.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ScreenshotAnnotationWidth = number | null; diff --git a/src/shared/api/model/screenshotEvidence.ts b/src/shared/api/model/screenshotEvidence.ts new file mode 100644 index 0000000..b147eae --- /dev/null +++ b/src/shared/api/model/screenshotEvidence.ts @@ -0,0 +1,18 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { ScreenshotEvidenceSourceUrl } from './screenshotEvidenceSourceUrl'; +import type { ScreenshotEvidenceAnnotations } from './screenshotEvidenceAnnotations'; + +export interface ScreenshotEvidence { + id: string; + url: string; + channel: string; + capturedAt: string; + caption: string; + sourceUrl?: ScreenshotEvidenceSourceUrl; + annotations?: ScreenshotEvidenceAnnotations; +} diff --git a/src/shared/api/model/screenshotEvidenceAnnotations.ts b/src/shared/api/model/screenshotEvidenceAnnotations.ts new file mode 100644 index 0000000..9ea5627 --- /dev/null +++ b/src/shared/api/model/screenshotEvidenceAnnotations.ts @@ -0,0 +1,9 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { ScreenshotAnnotation } from './screenshotAnnotation'; + +export type ScreenshotEvidenceAnnotations = ScreenshotAnnotation[] | null; diff --git a/src/shared/api/model/screenshotEvidenceSourceUrl.ts b/src/shared/api/model/screenshotEvidenceSourceUrl.ts new file mode 100644 index 0000000..ecda4aa --- /dev/null +++ b/src/shared/api/model/screenshotEvidenceSourceUrl.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type ScreenshotEvidenceSourceUrl = string | null; diff --git a/src/shared/api/model/severity.ts b/src/shared/api/model/severity.ts new file mode 100644 index 0000000..1f0dcbb --- /dev/null +++ b/src/shared/api/model/severity.ts @@ -0,0 +1,18 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type Severity = typeof Severity[keyof typeof Severity]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const Severity = { + critical: 'critical', + warning: 'warning', + good: 'good', + excellent: 'excellent', + unknown: 'unknown', +} as const; diff --git a/src/shared/api/model/snsLink.ts b/src/shared/api/model/snsLink.ts new file mode 100644 index 0000000..fe36e14 --- /dev/null +++ b/src/shared/api/model/snsLink.ts @@ -0,0 +1,12 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface SnsLink { + platform: string; + url: string; + location: string; +} diff --git a/src/shared/api/model/strategyDetail.ts b/src/shared/api/model/strategyDetail.ts new file mode 100644 index 0000000..a2bb53b --- /dev/null +++ b/src/shared/api/model/strategyDetail.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface StrategyDetail { + strategy: string; + detail: string; +} diff --git a/src/shared/api/model/topVideo.ts b/src/shared/api/model/topVideo.ts new file mode 100644 index 0000000..d8f02d5 --- /dev/null +++ b/src/shared/api/model/topVideo.ts @@ -0,0 +1,16 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { VideoType } from './videoType'; +import type { TopVideoDuration } from './topVideoDuration'; + +export interface TopVideo { + title: string; + views: number; + uploadedAgo: string; + type: VideoType; + duration?: TopVideoDuration; +} diff --git a/src/shared/api/model/topVideoDuration.ts b/src/shared/api/model/topVideoDuration.ts new file mode 100644 index 0000000..d8a630b --- /dev/null +++ b/src/shared/api/model/topVideoDuration.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type TopVideoDuration = string | null; diff --git a/src/shared/api/model/trackingPixel.ts b/src/shared/api/model/trackingPixel.ts new file mode 100644 index 0000000..3468176 --- /dev/null +++ b/src/shared/api/model/trackingPixel.ts @@ -0,0 +1,13 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { TrackingPixelDetails } from './trackingPixelDetails'; + +export interface TrackingPixel { + name: string; + installed: boolean; + details?: TrackingPixelDetails; +} diff --git a/src/shared/api/model/trackingPixelDetails.ts b/src/shared/api/model/trackingPixelDetails.ts new file mode 100644 index 0000000..fca8a6a --- /dev/null +++ b/src/shared/api/model/trackingPixelDetails.ts @@ -0,0 +1,8 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type TrackingPixelDetails = string | null; diff --git a/src/shared/api/model/transformationProposal.ts b/src/shared/api/model/transformationProposal.ts new file mode 100644 index 0000000..b5a0729 --- /dev/null +++ b/src/shared/api/model/transformationProposal.ts @@ -0,0 +1,17 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { AsIsToBeItem } from './asIsToBeItem'; +import type { PlatformStrategy } from './platformStrategy'; +import type { NewChannelProposal } from './newChannelProposal'; + +export interface TransformationProposal { + brandIdentity: AsIsToBeItem[]; + contentStrategy: AsIsToBeItem[]; + platformStrategies: PlatformStrategy[]; + websiteImprovements: AsIsToBeItem[]; + newChannelProposals: NewChannelProposal[]; +} diff --git a/src/shared/api/model/videoType.ts b/src/shared/api/model/videoType.ts new file mode 100644 index 0000000..36be8b0 --- /dev/null +++ b/src/shared/api/model/videoType.ts @@ -0,0 +1,15 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export type VideoType = typeof VideoType[keyof typeof VideoType]; + + +// eslint-disable-next-line @typescript-eslint/no-redeclare +export const VideoType = { + Short: 'Short', + Long: 'Long', +} as const; diff --git a/src/shared/api/model/websiteAudit.ts b/src/shared/api/model/websiteAudit.ts new file mode 100644 index 0000000..860c7da --- /dev/null +++ b/src/shared/api/model/websiteAudit.ts @@ -0,0 +1,18 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { AdditionalDomain } from './additionalDomain'; +import type { WebsiteAuditSnsLinksDetail } from './websiteAuditSnsLinksDetail'; +import type { TrackingPixel } from './trackingPixel'; + +export interface WebsiteAudit { + primaryDomain: string; + additionalDomains: AdditionalDomain[]; + snsLinksOnSite: boolean; + snsLinksDetail?: WebsiteAuditSnsLinksDetail; + trackingPixels: TrackingPixel[]; + mainCta: string; +} diff --git a/src/shared/api/model/websiteAuditSnsLinksDetail.ts b/src/shared/api/model/websiteAuditSnsLinksDetail.ts new file mode 100644 index 0000000..d1a0e56 --- /dev/null +++ b/src/shared/api/model/websiteAuditSnsLinksDetail.ts @@ -0,0 +1,9 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { SnsLink } from './snsLink'; + +export type WebsiteAuditSnsLinksDetail = SnsLink[] | null; diff --git a/src/shared/api/model/weeklyViewGrowth.ts b/src/shared/api/model/weeklyViewGrowth.ts new file mode 100644 index 0000000..888ed3a --- /dev/null +++ b/src/shared/api/model/weeklyViewGrowth.ts @@ -0,0 +1,11 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ + +export interface WeeklyViewGrowth { + absolute: number; + percentage: number; +} diff --git a/src/shared/api/model/youTubeAudit.ts b/src/shared/api/model/youTubeAudit.ts new file mode 100644 index 0000000..6633095 --- /dev/null +++ b/src/shared/api/model/youTubeAudit.ts @@ -0,0 +1,30 @@ +/** + * Generated by orval v7.21.0 🍺 + * Do not edit manually. + * FastAPI + * OpenAPI spec version: 0.1.0 + */ +import type { WeeklyViewGrowth } from './weeklyViewGrowth'; +import type { EstimatedRevenue } from './estimatedRevenue'; +import type { LinkedUrl } from './linkedUrl'; +import type { TopVideo } from './topVideo'; +import type { DiagnosisItem } from './diagnosisItem'; + +export interface YouTubeAudit { + channelName: string; + handle: string; + subscribers: number; + totalVideos: number; + totalViews: number; + weeklyViewGrowth: WeeklyViewGrowth; + estimatedMonthlyRevenue: EstimatedRevenue; + avgVideoLength: string; + uploadFrequency: string; + channelCreatedDate: string; + subscriberRank: string; + channelDescription: string; + linkedUrls: LinkedUrl[]; + playlists: string[]; + topVideos: TopVideo[]; + diagnosis: DiagnosisItem[]; +}