max / makenotwork
- Co-Authored-By
- Claude Opus 5 (1M context) <noreply@anthropic.com>
18 files changed,
+895 insertions,
-300 deletions
| @@ -8527,23 +8527,6 @@ | |||
| 8527 | 8527 | } | |
| 8528 | 8528 | .stripe-actions-disconnect { margin-left: auto; } | |
| 8529 | 8529 | ||
| 8530 | - | .payout-stats-grid { | |
| 8531 | - | display: grid; | |
| 8532 | - | grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); | |
| 8533 | - | gap: var(--gap-section); | |
| 8534 | - | margin-top: var(--gap-section); | |
| 8535 | - | padding-top: var(--gap-section); | |
| 8536 | - | border-top: 1px solid var(--border); | |
| 8537 | - | } | |
| 8538 | - | ||
| 8539 | - | .payouts-disabled-notice { | |
| 8540 | - | margin-top: var(--gap-section); | |
| 8541 | - | padding: var(--gap-section); | |
| 8542 | - | background: var(--warning); | |
| 8543 | - | color: var(--primary-light); | |
| 8544 | - | font-size: var(--text-note); | |
| 8545 | - | } | |
| 8546 | - | ||
| 8547 | 8530 | .fee-breakdown { | |
| 8548 | 8531 | display: grid; | |
| 8549 | 8532 | grid-template-columns: 1fr 1fr; | |
| @@ -10892,22 +10875,6 @@ | |||
| 10892 | 10875 | USER DASHBOARD TABS (support / sessions / buyer contacts) | |
| 10893 | 10876 | =========================================== */ | |
| 10894 | 10877 | ||
| 10895 | - | /* Support tab (templates/partials/tabs/user_support.html). */ | |
| 10896 | - | .support-tab .support-intro-meta { | |
| 10897 | - | margin-bottom: var(--gap-pane); | |
| 10898 | - | font-size: var(--text-note); | |
| 10899 | - | opacity: 0.8; | |
| 10900 | - | } | |
| 10901 | - | .support-tab .support-form { max-width: 600px; } | |
| 10902 | - | .support-tab .response-times { | |
| 10903 | - | margin-top: var(--gap-page); | |
| 10904 | - | font-size: var(--text-note); | |
| 10905 | - | opacity: 0.7; | |
| 10906 | - | } | |
| 10907 | - | .support-tab .response-times ul { | |
| 10908 | - | margin: var(--gap-bound) 0 0 var(--gap-pane); | |
| 10909 | - | } | |
| 10910 | - | ||
| 10911 | 10878 | /* Sessions tab (templates/partials/tabs/user_sessions.html). */ | |
| 10912 | 10879 | .sessions-tab .sessions-table { width: 100%; } | |
| 10913 | 10880 | .sessions-tab .device-cell { |
| @@ -47,6 +47,7 @@ | |||
| 47 | 47 | pub mod library_contacts; | |
| 48 | 48 | pub mod library_tabs; | |
| 49 | 49 | pub mod media_picker; | |
| 50 | + | pub mod payout_summary; | |
| 50 | 51 | pub mod project_content; | |
| 51 | 52 | pub mod project_tabs; | |
| 52 | 53 | pub mod rich_field; | |
| @@ -54,6 +55,8 @@ | |||
| 54 | 55 | pub mod ssh_keys; | |
| 55 | 56 | pub mod upload_field; | |
| 56 | 57 | pub mod user_analytics; | |
| 58 | + | pub mod user_projects; | |
| 59 | + | pub mod user_support; | |
| 57 | 60 | pub mod user_tabs; | |
| 58 | 61 | pub mod version_delete_act; | |
| 59 | 62 | pub mod widgets; | |
| @@ -222,6 +225,7 @@ | |||
| 222 | 225 | library_contacts::PATH, | |
| 223 | 226 | buyer_contacts::PATH, | |
| 224 | 227 | user_analytics::PATH, | |
| 228 | + | payout_summary::PATH, | |
| 225 | 229 | forum_memberships::LIBRARY_PATH, | |
| 226 | 230 | forum_memberships::SETTINGS_PATH, | |
| 227 | 231 | ]; | |
| @@ -238,6 +242,7 @@ | |||
| 238 | 242 | library_contacts::SCREEN, | |
| 239 | 243 | buyer_contacts::SCREEN, | |
| 240 | 244 | user_analytics::SCREEN, | |
| 245 | + | payout_summary::SCREEN, | |
| 241 | 246 | forum_memberships::LIBRARY_SCREEN, | |
| 242 | 247 | forum_memberships::SETTINGS_SCREEN, | |
| 243 | 248 | ]; | |
| @@ -283,6 +288,10 @@ | |||
| 283 | 288 | user_analytics::PATH, | |
| 284 | 289 | mount(app, user_analytics::screen, &[], user_analytics::renderer), | |
| 285 | 290 | ), | |
| 291 | + | ( | |
| 292 | + | payout_summary::PATH, | |
| 293 | + | mount(app, payout_summary::screen, &[], payout_summary::renderer), | |
| 294 | + | ), | |
| 286 | 295 | ( | |
| 287 | 296 | forum_memberships::SETTINGS_PATH, | |
| 288 | 297 | mount( |
| @@ -104,9 +104,12 @@ | |||
| 104 | 104 | const TABS: &[Tab] = &[ | |
| 105 | 105 | Tab { | |
| 106 | 106 | label: "Projects", | |
| 107 | - | panel: "user-projects", | |
| 107 | + | panel: super::user_projects::REGION, | |
| 108 | 108 | route: "projects", | |
| 109 | 109 | gate: Gate::Creator, | |
| 110 | + | // `None` although the panel is described: `screen` means "a quasi route | |
| 111 | + | // answers this address", and Projects is a fill on the Askama handler | |
| 112 | + | // that keeps the ETag. See `super::user_projects`. | |
| 110 | 113 | screen: None, | |
| 111 | 114 | }, | |
| 112 | 115 | Tab { | |
| @@ -132,9 +135,11 @@ | |||
| 132 | 135 | }, | |
| 133 | 136 | Tab { | |
| 134 | 137 | label: "Support", | |
| 135 | - | panel: "user-support", | |
| 138 | + | panel: super::user_support::REGION, | |
| 136 | 139 | route: "support", | |
| 137 | 140 | gate: Gate::Always, | |
| 141 | + | // Described, but as a fill on the Askama handler rather than a quasi | |
| 142 | + | // route, so the strip still fetches it. See `super::user_support`. | |
| 138 | 143 | screen: None, | |
| 139 | 144 | }, | |
| 140 | 145 | ]; |
| @@ -225,11 +225,9 @@ | |||
| 225 | 225 | UserSettingsTabTemplate, | |
| 226 | 226 | UserAccountTabTemplate, | |
| 227 | 227 | UserPaymentsTabTemplate, | |
| 228 | - | UserProjectsTabTemplate, | |
| 229 | 228 | UserCreatorTabTemplate, | |
| 230 | 229 | ProjectOverviewTabTemplate, | |
| 231 | 230 | ProjectAnalyticsTabTemplate, | |
| 232 | - | PayoutSummaryPartialTemplate, | |
| 233 | 231 | ProjectSettingsTabTemplate, | |
| 234 | 232 | ProjectCodeTabTemplate, | |
| 235 | 233 | ProjectSubscriptionsTabTemplate, | |
| @@ -258,7 +256,6 @@ | |||
| 258 | 256 | // Media library | |
| 259 | 257 | UserMediaTabTemplate, | |
| 260 | 258 | // Support | |
| 261 | - | UserSupportTabTemplate, | |
| 262 | 259 | // Collections | |
| 263 | 260 | CollectionTemplate, | |
| 264 | 261 | // Library tabs |
| @@ -8,9 +8,9 @@ | |||
| 8 | 8 | use crate::types::{ | |
| 9 | 9 | AdminAppealRow, AdminHeldUploadRow, AdminReportRow, AdminUserRow, AdminWaitlistRow, | |
| 10 | 10 | BlogPostDashboardRow, ChartBar, Collection, ContentItem, DiscoverItem, DiscoverProject, | |
| 11 | - | InviteCodeDisplay, Item, ItemSection, LicenseKeyRow, PayoutSummary, Project, ProjectCard, | |
| 12 | - | ProjectMemberRow, PromoCodeRow, SaleRow, SidebarView, StatCard, SubscriptionTier, SyncAppRow, | |
| 13 | - | TipReceived, Transaction, User, UserSubscription, Version, WaitlistEntry, WaveStats, | |
| 11 | + | InviteCodeDisplay, Item, ItemSection, LicenseKeyRow, Project, ProjectCard, ProjectMemberRow, | |
| 12 | + | PromoCodeRow, SaleRow, SidebarView, StatCard, SubscriptionTier, SyncAppRow, TipReceived, | |
| 13 | + | Transaction, User, UserSubscription, Version, WaitlistEntry, WaveStats, | |
| 14 | 14 | }; | |
| 15 | 15 | ||
| 16 | 16 | use super::CsrfTokenOption; | |
| @@ -340,14 +340,6 @@ | |||
| 340 | 340 | pub can_create_projects: bool, | |
| 341 | 341 | } | |
| 342 | 342 | ||
| 343 | - | /// Dashboard tab: user's projects list with create button. | |
| 344 | - | #[derive(Template)] | |
| 345 | - | #[template(path = "partials/tabs/user_projects.html")] | |
| 346 | - | pub struct UserProjectsTabTemplate { | |
| 347 | - | pub projects: Vec<ProjectCard>, | |
| 348 | - | pub can_create_projects: bool, | |
| 349 | - | } | |
| 350 | - | ||
| 351 | 343 | /// Creator tab in the user dashboard showing invite/waitlist status. | |
| 352 | 344 | #[derive(Template)] | |
| 353 | 345 | #[template(path = "partials/tabs/user_creator.html")] | |
| @@ -597,13 +589,6 @@ | |||
| 597 | 589 | pub storage_display: String, | |
| 598 | 590 | } | |
| 599 | 591 | ||
| 600 | - | /// Support tab in the user dashboard, submit a support ticket. | |
| 601 | - | #[derive(Template)] | |
| 602 | - | #[template(path = "partials/tabs/user_support.html")] | |
| 603 | - | pub struct UserSupportTabTemplate { | |
| 604 | - | pub email: String, | |
| 605 | - | } | |
| 606 | - | ||
| 607 | 592 | // Library Tab Partials | |
| 608 | 593 | ||
| 609 | 594 | /// Library purchases tab. | |
| @@ -642,15 +627,6 @@ | |||
| 642 | 627 | pub revenue: String, | |
| 643 | 628 | } | |
| 644 | 629 | ||
| 645 | - | /// Stripe payout-summary card, HTMX-loaded into the Payments tab so the tab | |
| 646 | - | /// render never blocks on the Stripe balance round-trip (ultra-fuzz Run 11 Perf SER-2). | |
| 647 | - | #[derive(Template)] | |
| 648 | - | #[template(path = "partials/tabs/payout_summary.html")] | |
| 649 | - | pub struct PayoutSummaryPartialTemplate { | |
| 650 | - | pub payout_summary: Option<PayoutSummary>, | |
| 651 | - | pub stripe_payouts_enabled: bool, | |
| 652 | - | } | |
| 653 | - | ||
| 654 | 630 | /// SSH keys list partial for HTMX updates. | |
| 655 | 631 | #[derive(Template)] | |
| 656 | 632 | #[template(path = "partials/ssh_keys_list.html")] |
| @@ -1,13 +1,6 @@ | |||
| 1 | 1 | //! View types for money flows: payouts, transactions, tips, subscriptions, | |
| 2 | 2 | //! license keys, promo codes, and sales. | |
| 3 | 3 | ||
| 4 | - | /// Payout summary derived from the Stripe Balance API. | |
| 5 | - | #[derive(Clone)] | |
| 6 | - | pub struct PayoutSummary { | |
| 7 | - | pub available: String, | |
| 8 | - | pub pending: String, | |
| 9 | - | } | |
| 10 | - | ||
| 11 | 4 | /// A single bar in a revenue bar chart. | |
| 12 | 5 | #[derive(Clone)] | |
| 13 | 6 | pub struct ChartBar { |
| @@ -66,6 +66,11 @@ | |||
| 66 | 66 | quasi::buyer_contacts::PATH, | |
| 67 | 67 | "contacts-section", | |
| 68 | 68 | ), | |
| 69 | + | ( | |
| 70 | + | "payout_summary", | |
| 71 | + | quasi::payout_summary::PATH, | |
| 72 | + | quasi::payout_summary::REGION, | |
| 73 | + | ), | |
| 69 | 74 | ( | |
| 70 | 75 | "user_analytics", | |
| 71 | 76 | quasi::user_analytics::PATH, |