From 14af38a21dc8e790b9ddc29e241784fd769dc3fc Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Sun, 9 Nov 2025 20:32:34 -0500 Subject: PodcastItLater: Add Stripe billing and mobile responsiveness - Implemented complete Stripe integration (Billing.py) - Checkout sessions for subscription upgrades - Billing portal for subscription management - Webhook handling for subscription events - Usage tracking with tier-based limits (free: 10, personal: 50, pro: unlimited) - Added billing page UI (BillingPage component) - Current plan display with usage stats - Pricing cards for all tiers with upgrade buttons - Manage subscription button for paid users - Success/error messaging - Database migrations for billing - Added plan_tier, stripe_customer_id, stripe_subscription_id - Added subscription_status, period dates, cancel_at_period_end - Created stripe_events table for webhook idempotency - Added get_usage() method for usage tracking - Made UI mobile-friendly and responsive - Added viewport meta tags to all pages - Replaced pages.HtmlPage with raw html.html for meta tag control - Responsive button layouts with flexbox wrapping - Responsive pricing cards (1 col mobile, 2 col tablet, 3 col desktop) - Touch-friendly forms and buttons (44px minimum) - Responsive padding and containers - Admin tables with horizontal scroll - Added Stripe testing guide (STRIPE_TESTING.md) - Fixed CSS bug in pricing cards (cardh-100 text rendering) - Updated tasks: completed t-144e7lF, t-1pIV0ZF, t-1s8ADC0 Amp-Thread-ID: https://ampcode.com/threads/T-42fd5fb3-3dc5-4cbc-a9a3-78db9e13187e Co-authored-by: Amp --- Biz/PodcastItLater/Admin.py | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'Biz/PodcastItLater/Admin.py') diff --git a/Biz/PodcastItLater/Admin.py b/Biz/PodcastItLater/Admin.py index 5772256..7dd0c50 100644 --- a/Biz/PodcastItLater/Admin.py +++ b/Biz/PodcastItLater/Admin.py @@ -13,7 +13,6 @@ Admin pages and functionality for managing users and queue items. # : dep pytest-mock import Biz.PodcastItLater.Core as Core import ludic.catalog.layouts as layouts -import ludic.catalog.pages as pages import ludic.html as html # i need to import these unused because bild cannot get local transitive python @@ -305,16 +304,24 @@ class AdminUsers(Component[AnyChildren, AdminUsersAttrs]): """Admin view for managing users.""" @override - def render(self) -> pages.HtmlPage: + def render(self) -> html.html: users = self.attrs["users"] - return pages.HtmlPage( - pages.Head( - title="PodcastItLater - User Management", - htmx_version="1.9.10", - load_styles=False, + return html.html( + html.head( + html.meta(charset="utf-8"), + html.meta( + name="viewport", + content="width=device-width, initial-scale=1", + ), + html.title("PodcastItLater - User Management"), + html.script( + src="https://unpkg.com/htmx.org@1.9.10", + integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC", + crossorigin="anonymous", + ), ), - pages.Body( + html.body( create_bootstrap_styles(), html.div( html.h1( @@ -371,18 +378,26 @@ class AdminView(Component[AnyChildren, AdminViewAttrs]): """Admin view showing all queue items and episodes in tables.""" @override - def render(self) -> pages.HtmlPage: + def render(self) -> html.html: queue_items = self.attrs["queue_items"] episodes = self.attrs["episodes"] status_counts = self.attrs.get("status_counts", {}) - return pages.HtmlPage( - pages.Head( - title="PodcastItLater - Admin Queue Status", - htmx_version="1.9.10", - load_styles=False, + return html.html( + html.head( + html.meta(charset="utf-8"), + html.meta( + name="viewport", + content="width=device-width, initial-scale=1", + ), + html.title("PodcastItLater - Admin Queue Status"), + html.script( + src="https://unpkg.com/htmx.org@1.9.10", + integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC", + crossorigin="anonymous", + ), ), - pages.Body( + html.body( create_bootstrap_styles(), html.div( AdminView._render_content( -- cgit v1.2.3