feat(sprint-6): Phase 3 — Stripe integration (SEPA + PayPal + Card)
- V7 migration: subscriptions table with plan tiers - Subscription entity + PlanTier/SubscriptionStatus enums - StripeService: customer creation, checkout, portal, webhook handling - SubscriptionController: /api/v1/billing endpoints - Webhook handler: invoice.paid, payment_failed, subscription.deleted/updated - Plan enforcement: member limit interceptor, trial expiry check - Frontend: /settings/billing page (plan card, usage, upgrade, portal link) - Trial expired banner on all admin pages - React Query hooks (useSubscriptionQuery, checkout/portal mutations) - Stripe Java SDK 28.2.0 - Full i18n (de/en) for billing namespace
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query"
|
||||
|
||||
import { apiClient } from "@/lib/api-client"
|
||||
|
||||
export interface SubscriptionData {
|
||||
planTier: string
|
||||
status: string
|
||||
memberLimit: number
|
||||
trialEndsAt: string | null
|
||||
currentPeriodStart: string | null
|
||||
currentPeriodEnd: string | null
|
||||
canceledAt: string | null
|
||||
hasStripeSubscription: boolean
|
||||
}
|
||||
|
||||
export function useSubscriptionQuery() {
|
||||
return useQuery({
|
||||
queryKey: ["billing", "subscription"],
|
||||
queryFn: () => apiClient<SubscriptionData>("/billing/subscription"),
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreateCheckoutMutation() {
|
||||
return useMutation({
|
||||
mutationFn: async (planTier: string) => {
|
||||
const data = await apiClient<{ url: string }>("/billing/checkout", {
|
||||
method: "POST",
|
||||
body: { planTier },
|
||||
})
|
||||
return data
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
window.location.href = data.url
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreatePortalMutation() {
|
||||
return useMutation({
|
||||
mutationFn: async () => {
|
||||
const data = await apiClient<{ url: string }>("/billing/portal", {
|
||||
method: "POST",
|
||||
})
|
||||
return data
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
window.location.href = data.url
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user