From c3c1513ac1ac9b4e5f48070c080f120a4eeaf69a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20M=C3=B6rling?= Date: Fri, 15 May 2026 20:30:15 +0200 Subject: [PATCH] feat: add payment page and wire compose submit to payment flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - api/payment.ts: payOrder(orderId) calls POST /api/payment/{id}/pay - api/orders.ts: add amountPaid (number|null) to Order type - PaymentRedirect.vue: route /betalning/:orderId, shows plate from query?plate, amount label (49 kr), green Betalt button, mock note: "Detta är en mock-betalning. I framtiden skickas du till Stripe." On click: calls payOrder, on success navigates to /orders, on failure shows error. Button disables and shows "Bearbetar..." while paying. - ComposePage.vue: after createOrder success, captures returned order object and navigates to /betalning/{orderId}?plate=... instead of the old direct-to-orders route - Router: add /betalning/:orderId route (name: payment, component: PaymentRedirect, meta: { requiresAuth: true }) --- frontend/src/api/orders.ts | 1 + frontend/src/api/payment.ts | 8 ++ frontend/src/pages/ComposePage.vue | 8 +- frontend/src/pages/PaymentRedirect.vue | 138 +++++++++++++++++++++++++ frontend/src/router/index.ts | 7 ++ 5 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 frontend/src/api/payment.ts create mode 100644 frontend/src/pages/PaymentRedirect.vue diff --git a/frontend/src/api/orders.ts b/frontend/src/api/orders.ts index 32a02b8..41dac62 100644 --- a/frontend/src/api/orders.ts +++ b/frontend/src/api/orders.ts @@ -5,6 +5,7 @@ export interface Order { plate: string status: string trackingId: string | null + amountPaid: number | null createdAt: string } diff --git a/frontend/src/api/payment.ts b/frontend/src/api/payment.ts new file mode 100644 index 0000000..dbaa53a --- /dev/null +++ b/frontend/src/api/payment.ts @@ -0,0 +1,8 @@ +import { request } from './client' +import type { Order } from './orders' + +export function payOrder(orderId: string): Promise { + return request(`/payment/${orderId}/pay`, { + method: 'POST', + }) +} diff --git a/frontend/src/pages/ComposePage.vue b/frontend/src/pages/ComposePage.vue index a133c27..7f90256 100644 --- a/frontend/src/pages/ComposePage.vue +++ b/frontend/src/pages/ComposePage.vue @@ -34,8 +34,12 @@ async function handleSubmit() { errorMessage.value = '' try { - await createOrder(plate.value, letterText.value) - await router.push({ name: 'orders' }) + const order = await createOrder(plate.value, letterText.value) + await router.push({ + name: 'payment', + params: { orderId: order.id }, + query: { plate: plate.value }, + }) } catch { errorMessage.value = 'Kunde inte skapa beställningen. Försök igen senare.' } finally { diff --git a/frontend/src/pages/PaymentRedirect.vue b/frontend/src/pages/PaymentRedirect.vue new file mode 100644 index 0000000..91320af --- /dev/null +++ b/frontend/src/pages/PaymentRedirect.vue @@ -0,0 +1,138 @@ + + + + + diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 0ec783b..8c4dbd5 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -7,6 +7,7 @@ import RegisterPage from '@/pages/RegisterPage.vue' import LoginPage from '@/pages/LoginPage.vue' import OrdersPage from '@/pages/OrdersPage.vue' import AdminPage from '@/pages/AdminPage.vue' +import PaymentRedirect from '@/pages/PaymentRedirect.vue' import { useAuthStore } from '@/stores/authStore' import { getActivePinia } from 'pinia' @@ -36,6 +37,12 @@ const router = createRouter({ component: AdminPage, meta: { requiresAuth: true, requiresAdmin: true }, }, + { + path: '/betalning/:orderId', + name: 'payment', + component: PaymentRedirect, + meta: { requiresAuth: true }, + }, { path: '/registrera', name: 'register',