from django.db import models from apps.core.utils import CONTENT_FORMAT_CHOICES, FORMAT_MARKDOWN, FORMAT_PLAIN, render_content class HomepageSection(models.Model): TYPE_FEATURES = "features" TYPE_SCREENSHOTS = "screenshots" TYPE_PRODUCTS = "products" TYPE_PROBLEMS = "problems" TYPE_ABOUT_STRIP = "about_strip" TYPE_SUPPORTERS = "supporters" TYPE_CHOICES = [ (TYPE_FEATURES, "Features"), (TYPE_SCREENSHOTS, "Screenshots Gallery"), (TYPE_PRODUCTS, "Products"), (TYPE_PROBLEMS, "Problems / Value Proposition"), (TYPE_ABOUT_STRIP, "About Strip"), (TYPE_SUPPORTERS, "Supporters"), ] section_type = models.CharField(max_length=30, choices=TYPE_CHOICES, unique=True) badge = models.CharField(max_length=100, blank=True) title = models.CharField(max_length=300, blank=True) description = models.TextField(blank=True) link_text = models.CharField(max_length=100, blank=True, help_text="CTA button label (About Strip).") link_url = models.CharField(max_length=300, blank=True, help_text="CTA button URL (About Strip).") order = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) class Meta: ordering = ["order"] verbose_name = "Homepage Section" verbose_name_plural = "Homepage Sections" def __str__(self): return f"[{self.get_section_type_display()}] {self.title or self.badge}" class HomepageSectionItem(models.Model): section = models.ForeignKey(HomepageSection, on_delete=models.CASCADE, related_name="items") icon = models.CharField(max_length=20, blank=True, help_text="Emoji or short symbol (e.g. ⚗️).") title = models.CharField(max_length=300, blank=True) content = models.TextField(blank=True) image = models.ImageField(upload_to="homepage/items/", blank=True, null=True, help_text="Logo or image (used for Supporters cards).") order = models.PositiveIntegerField(default=0) class Meta: ordering = ["order"] verbose_name = "Homepage Section Item" verbose_name_plural = "Homepage Section Items" def __str__(self): return f"{self.section} › {self.title or self.icon or '(item)'}" class AboutSection(models.Model): TYPE_HERO = "hero" TYPE_INTRO = "intro" TYPE_GRID = "grid" TYPE_HISTORY = "history" TYPE_CUSTOM = "custom" TYPE_CHOICES = [ (TYPE_HERO, "Hero"), (TYPE_INTRO, "Intro Card"), (TYPE_GRID, "Grid Cards"), (TYPE_HISTORY, "History Block"), (TYPE_CUSTOM, "Custom Content"), ] section_type = models.CharField(max_length=30, choices=TYPE_CHOICES, default=TYPE_CUSTOM) badge = models.CharField(max_length=100, blank=True) title = models.CharField(max_length=300, blank=True) subtitle = models.CharField(max_length=500, blank=True, help_text="Used as subtitle in Hero and year in History.") content = models.TextField(blank=True) content_format = models.CharField(max_length=20, choices=CONTENT_FORMAT_CHOICES, default=FORMAT_MARKDOWN) order = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["order"] verbose_name = "About Section" verbose_name_plural = "About Sections" @property def rendered_content(self): return render_content(self.content, self.content_format) def __str__(self): label = self.title or self.badge or self.get_section_type_display() return f"[{self.get_section_type_display()}] {label}" class AboutSectionItem(models.Model): section = models.ForeignKey(AboutSection, on_delete=models.CASCADE, related_name="items") badge = models.CharField(max_length=100, blank=True) title = models.CharField(max_length=300, blank=True) content = models.TextField(blank=True, help_text="Description text or link label for History links.") url = models.URLField(blank=True, help_text="Used for History block links.") image = models.ImageField(upload_to="about/", blank=True, null=True) image_alt = models.CharField(max_length=200, blank=True) is_featured = models.BooleanField(default=False, help_text="Mark as featured item (e.g. large screenshot).") order = models.PositiveIntegerField(default=0) class Meta: ordering = ["order"] verbose_name = "About Section Item" verbose_name_plural = "About Section Items" def __str__(self): return f"{self.section} › {self.title or self.badge or '(item)'}" class ContactSubmission(models.Model): name = models.CharField(max_length=200) title = models.CharField(max_length=300) description = models.TextField() email = models.EmailField(blank=True) submitted_at = models.DateTimeField(auto_now_add=True) is_read = models.BooleanField(default=False) class Meta: ordering = ["-submitted_at"] verbose_name = "Contact Submission" verbose_name_plural = "Contact Submissions" def __str__(self): return f"{self.name} — {self.title}" class FAQEntry(models.Model): question = models.CharField(max_length=500) answer = models.TextField() answer_format = models.CharField( max_length=20, choices=CONTENT_FORMAT_CHOICES, default=FORMAT_PLAIN ) order = models.PositiveIntegerField(default=0) is_active = models.BooleanField(default=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["order"] verbose_name = "FAQ Entry" verbose_name_plural = "FAQ Entries" def __str__(self): return self.question @property def rendered_answer(self): return render_content(self.answer, self.answer_format) class DownloadItem(models.Model): PLATFORM_WINDOWS = "windows" PLATFORM_MACOS = "macos" PLATFORM_LINUX = "linux" PLATFORM_CHOICES = [ (PLATFORM_WINDOWS, "Windows"), (PLATFORM_MACOS, "macOS"), (PLATFORM_LINUX, "Linux"), ] name = models.CharField(max_length=200) platform = models.CharField(max_length=20, choices=PLATFORM_CHOICES) version = models.CharField(max_length=50) download_url = models.URLField() description = models.TextField(blank=True) is_active = models.BooleanField(default=True) order = models.PositiveIntegerField(default=0) created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ["order", "platform"] verbose_name = "Download Item" verbose_name_plural = "Download Items" def __str__(self): return f"{self.name} ({self.get_platform_display()})"