From abc8230c04a787045a599327455445585edff46a Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Thu, 13 Nov 2025 15:22:48 -0500 Subject: Implement full account management page - Display account information (email, creation date) - Show subscription details (plan, status, features) - Display cancellation warning if subscription ending - Add Upgrade button for free users - Add Manage Subscription button for paid users (goes to Stripe portal) - Add logout button in Actions section - Replace Coming Soon placeholder with functional UI Addresses account management epic tasks. Amp-Thread-ID: https://ampcode.com/threads/T-8edacbeb-b343-49ca-b524-1c999272acb6 Co-authored-by: Amp --- Biz/PodcastItLater/Web.py | 157 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 9 deletions(-) (limited to 'Biz/PodcastItLater/Web.py') diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py index f4c65b1..af603e2 100644 --- a/Biz/PodcastItLater/Web.py +++ b/Biz/PodcastItLater/Web.py @@ -1064,7 +1064,7 @@ def verify_magic_link(request: Request) -> Response: @app.get("/account") def account_page(request: Request) -> html.html | RedirectResponse: - """Account management page (coming soon).""" + """Account management page.""" user_id = request.session.get("user_id") if not user_id: return RedirectResponse(url="/?error=login_required") @@ -1073,6 +1073,12 @@ def account_page(request: Request) -> html.html | RedirectResponse: if not user: return RedirectResponse(url="/?error=user_not_found") + # Get subscription details + tier = user.get("plan_tier", "free") + tier_info = Billing.get_tier_info(tier) + subscription_status = user.get("subscription_status", "") + cancel_at_period_end = user.get("cancel_at_period_end", 0) == 1 + return html.html( html.head( html.meta(charset="utf-8"), @@ -1085,6 +1091,11 @@ def account_page(request: Request) -> html.html | RedirectResponse: content="light dark", ), html.title("Account - PodcastItLater"), + html.script( + src="https://unpkg.com/htmx.org@1.9.10", + integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC", + crossorigin="anonymous", + ), ), html.body( html.style( @@ -1117,20 +1128,148 @@ def account_page(request: Request) -> html.html | RedirectResponse: ], ), ), + # Account info section html.div( + html.h4( + html.i(classes=["bi", "bi-envelope-fill", "me-2"]), + "Account Information", + classes=["mb-3"], + ), html.div( + html.div( + html.strong("Email: "), + user["email"], + classes=["mb-2"], + ), + html.div( + html.strong("Account Created: "), + user["created_at"], + classes=["mb-2"], + ), + classes=["card-body"], + ), + classes=["card", "mb-4"], + ), + # Subscription section + html.div( + html.h4( html.i( - classes=["bi", "bi-info-circle-fill", "me-2"], + classes=["bi", "bi-credit-card-fill", "me-2"], + ), + "Subscription", + classes=["mb-3"], + ), + html.div( + html.div( + html.strong("Plan: "), + tier_info["name"], + f" ({tier_info['price']})", + classes=["mb-2"], ), - html.strong("Coming Soon"), - html.p( - "Account management features including " - "subscription management, usage history, and " - "settings will be available here.", - classes=["mb-0", "mt-2"], + html.div( + html.strong("Status: "), + subscription_status.title() + if subscription_status + else "Active", + classes=["mb-2"], + ) + if tier == "paid" + else html.div(), + html.div( + html.i( + classes=[ + "bi", + "bi-info-circle", + "me-1", + ], + ), + "Your subscription will cancel at the end " + "of the billing period.", + classes=[ + "alert", + "alert-warning", + "mt-2", + "mb-2", + ], + ) + if cancel_at_period_end + else html.div(), + html.div( + html.strong("Features: "), + tier_info["description"], + classes=["mb-3"], + ), + # Subscription actions + html.div( + html.a( + html.i( + classes=[ + "bi", + "bi-arrow-up-circle", + "me-1", + ], + ), + "Upgrade to Paid Plan", + href="#", + hx_post="/billing/checkout", + hx_vals='{"tier": "paid"}', + classes=[ + "btn", + "btn-success", + "me-2", + ], + ) + if tier == "free" + else html.a( + html.i( + classes=[ + "bi", + "bi-gear-fill", + "me-1", + ], + ), + "Manage Subscription", + href="#", + hx_post="/billing/portal", + classes=[ + "btn", + "btn-primary", + "me-2", + ], + ), + ), + classes=["card-body"], + ), + classes=["card", "mb-4"], + ), + # Actions section + html.div( + html.h4( + html.i(classes=["bi", "bi-sliders", "me-2"]), + "Actions", + classes=["mb-3"], + ), + html.div( + html.a( + html.i( + classes=[ + "bi", + "bi-box-arrow-right", + "me-1", + ], + ), + "Logout", + href="/logout", + classes=[ + "btn", + "btn-outline-secondary", + "mb-2", + "me-2", + ], ), - classes=["alert", "alert-info"], + classes=["card-body"], ), + classes=["card", "mb-4"], ), classes=["mb-4"], ), -- cgit v1.2.3