# app/modules/cms/models/store_theme.py """ Store Theme Configuration Model Allows each store to customize their shop's appearance """ from sqlalchemy import JSON, Boolean, Column, ForeignKey, Integer, String, Text from sqlalchemy.orm import relationship from app.core.database import Base from models.database.base import TimestampMixin class StoreTheme(Base, TimestampMixin): """ Stores theme configuration for each store's shop. Each store can have ONE active theme: - Custom colors (primary, secondary, accent) - Custom fonts - Custom logo and favicon - Custom CSS overrides - Layout preferences Theme presets available: default, modern, classic, minimal, vibrant """ __tablename__ = "store_themes" id = Column(Integer, primary_key=True, index=True) store_id = Column( Integer, ForeignKey("stores.id", ondelete="CASCADE"), nullable=False, unique=True, # ONE store = ONE theme ) # Basic Theme Settings theme_name = Column( String(100), default="default" ) # default, modern, classic, minimal, vibrant is_active = Column(Boolean, default=True) # Color Scheme (JSON for flexibility) colors = Column( JSON, default={ "primary": "#6366f1", # Indigo "secondary": "#8b5cf6", # Purple "accent": "#ec4899", # Pink "background": "#ffffff", # White "text": "#1f2937", # Gray-800 "border": "#e5e7eb", # Gray-200 }, ) # Typography font_family_heading = Column(String(100), default="Inter, sans-serif") font_family_body = Column(String(100), default="Inter, sans-serif") # Branding Assets logo_url = Column(String(500), nullable=True) # Path to store logo logo_dark_url = Column(String(500), nullable=True) # Dark mode logo favicon_url = Column(String(500), nullable=True) # Favicon banner_url = Column(String(500), nullable=True) # Homepage banner # Layout Preferences layout_style = Column(String(50), default="grid") # grid, list, masonry header_style = Column(String(50), default="fixed") # fixed, static, transparent product_card_style = Column( String(50), default="modern" ) # modern, classic, minimal # Custom CSS (for advanced customization) custom_css = Column(Text, nullable=True) # Social Media Links social_links = Column(JSON, default={}) # {facebook: "url", instagram: "url", etc.} # SEO & Meta meta_title_template = Column( String(200), nullable=True ) # e.g., "{product_name} - {shop_name}" meta_description = Column(Text, nullable=True) # Relationships - FIXED: back_populates must match the relationship name in Store model store = relationship("Store", back_populates="store_theme") def __repr__(self): return ( f"" ) @property def primary_color(self): """Get primary color from JSON""" return self.colors.get("primary", "#6366f1") @property def css_variables(self): """Generate CSS custom properties from theme config""" return { "--color-primary": self.colors.get("primary", "#6366f1"), "--color-secondary": self.colors.get("secondary", "#8b5cf6"), "--color-accent": self.colors.get("accent", "#ec4899"), "--color-background": self.colors.get("background", "#ffffff"), "--color-text": self.colors.get("text", "#1f2937"), "--color-border": self.colors.get("border", "#e5e7eb"), "--font-heading": self.font_family_heading, "--font-body": self.font_family_body, } def to_dict(self): """Convert theme to dictionary for template rendering""" return { "theme_name": self.theme_name, "colors": self.colors, "fonts": { "heading": self.font_family_heading, "body": self.font_family_body, }, "branding": { "logo": self.logo_url, "logo_dark": self.logo_dark_url, "favicon": self.favicon_url, "banner": self.banner_url, }, "layout": { "style": self.layout_style, "header": self.header_style, "product_card": self.product_card_style, }, "social_links": self.social_links, "custom_css": self.custom_css, "css_variables": self.css_variables, } __all__ = ["StoreTheme"]