//! Templates for creator dashboards, admin panels, and account management. use askama::Template; use crate::auth::SessionUser; use crate::types::*; use super::CsrfTokenOption; // ============================================================================ // Dashboard Pages // ============================================================================ /// Main user dashboard page with tabbed navigation. #[derive(Template)] #[template(path = "dashboards/dashboard-user.html")] #[allow(dead_code)] // Fields used by Askama template pub struct DashboardUserTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub user: User, pub transactions: Vec, /// Used to conditionally show the first-run onboarding banner. pub projects: Vec, /// Onboarding checklist for new creators (None once all steps complete). pub onboarding: Option, /// Show "Show setup checklist" link when checklist was dismissed but steps remain. pub show_checklist_recovery: bool, /// Whether user has MT forum memberships (controls Forums tab visibility). pub has_mt_memberships: bool, // Suspension context (for banner) pub suspended: bool, pub suspension_reason: Option, pub has_pending_appeal: bool, pub appeal_decision: Option, pub appeal_response: Option, /// One-time warning when a breached password is detected (cleared after display). pub password_warning: Option, /// Whether the user has self-deactivated their account (limbo state). pub deactivated: bool, /// Whether this creator has voluntarily paused their account. pub creator_paused: bool, /// Whether git hosting is configured on this server (controls SSH Keys tab visibility). pub git_enabled: bool, } /// Project dashboard page with stats, content list, and management tabs. #[derive(Template)] #[template(path = "dashboards/dashboard-project.html")] #[allow(dead_code)] // Fields used by Askama template pub struct DashboardProjectTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub project: Project, pub creator_username: String, pub stats: Vec, pub items: Vec, /// Whether this creator has connected their Stripe account (controls Subscriptions tab visibility). pub stripe_connected: bool, /// Whether this project has the "blog" feature enabled (controls Blog tab visibility). pub has_blog: bool, /// Whether git hosting is configured on this server (controls Code tab visibility). pub git_enabled: bool, /// Whether this project has the "cloud_sync" feature enabled (controls Cloud Sync tab visibility). pub synckit_enabled: bool, } /// Item management dashboard shell with tabbed navigation (content loaded via HTMX). #[derive(Template)] #[template(path = "dashboards/dashboard-item.html")] pub struct DashboardItemTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub item: Item, pub project_title: String, pub project_slug: String, } // ============================================================================ // Admin // ============================================================================ /// Admin waitlist management page with filtering and invite controls. #[derive(Template)] #[template(path = "dashboards/admin-waitlist.html")] pub struct AdminWaitlistTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub stats: WaitlistStats, pub entries: Vec, pub current_filter: String, pub admin_active_page: &'static str, } /// Admin user management page. #[derive(Template)] #[template(path = "dashboards/admin-users.html")] pub struct AdminUsersTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub users: Vec, pub total_users: usize, pub total_suspended: usize, pub current_filter: String, pub current_page: i64, pub total_pages: i64, pub admin_active_page: &'static str, } /// Per-layer health stat displayed in the dashboard's top panel. #[derive(Clone)] pub struct LayerHealthCard { pub layer: String, pub total: i64, pub success_rate_pct: i32, pub error_rate_pct: i32, pub fail_count: i64, pub status_badge: &'static str, pub last_seen: String, } /// Admin upload review queue page. #[derive(Template)] #[template(path = "dashboards/admin-uploads.html")] pub struct AdminUploadsTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub held_uploads: Vec, pub total_held: usize, pub admin_active_page: &'static str, pub layer_health: Vec, pub queue_pending: i64, pub queue_running: i64, pub recent_history: Vec, pub history_total: usize, } /// Full audit log for the scan pipeline (Phase 2b). #[derive(Template)] #[template(path = "dashboards/admin-scan-audit.html")] pub struct AdminScanAuditTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub admin_active_page: &'static str, pub entries: Vec, pub filter_action: String, pub filter_admin: String, pub filter_since_days: String, } /// Admin appeals queue page. #[derive(Template)] #[template(path = "dashboards/admin-appeals.html")] pub struct AdminAppealsTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub appeals: Vec, pub admin_active_page: &'static str, } /// Admin reports queue page. #[derive(Template)] #[template(path = "dashboards/admin-reports.html")] pub struct AdminReportsTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub reports: Vec, pub stats: ReportStats, pub current_filter: String, pub admin_active_page: &'static str, } /// Admin email signups page. #[derive(Template)] #[template(path = "dashboards/admin-signups.html")] pub struct AdminSignupsTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub signups: Vec, pub total: i64, pub admin_active_page: &'static str, } /// Admin metrics dashboard page. #[derive(Template)] #[template(path = "dashboards/admin-metrics.html")] pub struct AdminMetricsTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub admin_active_page: &'static str, pub uptime: String, pub total_requests: u64, pub error_rate: f64, pub total_errors: u64, pub pool_max: u32, pub pool_active: u32, pub pool_idle: u32, pub top_routes: Vec, pub error_breakdown: Vec, } /// A row in the top routes table. pub struct RouteMetric { pub method: String, pub path: String, pub status: String, pub count: u64, } /// A row in the error breakdown table. pub struct ErrorMetric { pub kind: String, pub count: u64, } // ============================================================================ // Export & Account Management // ============================================================================ /// Data export portal for the no-lock-in guarantee. #[derive(Template)] #[template(path = "dashboards/dashboard-export.html")] pub struct ExportPortalTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, /// Whether the user has any exportable content (projects, items, files). pub has_content: bool, /// Human-readable total size of exportable data (e.g. "12.3 MB"). pub content_size: String, } /// Data import portal for migrating from other platforms. #[derive(Template)] #[template(path = "dashboards/dashboard-import.html")] pub struct ImportPortalTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub projects: Vec, pub jobs: Vec, } /// Minimal project info for the import page project selector. pub struct ImportProjectOption { pub id: String, pub title: String, } /// A row in the import history table. pub struct ImportJobRow { pub source: String, pub status: String, pub total_rows: i32, pub created_rows: i32, pub created_at: chrono::DateTime, } /// Account deletion confirmation page with username verification. #[derive(Template)] #[template(path = "dashboards/dashboard-delete-account.html")] pub struct DeleteAccountTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub username: String, } /// Blog post editor page (create/edit). #[derive(Template)] #[template(path = "dashboards/dashboard-blog-editor.html")] pub struct BlogEditorTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub project_id: String, pub project_slug: String, pub editing: bool, pub post_id: String, pub post_title: String, pub post_slug: String, pub post_body: String, pub post_is_published: bool, /// Whether this editor is for the platform changelog project. Gates the /// owner-only "Show on landing" control so it never appears on a regular /// creator's blog, where the flag would be inert. pub is_changelog_project: bool, /// Current value of the post's landing flag (false for new posts). pub post_show_on_landing: bool, } /// HTMX partial: onboarding checklist (returned by the restore handler). #[derive(Template)] #[template(path = "partials/onboarding_checklist.html")] pub struct OnboardingChecklistPartialTemplate { pub checklist: OnboardingChecklist, } // License key and promo code view types live in crate::types (LicenseKeyRow, PromoCodeRow). // ============================================================================ // Creation Wizards // ============================================================================ /// Step navigation item for the wizard sidebar. pub struct StepNavItem { pub name: &'static str, pub label: &'static str, pub state: &'static str, // "completed", "active", "pending" } /// A subscription tier row for the wizard monetization/preview steps. pub struct WizardTierRow { pub id: String, pub name: String, pub price_display: String, pub price_dollars: String, pub description: String, } /// Full page: project creation wizard. #[derive(Template)] #[template(path = "wizards/wizard_project.html")] pub struct WizardProjectTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub nav: Vec, pub project_features: &'static [(&'static str, &'static str, &'static str)], } /// Full page: item creation wizard. #[derive(Template)] #[template(path = "wizards/wizard_item.html")] pub struct WizardItemTemplate { pub csrf_token: CsrfTokenOption, pub session_user: Option, pub nav: Vec, pub project_slug: String, pub item_type_cards: Vec<(&'static str, &'static str, &'static str)>, } // --- Project step partials --- /// Wizard step partial: project basics (title, slug, features, category). #[derive(Template)] #[template(path = "wizards/steps/project/basics.html")] pub struct WizardProjectBasicsTemplate { pub nav: Vec, pub slug: String, pub project_features: &'static [(&'static str, &'static str, &'static str)], pub title: String, pub features: Vec, pub description: String, pub category_name: String, pub ai_tier: String, pub ai_disclosure: String, } /// Wizard step partial: project appearance (cover image upload). #[derive(Template)] #[template(path = "wizards/steps/project/appearance.html")] pub struct WizardProjectAppearanceTemplate { pub nav: Vec, pub slug: String, pub project_id: String, pub cover_image_url: Option, pub project_title: String, } /// Wizard step partial: project monetization (pricing model, tiers, Stripe). #[derive(Template)] #[template(path = "wizards/steps/project/monetization.html")] pub struct WizardProjectMonetizationTemplate { pub nav: Vec, pub slug: String, pub tiers: Vec, pub stripe_connected: bool, /// Current pricing model string value (free, buy_once, pwyw, subscription). pub pricing_model: String, /// Current fixed price in dollars (for buy_once). pub price_dollars: String, /// Current PWYW minimum in dollars. pub pwyw_min_dollars: String, } /// Wizard step partial: project first content prompt (item count gate). #[derive(Template)] #[template(path = "wizards/steps/project/first_content.html")] pub struct WizardProjectFirstContentTemplate { pub nav: Vec, pub slug: String, pub item_count: u32, } /// Wizard step partial: project preview and publish confirmation. #[derive(Template)] #[template(path = "wizards/steps/project/preview.html")] #[allow(dead_code)] pub struct WizardProjectPreviewTemplate { pub csrf_token: CsrfTokenOption, pub nav: Vec, pub slug: String, pub title: String, pub features: Vec, pub description: String, pub cover_image_url: Option, pub category_name: Option, pub tier_count: u32, pub item_count: u32, pub tiers: Vec, pub is_public: bool, /// Human-readable pricing display (e.g. "Free", "$9.99", "PWYW"). pub pricing_display: String, } // --- Item step partials --- /// Wizard step partial: item type selection (text, audio, video, software, bundle). #[derive(Template)] #[template(path = "wizards/steps/item/type.html")] pub struct WizardItemTypeTemplate { pub nav: Vec, pub project_slug: String, pub item_id: String, pub item_type_cards: Vec<(&'static str, &'static str, &'static str)>, pub selected_type: String, } /// Wizard step partial: item basics (title, description, cover image). #[derive(Template)] #[template(path = "wizards/steps/item/basics.html")] pub struct WizardItemBasicsTemplate { pub nav: Vec, pub project_slug: String, pub item_id: String, pub title: String, pub description: String, pub cover_image_url: Option, } /// Wizard step partial: item content (body editor, bundle picker). #[derive(Template)] #[template(path = "wizards/steps/item/content.html")] pub struct WizardItemContentTemplate { pub nav: Vec, pub project_slug: String, pub project_id: String, pub item_id: String, pub item_type: String, pub body: String, /// Non-bundle items in the project available for inclusion. pub bundleable_items: Vec, /// IDs of items already selected for this bundle. pub selected_bundle_ids: Vec, /// IDs of items currently marked unlisted. pub unlisted_ids: Vec, } /// Lightweight item info for the bundle item picker. pub struct BundleableItem { pub id: String, pub title: String, pub item_type: String, } /// Wizard step partial: item sections (reorderable content sections). #[derive(Template)] #[template(path = "wizards/steps/item/sections.html")] pub struct WizardItemSectionsTemplate { pub nav: Vec, pub project_slug: String, pub item_id: String, pub sections: Vec, } /// Wizard step partial: item pricing (model selection, price entry). #[derive(Template)] #[template(path = "wizards/steps/item/pricing.html")] pub struct WizardItemPricingTemplate { pub nav: Vec, pub project_slug: String, pub item_id: String, pub pricing_model: String, pub price_dollars: String, pub pwyw_suggested_dollars: String, pub pwyw_min_dollars: String, } /// Wizard step partial: item preview and publish confirmation. #[derive(Template)] #[template(path = "wizards/steps/item/preview.html")] pub struct WizardItemPreviewTemplate { pub csrf_token: CsrfTokenOption, pub nav: Vec, pub project_slug: String, pub item_id: String, pub title: String, pub item_type: String, pub description: String, pub price_display: String, pub tag_names: Vec, pub has_content: bool, pub is_public: bool, }