from typing import Literal from pydantic import BaseModel class PlanInput(BaseModel): clinic_name: str | None = None clinic_name_en: str | None = None address: str | None = None phone: str | None = None slogan: str | None = None services: str | None = None doctors: str | None = None report: str | None = None # --- BrandGuide --- class ColorSwatch(BaseModel): name: str hex: str usage: str class FontSpec(BaseModel): family: str weight: str usage: str sampleText: str class LogoUsageRule(BaseModel): rule: str description: str correct: bool class ToneOfVoice(BaseModel): personality: list[str] communicationStyle: str doExamples: list[str] dontExamples: list[str] class ChannelBrandingRule(BaseModel): channel: str icon: str profilePhoto: str bannerSpec: str bioTemplate: str currentStatus: Literal["correct", "incorrect", "missing"] class BrandInconsistencyValue(BaseModel): channel: str value: str isCorrect: bool class BrandInconsistency(BaseModel): field: str values: list[BrandInconsistencyValue] impact: str recommendation: str class BrandGuide(BaseModel): colors: list[ColorSwatch] fonts: list[FontSpec] logoRules: list[LogoUsageRule] toneOfVoice: ToneOfVoice channelBranding: list[ChannelBrandingRule] brandInconsistencies: list[BrandInconsistency] # --- ChannelStrategy --- class ChannelStrategyCard(BaseModel): channelId: str channelName: str icon: str currentStatus: str targetGoal: str contentTypes: list[str] postingFrequency: str tone: str formatGuidelines: list[str] priority: Literal["P0", "P1", "P2"] customerJourneyStage: Literal["awareness", "interest", "consideration", "conversion", "loyalty"] | None = None # --- ContentStrategy --- class ContentPillar(BaseModel): title: str description: str relatedUSP: str exampleTopics: list[str] color: str class ContentTypeRow(BaseModel): format: str channels: list[str] frequency: str purpose: str class WorkflowStep(BaseModel): step: int name: str description: str owner: str duration: str class RepurposingOutput(BaseModel): format: str channel: str description: str class ContentStrategyData(BaseModel): pillars: list[ContentPillar] typeMatrix: list[ContentTypeRow] workflow: list[WorkflowStep] repurposingSource: str repurposingOutputs: list[RepurposingOutput] # --- Calendar --- class CalendarEntry(BaseModel): dayOfWeek: int channel: str channelIcon: str contentType: Literal["video", "blog", "social", "ad"] title: str id: str | None = None description: str | None = None pillar: str | None = None status: Literal["draft", "approved", "published"] | None = None isManualEdit: bool | None = None aiPromptSeed: str | None = None class CalendarWeek(BaseModel): weekNumber: int label: str entries: list[CalendarEntry] class ContentCountSummary(BaseModel): type: Literal["video", "blog", "social", "ad"] label: str count: int color: str class CalendarData(BaseModel): weeks: list[CalendarWeek] monthlySummary: list[ContentCountSummary] # --- AssetCollection --- class AssetCard(BaseModel): id: str source: Literal["homepage", "naver_place", "blog", "social", "youtube"] sourceLabel: str type: Literal["photo", "video", "text"] title: str description: str repurposingSuggestions: list[str] status: Literal["collected", "pending", "needs_creation"] class YouTubeRepurposeItem(BaseModel): title: str views: int type: Literal["Short", "Long"] repurposeAs: list[str] class AssetCollectionData(BaseModel): assets: list[AssetCard] youtubeRepurpose: list[YouTubeRepurposeItem] # --- Repurposing --- class RepurposingProposalItem(BaseModel): sourceVideo: YouTubeRepurposeItem outputs: list[RepurposingOutput] estimatedEffort: Literal["low", "medium", "high"] priority: Literal["high", "medium", "low"] # --- Workflow --- class WorkflowVideoDraft(BaseModel): script: str shootingGuide: list[str] duration: str # class WorkflowImageTextDraft(BaseModel): # type: Literal["cardnews", "blog"] # headline: str # copy: list[str] # layoutHint: str | None = None # class WorkflowItem(BaseModel): # id: str # title: str # contentType: Literal["video", "image-text"] # channel: str # channelIcon: str # stage: Literal["planning", "ai-draft", "review", "approved", "scheduled"] # userNotes: str | None = None # videoDraft: WorkflowVideoDraft | None = None # imageTextDraft: WorkflowImageTextDraft | None = None # scheduledDate: str | None = None # class WorkflowData(BaseModel): # items: list[WorkflowItem] # --- PlanOutput --- class PlanOutput(BaseModel): brandGuide: BrandGuide channelStrategies: list[ChannelStrategyCard] contentStrategy: ContentStrategyData calendar: CalendarData assetCollection: AssetCollectionData repurposingProposals: list[RepurposingProposalItem] | None = None #workflow: WorkflowData | None = None