From f95cba90426449696a23f7e42f39abb585ad5884 Mon Sep 17 00:00:00 2001 From: MiguelMLorente Date: Mon, 24 Nov 2025 22:15:07 +0100 Subject: [PATCH] Redirect customer after stripe flow completion --- src/App.tsx | 17 ++++++++++++++--- src/api/client.ts | 11 +++++++++-- src/context/pre-login-page-context.ts | 4 ++-- src/pages/Buy.tsx | 12 ++++++++++-- src/pages/BuyReturn.tsx | 18 ++++++++++++++++++ src/pages/SignUp.tsx | 10 +++++++--- vite.config.ts | 19 ++++++++++++------- 7 files changed, 72 insertions(+), 19 deletions(-) create mode 100644 src/pages/BuyReturn.tsx diff --git a/src/App.tsx b/src/App.tsx index 7ddbee4..6a665f5 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,9 @@ import "./App.css"; import { Login } from "./pages/Login.tsx"; -import { ContentLayout, SpaceBetween } from "@cloudscape-design/components"; +import { + ContentLayout, + SpaceBetween +} from "@cloudscape-design/components"; import icon from "./paella-icon.png"; import { Outlet, Route, Routes } from "react-router"; import { SignUp } from "./pages/SignUp.tsx"; @@ -10,9 +13,16 @@ import { useState } from "react"; import { PreLoginPageContext } from "./context/pre-login-page-context.ts"; import { LoggedInPageContext } from "./context/logged-in-page-context.ts"; import { NotFound } from "./pages/NotFound.tsx"; +import { BuyReturn } from "./pages/BuyReturn.tsx"; function App() { - const [userId, setUserId] = useState(null); + const locallyStoredUserId = window.localStorage.getItem("paysplit-user-id"); + const locallyStoredUserIdAsNumber = locallyStoredUserId ? parseInt(locallyStoredUserId) : null + const [userId, setUserId] = useState(locallyStoredUserIdAsNumber); + const storeUserId = (id: number) => { + window.localStorage.setItem("paysplit-user-id", id.toString()); + setUserId(id); + } return ( @@ -21,7 +31,7 @@ function App() { + } @@ -38,6 +48,7 @@ function App() { > } /> } /> + } /> } /> diff --git a/src/api/client.ts b/src/api/client.ts index bd91879..e3e22cf 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -16,5 +16,12 @@ export const registerUser = (name: string, password: string) => password, }) as Promise>; -export const startBuyFlow = (userId: string) => - axios.post("/buy/start", { userId }); +export const startBuyFlow = (userId: number, quantity: number) => + axios.post("/buy/start", { userId, quantity }) as Promise< + AxiosResponse<{ url: string }, unknown, {}> + >; + +export const completeBuyFlow = (userId: number) => + axios.post("/buy/complete", { userId }) as Promise< + AxiosResponse<{ url: string }, unknown, {}> + >; diff --git a/src/context/pre-login-page-context.ts b/src/context/pre-login-page-context.ts index 9b1cbeb..089681d 100644 --- a/src/context/pre-login-page-context.ts +++ b/src/context/pre-login-page-context.ts @@ -1,7 +1,7 @@ -import { createContext, type Dispatch, type SetStateAction } from "react"; +import { createContext } from "react"; interface PreLoginPageContextProps { - setUserId: Dispatch>; + setUserId: (id: number) => void; } export const PreLoginPageContext = diff --git a/src/pages/Buy.tsx b/src/pages/Buy.tsx index 00a0f70..d75b159 100644 --- a/src/pages/Buy.tsx +++ b/src/pages/Buy.tsx @@ -5,10 +5,18 @@ import { Input, SpaceBetween, } from "@cloudscape-design/components"; -import { useState } from "react"; +import { useContext, useState } from "react"; +import { startBuyFlow } from "../api/client"; +import { LoggedInPageContext } from "../context/logged-in-page-context"; export const Buy = () => { const [quantity, setQuantity] = useState(0); + const { userId } = useContext(LoggedInPageContext)!; + const handleBuyFlow = () => + startBuyFlow(userId, quantity).then( + (response) => (window.location.href = response.data.url), + ); + return ( @@ -18,7 +26,7 @@ export const Buy = () => { value={quantity.toString()} onChange={(e) => setQuantity(parseInt(e.detail.value))} /> - + ); diff --git a/src/pages/BuyReturn.tsx b/src/pages/BuyReturn.tsx new file mode 100644 index 0000000..784e416 --- /dev/null +++ b/src/pages/BuyReturn.tsx @@ -0,0 +1,18 @@ +import { Header, SpaceBetween, Spinner } from "@cloudscape-design/components"; +import { useContext } from "react"; +import { completeBuyFlow } from "../api/client"; +import { LoggedInPageContext } from "../context/logged-in-page-context"; + +export const BuyReturn = () => { + const { userId } = useContext(LoggedInPageContext)!; + completeBuyFlow(userId).then( + (response) => (window.location.href = response.data.url), + ); + + return ( + + +
We are processing your request
+
+ ); +}; diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx index 0bf4cb5..2a76f6f 100644 --- a/src/pages/SignUp.tsx +++ b/src/pages/SignUp.tsx @@ -7,6 +7,7 @@ import { } from "@cloudscape-design/components"; import { useState } from "react"; import { FormattedDate } from "react-intl"; +import { Link } from "react-router"; export const SignUp = () => { const [selectedDate, setSelectedDate] = useState(null); @@ -50,10 +51,13 @@ export const SignUp = () => { {!availableTokens && (

- You don't have any more tokens to sign up to any slot, please buy - here. + You don't have any tokens to sign up to a slot, please buy here.

- +
)} diff --git a/vite.config.ts b/vite.config.ts index 640fc48..cefd6c6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,16 +1,21 @@ import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; +const serverRoutes = ["/access", "/buy/start", "/buy/complete", "/buy/cancel"]; + // https://vite.dev/config/ export default defineConfig({ server: { - proxy: { - "/access": { - target: "http://localhost:3000", - changeOrigin: true, - secure: false, - }, - }, + proxy: Object.fromEntries( + serverRoutes.map((key) => [ + key, + { + target: "http://localhost:3000", + changeOrigin: true, + secure: false, + }, + ]), + ), }, plugins: [react()], });