diff --git a/internal/handler/handler.go b/internal/handler/handler.go index c05e433..92862ed 100644 --- a/internal/handler/handler.go +++ b/internal/handler/handler.go @@ -49,6 +49,7 @@ mux.HandleFunc("/auth/logout", h.handleLogout) mux.HandleFunc("/contacts", h.requireAuth(h.handleContacts)) mux.HandleFunc("/audit", h.requireAuth(h.handleAuditLog)) mux.HandleFunc("/analytics", h.requireAuth(h.handleAnalytics)) + mux.HandleFunc("/subscription", h.requireAuth(h.handleSubscription)) // Admin CRUD mux.HandleFunc("/admin", h.requireAdmin(h.handleAdmin)) diff --git a/internal/handler/subscription.go b/internal/handler/subscription.go new file mode 100644 index 0000000..ebb0ef0 --- /dev/null +++ b/internal/handler/subscription.go @@ -0,0 +1,26 @@ +package handler + +import ( + "net/http" + + "dealroom/templates" +) + +func (h *Handler) handleSubscription(w http.ResponseWriter, r *http.Request) { + profile := getProfile(r.Context()) + + var roomsUsed, usersUsed int + h.db.QueryRow("SELECT COUNT(*) FROM deals WHERE organization_id = ? AND is_archived = 0", profile.OrganizationID).Scan(&roomsUsed) + h.db.QueryRow("SELECT COUNT(*) FROM profiles WHERE organization_id = ?", profile.OrganizationID).Scan(&usersUsed) + + stats := &templates.SubscriptionStats{ + RoomsUsed: roomsUsed, + RoomsLimit: 15, + UsersUsed: usersUsed, + UsersLimit: 25, + StorageUsed: "23GB", + StorageLimit: "100GB", + } + + templates.SubscriptionPage(profile, stats).Render(r.Context(), w) +} diff --git a/templates/layout.templ b/templates/layout.templ index affc5c4..7e734a5 100644 --- a/templates/layout.templ +++ b/templates/layout.templ @@ -54,6 +54,7 @@ templ Layout(profile *model.Profile, activePage string) { @sidebarLink("/contacts", "Contacts", activePage == "contacts", svgUsers()) @sidebarLink("/team", "Team", activePage == "team", svgTeam()) @sidebarLink("/audit", "Audit Log", activePage == "audit", svgShield()) + @sidebarLink("/subscription", "Subscription", activePage == "subscription", svgCreditCard()) @sidebarLink("/admin", "Admin", activePage == "admin", svgCog()) } if rbac.IsBuyer(profile.Role) { @@ -164,6 +165,10 @@ templ svgTeam() { } +templ svgCreditCard() { + +} + templ svgShield() { } diff --git a/templates/subscription.templ b/templates/subscription.templ new file mode 100644 index 0000000..0f7e8e5 --- /dev/null +++ b/templates/subscription.templ @@ -0,0 +1,141 @@ +package templates + +import "dealroom/internal/model" +import "fmt" + +type SubscriptionStats struct { + RoomsUsed int + RoomsLimit int + UsersUsed int + UsersLimit int + StorageUsed string + StorageLimit string +} + +templ SubscriptionPage(profile *model.Profile, stats *SubscriptionStats) { + @Layout(profile, "subscription") { +
+
+

Subscription

+

Manage your plan and usage.

+
+ + +
+
+
+
+

Growth Plan

+ Current +
+

$799/month

+
+
+
+
+
+ Deal Rooms + { fmt.Sprintf("%d / %d", stats.RoomsUsed, stats.RoomsLimit) } +
+
+
+
+
+
+
+ Users + { fmt.Sprintf("%d / %d", stats.UsersUsed, stats.UsersLimit) } +
+
+
+
+
+
+
+ Storage + { stats.StorageUsed } / { stats.StorageLimit } +
+
+
+
+
+
+
+ + +
+ +
+

Starter

+

$299/mo

+
    +
  • + + 3 deal rooms +
  • +
  • + + 5 users +
  • +
  • + + 10GB storage +
  • +
+ +
+ + +
+
Current Plan
+

Growth

+

$799/mo

+
    +
  • + + 15 deal rooms +
  • +
  • + + 25 users +
  • +
  • + + 100GB storage +
  • +
+ +
+ + +
+

Enterprise

+

Custom

+
    +
  • + + Unlimited deal rooms +
  • +
  • + + Unlimited users +
  • +
  • + + 1TB storage +
  • +
+ +
+
+
+ } +} + +func usageWidth(used int, limit int) templ.Attributes { + pct := 0 + if limit > 0 { + pct = (used * 100) / limit + } + return templ.Attributes{"style": fmt.Sprintf("width: %d%%", pct)} +}