Compare commits

..

No commits in common. "b4691b029a2ac7d4524e90fbb51d99bebed529a3" and "2db78e6bec7eb54e5195c80f7dde36c579521bc0" have entirely different histories.

64 changed files with 212 additions and 682 deletions

View File

@ -2,7 +2,7 @@
* /test + E2E· URL .
*
* 7 : homepage, youtube, instagram, facebook, naverPlace, naverBlog, gangnamUnni
* .
* . naverPlace ( ID ).
*/
export interface ChannelUrls {
@ -24,121 +24,121 @@ export const CLINICS: ClinicFixture[] = [
{
label: '뷰성형외과',
urls: {
homepage: 'https://www.viewclinic.com',
youtube: 'https://www.youtube.com/@ViewclinicKR',
instagram: 'https://www.instagram.com/viewplastic/',
facebook: 'https://www.facebook.com/viewps1/',
naverPlace: 'https://m.place.naver.com/hospital/11709005',
naverBlog: 'https://blog.naver.com/viewclinicps',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/189',
homepage: 'viewclinic.com',
youtube: 'youtube.com/channel/UCQqqH3Klj2HQSHNNSVug-CQ',
instagram: 'instagram.com/viewplastic',
facebook: 'facebook.com/viewps1',
naverPlace: 'https://naver.me/x9BxGXkK',
naverBlog: 'blog.naver.com/viewclinicps',
gangnamUnni: 'gangnamunni.com/hospitals/189',
},
},
{
label: '바노바기 성형외과',
urls: {
homepage: 'https://www.banobagi.com',
youtube: 'https://www.youtube.com/c/banobagips',
instagram: 'https://www.instagram.com/banobagi_ps/',
facebook: 'https://www.facebook.com/BanobagiPlasticSurgery',
naverPlace: 'https://m.place.naver.com/hospital/21033469',
naverBlog: 'https://blog.naver.com/banobagips',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/23',
homepage: 'banobagi.com',
youtube: 'youtube.com/c/banobagips',
instagram: 'instagram.com/banobagi_ps',
facebook: 'facebook.com/BanobagiPlasticSurgery',
naverPlace: 'https://naver.me/xxY2yLr5',
naverBlog: 'blog.naver.com/banobagiprs',
gangnamUnni: 'gangnamunni.com/hospitals/23',
},
},
{
label: '아이디병원',
label: 'ID 성형외과',
urls: {
homepage: 'https://www.idhospital.com',
youtube: 'https://www.youtube.com/user/IDhospital',
instagram: 'https://www.instagram.com/idhospital',
facebook: 'https://www.facebook.com/idhospital0050',
naverPlace: 'https://m.place.naver.com/hospital/11548359',
naverBlog: 'https://blog.naver.com/idfacial',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/257',
homepage: 'idhospital.com',
youtube: 'youtube.com/user/IDhospital',
instagram: 'instagram.com/idhospital',
facebook: 'facebook.com/idhospital0050',
naverPlace: 'https://naver.me/GtURpCEn',
naverBlog: '',
gangnamUnni: 'gangnamunni.com/hospitals/257',
},
},
{
label: 'JK 성형외과',
urls: {
homepage: 'jkplastic.com',
youtube: 'youtube.com/channel/UC5F8dEt32hdp3cTeFyls4qg',
instagram: 'instagram.com/jkplasticsurgery_kr',
facebook: 'facebook.com/jkmedicalgroup',
naverPlace: 'https://naver.me/x67y6cAc',
naverBlog: 'blog.naver.com/jkstory1',
gangnamUnni: 'gangnamunni.com/hospitals/858',
},
},
{
label: '그랜드 성형외과',
urls: {
homepage: 'https://www.grandsurgery.com',
youtube: 'https://www.youtube.com/channel/UCU2o_aHqsNFuqwtdzVM3xbQ',
instagram: 'https://www.instagram.com/grand_korea/',
facebook: 'https://www.facebook.com/grandps.korea',
naverPlace: 'https://m.place.naver.com/hospital/12322994',
naverBlog: 'https://blog.naver.com/grandprs',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/62',
homepage: 'grandsurgery.com',
youtube: 'youtube.com/channel/UCU2o_aHqsNFuqwtdzVM3xbQ',
instagram: 'instagram.com/grand_korea',
facebook: 'facebook.com/grandps.korea',
naverPlace: 'https://naver.me/Fw7MYKWK',
naverBlog: 'blog.naver.com/grandprs',
gangnamUnni: 'gangnamunni.com/hospitals/62',
},
},
{
label: '원진성형외과',
label: 'BK 성형외과',
urls: {
homepage: 'https://www.k-wonjin.co.kr',
youtube: 'https://www.youtube.com/@wjwonjin',
instagram: 'https://www.instagram.com/wonjin_official/',
facebook: 'https://www.facebook.com/KwonjinPS',
naverPlace: 'https://m.place.naver.com/hospital/11887873',
naverBlog: 'https://blog.naver.com/popokpop',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/2500',
homepage: 'bkhospital.com',
youtube: 'youtube.com/channel/UChJONft3hemy5DGbXUveTFg',
instagram: 'instagram.com/bkhospital_korea',
facebook: '',
naverPlace: 'https://naver.me/517CTH3W',
naverBlog: '',
gangnamUnni: '',
},
},
{
label: '나나성형외과',
label: '톡스앤필',
urls: {
homepage: 'https://www.nanaprs.com',
youtube: 'https://www.youtube.com/@Nanaprstv',
instagram: 'https://www.instagram.com/nanaprs/',
facebook: 'https://www.facebook.com/nanaprs2',
naverPlace: 'https://m.place.naver.com/hospital/1518147116',
naverBlog: 'https://blog.naver.com/nanaprs1',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/938',
homepage: 'toxnfill.com',
youtube: 'youtube.com/channel/UCFpFZkm7mclD-z_-j7FTUag',
instagram: 'instagram.com/toxnfill_official',
facebook: 'facebook.com/toxnfill.official',
naverPlace: 'https://naver.me/FvEmJIHA',
naverBlog: 'blog.naver.com/toxnfill',
gangnamUnni: 'gangnamunni.com/hospitals/3702',
},
},
{
label: '디에이성형외과',
label: '더 압구정 성형외과',
urls: {
homepage: 'https://daprs.com',
youtube: 'https://www.youtube.com/channel/UC0wlA-w5JIt0G0EeWQf65AQ',
instagram: 'https://www.instagram.com/da_plastic_surgery',
facebook: 'https://www.facebook.com/daprs/',
naverPlace: 'https://m.place.naver.com/hospital/33084820',
naverBlog: 'https://blog.naver.com/daprs',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/250',
homepage: 'theclinic.co.kr',
youtube: 'youtube.com/user/theplasticsurgery1',
instagram: 'instagram.com/the_plasticsurgery',
facebook: 'facebook.com/THEPS16445998',
naverPlace: '',
naverBlog: 'blog.naver.com/with_theps',
gangnamUnni: 'gangnamunni.com/hospitals/30',
},
},
{
label: '노트성형외과',
label: '라마르 성형외과',
urls: {
homepage: 'http://notebreast.com',
youtube: 'https://www.youtube.com/channel/UC2OIyb2serotqDyEzQYyCtA',
instagram: 'https://www.instagram.com/note.prs/',
facebook: 'https://www.facebook.com/noteprs2/',
naverPlace: 'https://m.place.naver.com/hospital/1572670484',
naverBlog: 'https://blog.naver.com/noteprs01',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/2186',
homepage: 'lamarps.com',
youtube: '',
instagram: '',
facebook: '',
naverPlace: '',
naverBlog: '',
gangnamUnni: '',
},
},
{
label: '에이비성형외과',
label: '오라클 성형외과',
urls: {
homepage: 'https://www.abps.co.kr',
youtube: 'https://www.youtube.com/@abplasticsurgery',
instagram: 'https://www.instagram.com/ab_plasticsurgery_kr/',
facebook: 'https://www.facebook.com/profile.php?id=100063560996454',
naverPlace: 'https://m.place.naver.com/hospital/1304260302',
naverBlog: 'https://blog.naver.com/abps20',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/3004',
},
},
{
label: '제이준성형외과',
urls: {
homepage: 'http://www.jjprs.com',
youtube: 'https://www.youtube.com/channel/UC1p4msJnetDKeOW-B4nlwZA',
instagram: 'https://www.instagram.com/jayjunps/',
facebook: 'https://www.facebook.com/jayjunps',
naverPlace: 'https://m.place.naver.com/hospital/36294945',
naverBlog: 'https://blog.naver.com/gusrlf00',
gangnamUnni: 'https://www.gangnamunni.com/hospitals/139',
homepage: 'oracleclinic.com',
youtube: 'youtube.com/@oracle_medical_group',
instagram: 'instagram.com/oraclemedicalgroup',
facebook: 'facebook.com/oracleclinickr',
naverPlace: 'https://naver.me/GhbU3VtK',
naverBlog: '',
gangnamUnni: 'gangnamunni.com/hospitals/125',
},
},
]

View File

@ -1,26 +1,23 @@
/**
* /test fixture dev .
*
* - 10 fixture ( PINNED_LABEL)
* - MultiChannelInput `key` prefill
* - PINNED_LABEL fixture form prefill
* - DevOnly localhost
*/
import { useState } from 'react'
import { useNavigate } from 'react-router'
import MultiChannelInput, { type AnalyzePayload } from '@/features/channels/components/MultiChannelInput'
import { CLINICS } from '../fixtures/mockUrls'
const PINNED_LABEL = '뷰성형외과'
function pickInitialIndex(): number {
function pickIndex(): number {
const i = CLINICS.findIndex((c) => c.label === PINNED_LABEL)
return i >= 0 ? i : 0
}
export default function TestPrefillPage() {
const navigate = useNavigate()
const [selectedIdx, setSelectedIdx] = useState<number>(pickInitialIndex)
const clinic = CLINICS[selectedIdx]
const clinic = CLINICS[pickIndex()]
const handleAnalyze = (payload: AnalyzePayload) => {
navigate('/report/loading', {
@ -41,35 +38,9 @@ export default function TestPrefillPage() {
<h1 className="text-3xl font-bold text-primary-900">
prefill
</h1>
<p className="mt-2 text-sm text-slate-600">
fixture URL .
</p>
</div>
<div className="mb-6 flex flex-wrap gap-2" role="tablist" aria-label="병원 fixture 선택">
{CLINICS.map((c, i) => {
const active = i === selectedIdx
return (
<button
key={c.label}
type="button"
role="tab"
aria-selected={active}
onClick={() => setSelectedIdx(i)}
className={
active
? 'px-3 py-1.5 rounded-full text-xs font-medium bg-gradient-to-r from-[#4F1DA1] to-[#021341] text-white shadow-sm'
: 'px-3 py-1.5 rounded-full text-xs font-medium bg-white/80 backdrop-blur-sm text-slate-700 border border-slate-200 hover:border-slate-300 hover:bg-white transition'
}
>
{c.label}
</button>
)
})}
</div>
<MultiChannelInput
key={clinic.label}
variant="hero"
initialUrls={clinic.urls}
onAnalyze={handleAnalyze}

View File

@ -1,7 +1,8 @@
import { motion } from 'motion/react';
import { Instagram, ExternalLink } from 'lucide-react';
import { Instagram, AlertCircle, FileText, Users, Eye, ExternalLink } from 'lucide-react';
import { SectionWrapper } from './ui/SectionWrapper';
import { EmptyState } from './ui/EmptyState';
import { MetricCard } from './ui/MetricCard';
import { DiagnosisRow } from './ui/DiagnosisRow';
import type { InstagramAudit as InstagramAuditType, InstagramAccount } from '@/features/report/types/report';
@ -67,12 +68,25 @@ function AccountCard({ account, index }: { key?: string | number; account: Insta
</div>
</div>
{/* Format */}
{/* Format & reels */}
<div className="space-y-2 mb-4">
<div className="flex items-center justify-between text-sm">
<span className="text-slate-500"> </span>
<span className="font-medium text-[#0A1128]">{account.contentFormat}</span>
</div>
<div className="flex items-center justify-between text-sm">
<span className="text-slate-500"> </span>
<span className={`font-medium ${account.reelsCount === 0 ? 'text-[#7C3A4B]' : 'text-[#0A1128]'}`}>
{account.reelsCount === 0 ? (
<span className="inline-flex items-center gap-1">
<AlertCircle size={14} className="text-[#D4889A]" />
0 ()
</span>
) : (
account.reelsCount
)}
</span>
</div>
</div>
{/* Highlights */}

View File

@ -32,24 +32,6 @@ function nonEmpty<T>(arr: T[] | null | undefined): arr is T[] {
return Array.isArray(arr) && arr.length > 0;
}
function hasClinicSnapshotData(s: MarketingReport['clinicSnapshot'] | null | undefined): boolean {
if (!s) return false;
return !!(
s.name ||
s.nameEn ||
s.location ||
s.phone ||
s.domain ||
s.established ||
(s.staffCount ?? 0) > 0 ||
(s.overallRating ?? 0) > 0 ||
(s.totalReviews ?? 0) > 0 ||
s.leadDoctor?.name ||
nonEmpty(s.certifications) ||
s.registryData
);
}
export default function ReportBody({ data }: ReportBodyProps) {
// 각 audit에서 핸들 끌어와 헤더의 바로가기 버튼에 전달
const socialHandles = {
@ -74,7 +56,7 @@ export default function ReportBody({ data }: ReportBodyProps) {
/>
<SectionErrorBoundary>
{hasClinicSnapshotData(data.clinicSnapshot) ? (
{hasValue(data.clinicSnapshot) && data.clinicSnapshot.name ? (
<ClinicSnapshot data={data.clinicSnapshot} targetUrl={data.targetUrl} socialHandles={socialHandles} />
) : (
<EmptySection id="clinic-snapshot" title="Clinic Overview" subtitle="병원 기본 정보" />

View File

@ -33,7 +33,7 @@ export default function YouTubeAudit({ data }: YouTubeAuditProps) {
label="구독자"
value={formatNumber(data.subscribers)}
icon={<Users size={20} />}
subtext={data.subscriberRank ?? undefined}
subtext={data.subscriberRank}
/>
<MetricCard
label="총 영상 수"
@ -45,22 +45,13 @@ export default function YouTubeAudit({ data }: YouTubeAuditProps) {
value={formatNumber(data.totalViews)}
icon={<Eye size={20} />}
/>
{data.weeklyViewGrowth ? (
<MetricCard
label="주간 성장"
value={`${data.weeklyViewGrowth.absolute >= 0 ? '+' : ''}${formatNumber(data.weeklyViewGrowth.absolute)}`}
value={`+${formatNumber(data.weeklyViewGrowth.absolute)}`}
icon={<TrendingUp size={20} />}
subtext={`${data.weeklyViewGrowth.percentage > 0 ? '+' : ''}${data.weeklyViewGrowth.percentage}%`}
trend={data.weeklyViewGrowth.percentage > 0 ? 'up' : data.weeklyViewGrowth.percentage < 0 ? 'down' : 'neutral'}
/>
) : (
<MetricCard
label="주간 성장"
value="-"
icon={<TrendingUp size={20} />}
subtext="데이터 없음"
/>
)}
</div>
{/* Channel info card */}
@ -95,8 +86,8 @@ export default function YouTubeAudit({ data }: YouTubeAuditProps) {
<p className="text-sm text-slate-600 mb-4">{data.channelDescription}</p>
<div className="flex flex-wrap gap-3 text-sm text-slate-500">
<span>: {data.channelCreatedDate}</span>
<span> : {data.avgVideoLength ?? '-'}</span>
<span> : {data.uploadFrequency ?? '-'}</span>
<span> : {data.avgVideoLength}</span>
<span> : {data.uploadFrequency}</span>
</div>
{/* Linked URLs */}

View File

@ -87,12 +87,12 @@ export interface YouTubeAudit {
subscribers: number;
totalVideos: number;
totalViews: number;
weeklyViewGrowth: { absolute: number; percentage: number } | null;
estimatedMonthlyRevenue: { min: number; max: number } | null;
avgVideoLength: string | null;
uploadFrequency: string | null;
weeklyViewGrowth: { absolute: number; percentage: number };
estimatedMonthlyRevenue: { min: number; max: number };
avgVideoLength: string;
uploadFrequency: string;
channelCreatedDate: string;
subscriberRank: string | null;
subscriberRank: string;
channelDescription: string;
linkedUrls: { label: string; url: string }[];
playlists: string[];

View File

@ -6,13 +6,17 @@
*/
import type { ClinicResponseHospitalNameEn } from './clinicResponseHospitalNameEn';
import type { ClinicResponseRoadAddress } from './clinicResponseRoadAddress';
import type { ClinicResponseUrl } from './clinicResponseUrl';
import type { ClinicResponseRawData } from './clinicResponseRawData';
export interface ClinicResponse {
hospital_id: string;
hospital_name: string;
hospital_name_en: ClinicResponseHospitalNameEn;
road_address: ClinicResponseRoadAddress;
url: ClinicResponseUrl;
status: string;
raw_data: ClinicResponseRawData;
created_at: string;
updated_at: string;
}

View File

@ -0,0 +1,9 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { ClinicResponseRawDataAnyOf } from './clinicResponseRawDataAnyOf';
export type ClinicResponseRawData = ClinicResponseRawDataAnyOf | null;

View File

@ -5,4 +5,4 @@
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotDomain = string | null;
export type ClinicResponseRawDataAnyOf = { [key: string]: unknown };

View File

@ -5,4 +5,4 @@
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageBio = string | null;
export type ClinicResponseUrl = string | null;

View File

@ -4,31 +4,30 @@
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { ClinicSnapshotName } from './clinicSnapshotName';
import type { ClinicSnapshotNameEn } from './clinicSnapshotNameEn';
import type { ClinicSnapshotStaffCount } from './clinicSnapshotStaffCount';
import type { ClinicSnapshotLeadDoctor } from './clinicSnapshotLeadDoctor';
import type { ClinicSnapshotOverallRating } from './clinicSnapshotOverallRating';
import type { ClinicSnapshotTotalReviews } from './clinicSnapshotTotalReviews';
import type { ClinicSnapshotLocation } from './clinicSnapshotLocation';
import type { ClinicSnapshotPhone } from './clinicSnapshotPhone';
import type { ClinicSnapshotDomain } from './clinicSnapshotDomain';
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?: ClinicSnapshotName;
nameEn?: ClinicSnapshotNameEn;
staffCount?: ClinicSnapshotStaffCount;
leadDoctor?: ClinicSnapshotLeadDoctor;
overallRating?: ClinicSnapshotOverallRating;
totalReviews?: ClinicSnapshotTotalReviews;
certifications?: string[];
location?: ClinicSnapshotLocation;
phone?: ClinicSnapshotPhone;
domain?: ClinicSnapshotDomain;
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;

View File

@ -1,9 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { LeadDoctor } from './leadDoctor';
export type ClinicSnapshotLeadDoctor = LeadDoctor | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotLocation = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotName = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotOverallRating = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotPhone = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotStaffCount = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotTotalReviews = number | null;

View File

@ -7,11 +7,10 @@
import type { FacebookPage } from './facebookPage';
import type { DiagnosisItem } from './diagnosisItem';
import type { BrandInconsistency } from './brandInconsistency';
import type { FacebookAuditConsolidationRecommendation } from './facebookAuditConsolidationRecommendation';
export interface FacebookAudit {
pages?: FacebookPage[];
diagnosis?: DiagnosisItem[];
brandInconsistencies?: BrandInconsistency[];
consolidationRecommendation?: FacebookAuditConsolidationRecommendation;
pages: FacebookPage[];
diagnosis: DiagnosisItem[];
brandInconsistencies: BrandInconsistency[];
consolidationRecommendation: string;
}

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookAuditConsolidationRecommendation = string | null;

View File

@ -4,41 +4,27 @@
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { FacebookPageUrl } from './facebookPageUrl';
import type { FacebookPagePageName } from './facebookPagePageName';
import type { FacebookPageLanguage } from './facebookPageLanguage';
import type { FacebookPageLabel } from './facebookPageLabel';
import type { FacebookPageFollowers } from './facebookPageFollowers';
import type { FacebookPageFollowing } from './facebookPageFollowing';
import type { FacebookPageCategory } from './facebookPageCategory';
import type { FacebookPageBio } from './facebookPageBio';
import type { FacebookPageLogo } from './facebookPageLogo';
import type { FacebookPageLogoDescription } from './facebookPageLogoDescription';
import type { FacebookPageLink } from './facebookPageLink';
import type { FacebookPageLinkedDomain } from './facebookPageLinkedDomain';
import type { FacebookPageReviews } from './facebookPageReviews';
import type { FacebookPageRecentPostAge } from './facebookPageRecentPostAge';
import type { FacebookPageHasWhatsapp } from './facebookPageHasWhatsapp';
import type { Language } from './language';
import type { FacebookPagePostFrequency } from './facebookPagePostFrequency';
import type { FacebookPageTopContentType } from './facebookPageTopContentType';
import type { FacebookPageEngagement } from './facebookPageEngagement';
export interface FacebookPage {
url?: FacebookPageUrl;
pageName?: FacebookPagePageName;
language?: FacebookPageLanguage;
label?: FacebookPageLabel;
followers?: FacebookPageFollowers;
following?: FacebookPageFollowing;
category?: FacebookPageCategory;
bio?: FacebookPageBio;
logo?: FacebookPageLogo;
logoDescription?: FacebookPageLogoDescription;
link?: FacebookPageLink;
linkedDomain?: FacebookPageLinkedDomain;
reviews?: FacebookPageReviews;
recentPostAge?: FacebookPageRecentPostAge;
hasWhatsapp?: FacebookPageHasWhatsapp;
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;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageCategory = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageFollowers = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageFollowing = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageHasWhatsapp = boolean | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageLabel = string | null;

View File

@ -1,9 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { Language } from './language';
export type FacebookPageLanguage = Language | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageLink = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageLinkedDomain = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageLogo = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageLogoDescription = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPagePageName = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageRecentPostAge = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageReviews = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type FacebookPageUrl = string | null;

View File

@ -61,21 +61,15 @@ export * from './clinicHistoryResponse';
export * from './clinicHistoryResponseMetricsTimeseries';
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 './clinicSnapshotDomain';
export * from './clinicSnapshotLeadDoctor';
export * from './clinicSnapshotLocation';
export * from './clinicSnapshotLogoImages';
export * from './clinicSnapshotName';
export * from './clinicSnapshotNameEn';
export * from './clinicSnapshotOverallRating';
export * from './clinicSnapshotPhone';
export * from './clinicSnapshotRegistryData';
export * from './clinicSnapshotSource';
export * from './clinicSnapshotStaffCount';
export * from './clinicSnapshotTotalReviews';
export * from './colorSwatch';
export * from './contentCountSummary';
export * from './contentCountSummaryType';
@ -87,26 +81,10 @@ export * from './diagnosisItem';
export * from './diagnosisItemEvidenceIds';
export * from './estimatedRevenue';
export * from './facebookAudit';
export * from './facebookAuditConsolidationRecommendation';
export * from './facebookPage';
export * from './facebookPageBio';
export * from './facebookPageCategory';
export * from './facebookPageEngagement';
export * from './facebookPageFollowers';
export * from './facebookPageFollowing';
export * from './facebookPageHasWhatsapp';
export * from './facebookPageLabel';
export * from './facebookPageLanguage';
export * from './facebookPageLink';
export * from './facebookPageLinkedDomain';
export * from './facebookPageLogo';
export * from './facebookPageLogoDescription';
export * from './facebookPagePageName';
export * from './facebookPagePostFrequency';
export * from './facebookPageRecentPostAge';
export * from './facebookPageReviews';
export * from './facebookPageTopContentType';
export * from './facebookPageUrl';
export * from './fileListItem';
export * from './fileListItemSizeBytes';
export * from './fileType';
@ -115,18 +93,6 @@ export * from './fileUploadResponseSizeBytes';
export * from './fontSpec';
export * from './hTTPValidationError';
export * from './instagramAccount';
export * from './instagramAccountBio';
export * from './instagramAccountCategory';
export * from './instagramAccountContentFormat';
export * from './instagramAccountFollowers';
export * from './instagramAccountFollowing';
export * from './instagramAccountHandle';
export * from './instagramAccountLabel';
export * from './instagramAccountLanguage';
export * from './instagramAccountPosts';
export * from './instagramAccountProfileLink';
export * from './instagramAccountProfilePhoto';
export * from './instagramAccountReelsCount';
export * from './instagramAudit';
export * from './kPIMetric';
export * from './language';
@ -149,6 +115,7 @@ export * from './planApiResponseClinicName';
export * from './planApiResponseClinicNameEn';
export * from './planApiResponseRepurposingProposals';
export * from './platformStrategy';
export * from './priceRange';
export * from './registryData';
export * from './registryDataBranches';
export * from './registryDataBrandGroup';
@ -192,16 +159,5 @@ export * from './websiteAuditSnsLinksDetail';
export * from './weeklyViewGrowth';
export * from './workflowStep';
export * from './youTubeAudit';
export * from './youTubeAuditAvgVideoLength';
export * from './youTubeAuditChannelCreatedDate';
export * from './youTubeAuditChannelDescription';
export * from './youTubeAuditChannelName';
export * from './youTubeAuditEstimatedMonthlyRevenue';
export * from './youTubeAuditHandle';
export * from './youTubeAuditSubscribers';
export * from './youTubeAuditTotalVideos';
export * from './youTubeAuditTotalViews';
export * from './youTubeAuditUploadFrequency';
export * from './youTubeAuditWeeklyViewGrowth';
export * from './youTubeRepurposeItem';
export * from './youTubeRepurposeItemType';

View File

@ -4,31 +4,20 @@
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { InstagramAccountHandle } from './instagramAccountHandle';
import type { InstagramAccountLanguage } from './instagramAccountLanguage';
import type { InstagramAccountLabel } from './instagramAccountLabel';
import type { InstagramAccountPosts } from './instagramAccountPosts';
import type { InstagramAccountFollowers } from './instagramAccountFollowers';
import type { InstagramAccountFollowing } from './instagramAccountFollowing';
import type { InstagramAccountCategory } from './instagramAccountCategory';
import type { InstagramAccountProfileLink } from './instagramAccountProfileLink';
import type { InstagramAccountReelsCount } from './instagramAccountReelsCount';
import type { InstagramAccountContentFormat } from './instagramAccountContentFormat';
import type { InstagramAccountProfilePhoto } from './instagramAccountProfilePhoto';
import type { InstagramAccountBio } from './instagramAccountBio';
import type { Language } from './language';
export interface InstagramAccount {
handle?: InstagramAccountHandle;
language?: InstagramAccountLanguage;
label?: InstagramAccountLabel;
posts?: InstagramAccountPosts;
followers?: InstagramAccountFollowers;
following?: InstagramAccountFollowing;
category?: InstagramAccountCategory;
profileLink?: InstagramAccountProfileLink;
highlights?: string[];
reelsCount?: InstagramAccountReelsCount;
contentFormat?: InstagramAccountContentFormat;
profilePhoto?: InstagramAccountProfilePhoto;
bio?: InstagramAccountBio;
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;
}

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountBio = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountCategory = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountContentFormat = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountFollowers = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountFollowing = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountHandle = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountLabel = string | null;

View File

@ -1,9 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { Language } from './language';
export type InstagramAccountLanguage = Language | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountPosts = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountProfileLink = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountProfilePhoto = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type InstagramAccountReelsCount = number | null;

View File

@ -8,6 +8,6 @@ import type { InstagramAccount } from './instagramAccount';
import type { DiagnosisItem } from './diagnosisItem';
export interface InstagramAudit {
accounts?: InstagramAccount[];
diagnosis?: DiagnosisItem[];
accounts: InstagramAccount[];
diagnosis: DiagnosisItem[];
}

View File

@ -12,5 +12,4 @@ export type Language = typeof Language[keyof typeof Language];
export const Language = {
KR: 'KR',
EN: 'EN',
WW: 'WW',
} as const;

View File

@ -5,4 +5,8 @@
* OpenAPI spec version: 0.1.0
*/
export type ClinicSnapshotNameEn = string | null;
export interface PriceRange {
min: string;
max: string;
currency: string;
}

View File

@ -4,35 +4,27 @@
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { YouTubeAuditChannelName } from './youTubeAuditChannelName';
import type { YouTubeAuditHandle } from './youTubeAuditHandle';
import type { YouTubeAuditSubscribers } from './youTubeAuditSubscribers';
import type { YouTubeAuditTotalVideos } from './youTubeAuditTotalVideos';
import type { YouTubeAuditTotalViews } from './youTubeAuditTotalViews';
import type { YouTubeAuditWeeklyViewGrowth } from './youTubeAuditWeeklyViewGrowth';
import type { YouTubeAuditEstimatedMonthlyRevenue } from './youTubeAuditEstimatedMonthlyRevenue';
import type { YouTubeAuditAvgVideoLength } from './youTubeAuditAvgVideoLength';
import type { YouTubeAuditUploadFrequency } from './youTubeAuditUploadFrequency';
import type { YouTubeAuditChannelCreatedDate } from './youTubeAuditChannelCreatedDate';
import type { YouTubeAuditChannelDescription } from './youTubeAuditChannelDescription';
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?: YouTubeAuditChannelName;
handle?: YouTubeAuditHandle;
subscribers?: YouTubeAuditSubscribers;
totalVideos?: YouTubeAuditTotalVideos;
totalViews?: YouTubeAuditTotalViews;
weeklyViewGrowth?: YouTubeAuditWeeklyViewGrowth;
estimatedMonthlyRevenue?: YouTubeAuditEstimatedMonthlyRevenue;
avgVideoLength?: YouTubeAuditAvgVideoLength;
uploadFrequency?: YouTubeAuditUploadFrequency;
channelCreatedDate?: YouTubeAuditChannelCreatedDate;
channelDescription?: YouTubeAuditChannelDescription;
linkedUrls?: LinkedUrl[];
playlists?: string[];
topVideos?: TopVideo[];
diagnosis?: DiagnosisItem[];
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[];
}

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditAvgVideoLength = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditChannelCreatedDate = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditChannelDescription = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditChannelName = string | null;

View File

@ -1,9 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { EstimatedRevenue } from './estimatedRevenue';
export type YouTubeAuditEstimatedMonthlyRevenue = EstimatedRevenue | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditHandle = string | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditSubscribers = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditTotalVideos = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditTotalViews = number | null;

View File

@ -1,8 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
export type YouTubeAuditUploadFrequency = string | null;

View File

@ -1,9 +0,0 @@
/**
* Generated by orval v7.21.0 🍺
* Do not edit manually.
* FastAPI
* OpenAPI spec version: 0.1.0
*/
import type { WeeklyViewGrowth } from './weeklyViewGrowth';
export type YouTubeAuditWeeklyViewGrowth = WeeklyViewGrowth | null;