""" Homepage Section Schemas with Dynamic Multi-Language Support. Language codes are NOT hardcoded - they come from platform.supported_languages. The TranslatableText class stores translations as a dict where keys are language codes. Example JSON structure: { "hero": { "enabled": true, "title": {"translations": {"fr": "Bienvenue", "en": "Welcome"}}, "subtitle": {"translations": {...}}, "buttons": [...] }, "features": {...}, "pricing": {...}, "cta": {...} } """ from pydantic import BaseModel, Field class TranslatableText(BaseModel): """ Text field with translations stored as language-keyed dict. Languages come from platform.supported_languages (not hardcoded). Use .get(lang, default_lang) to retrieve translation with fallback. """ translations: dict[str, str] = Field( default_factory=dict, description="Language code -> translated text mapping" ) def get(self, lang: str, default_lang: str = "fr") -> str: """Get translation with fallback to default language.""" return self.translations.get(lang) or self.translations.get(default_lang) or "" def set(self, lang: str, text: str) -> None: """Set translation for a language.""" self.translations[lang] = text def has_translation(self, lang: str) -> bool: """Check if translation exists for language.""" return bool(self.translations.get(lang)) class HeroButton(BaseModel): """Button in hero or CTA section.""" text: TranslatableText = Field(default_factory=TranslatableText) url: str = "" style: str = Field(default="primary", description="primary, secondary, outline") class HeroSection(BaseModel): """Hero section configuration.""" enabled: bool = True badge_text: TranslatableText | None = None title: TranslatableText = Field(default_factory=TranslatableText) subtitle: TranslatableText = Field(default_factory=TranslatableText) background_type: str = Field( default="gradient", description="gradient, image, solid" ) background_image: str | None = None buttons: list[HeroButton] = Field(default_factory=list) class FeatureCard(BaseModel): """Single feature in features section.""" icon: str = "" title: TranslatableText = Field(default_factory=TranslatableText) description: TranslatableText = Field(default_factory=TranslatableText) class FeaturesSection(BaseModel): """Features section configuration.""" enabled: bool = True title: TranslatableText = Field(default_factory=TranslatableText) subtitle: TranslatableText | None = None features: list[FeatureCard] = Field(default_factory=list) layout: str = Field(default="grid", description="grid, list, cards") class PricingSection(BaseModel): """Pricing section configuration.""" enabled: bool = True title: TranslatableText = Field(default_factory=TranslatableText) subtitle: TranslatableText | None = None use_subscription_tiers: bool = Field( default=True, description="Pull pricing from subscription_tiers table dynamically" ) class CTASection(BaseModel): """Call-to-action section configuration.""" enabled: bool = True title: TranslatableText = Field(default_factory=TranslatableText) subtitle: TranslatableText | None = None buttons: list[HeroButton] = Field(default_factory=list) background_type: str = Field( default="gradient", description="gradient, image, solid" ) class HomepageSections(BaseModel): """Complete homepage sections structure.""" hero: HeroSection | None = None features: FeaturesSection | None = None pricing: PricingSection | None = None cta: CTASection | None = None @classmethod def get_empty_structure(cls, languages: list[str]) -> "HomepageSections": """ Create empty section structure with language placeholders. Args: languages: List of language codes from platform.supported_languages Returns: HomepageSections with empty translations for all languages """ def make_translatable(langs: list[str]) -> TranslatableText: return TranslatableText(translations=dict.fromkeys(langs, "")) return cls( hero=HeroSection( title=make_translatable(languages), subtitle=make_translatable(languages), buttons=[], ), features=FeaturesSection( title=make_translatable(languages), features=[], ), pricing=PricingSection( title=make_translatable(languages), use_subscription_tiers=True, ), cta=CTASection( title=make_translatable(languages), buttons=[], ), ) # ============================================================================= # API Request/Response Schemas # ============================================================================= class SectionUpdateRequest(BaseModel): """Request to update a single section.""" section_name: str = Field(..., description="hero, features, pricing, or cta") section_data: dict = Field(..., description="Section configuration") class HomepageSectionsResponse(BaseModel): """Response containing all homepage sections with platform language info.""" sections: HomepageSections | None = None supported_languages: list[str] = Field(default_factory=lambda: ["fr", "de", "en"]) default_language: str = "fr"