diff options
author | 2024-08-25 04:10:49 +0100 | |
---|---|---|
committer | 2024-08-25 04:10:49 +0100 | |
commit | 923de5c2a264fec92ac28775030957ecc68350a2 (patch) | |
tree | c63411ad385639f6b8a5a41e14b690000be1114f | |
parent | Add store front page (diff) |
Gracefully handle missing token errors
-rw-r--r-- | thallium-frontend/src/api/client.ts | 6 | ||||
-rw-r--r-- | thallium-frontend/src/api/templates.ts | 4 | ||||
-rw-r--r-- | thallium-frontend/src/pages/StorePage.tsx | 14 |
3 files changed, 20 insertions, 4 deletions
diff --git a/thallium-frontend/src/api/client.ts b/thallium-frontend/src/api/client.ts index 9e64af5..bbba0d5 100644 --- a/thallium-frontend/src/api/client.ts +++ b/thallium-frontend/src/api/client.ts @@ -4,6 +4,12 @@ TODO: Someday these methods should try pick out authentication from the Redux st const BASE_URL = THALLIUM_BASE_URL; +export class APIMissingTokenError extends Error { + constructor() { + super("No token available"); + } +} + interface APIErrorResponse { detail?: string; } diff --git a/thallium-frontend/src/api/templates.ts b/thallium-frontend/src/api/templates.ts index d60260d..0c8dffd 100644 --- a/thallium-frontend/src/api/templates.ts +++ b/thallium-frontend/src/api/templates.ts @@ -1,4 +1,4 @@ -import { get } from "./client"; +import { get, APIMissingTokenError } from "./client"; import store from "../store"; export interface Variant { @@ -27,7 +27,7 @@ export const getTemplates = async (withVariants: boolean): Promise<Template[]> = const token = store.getState().authorization.voucherToken; if (!token) { - throw new Error("No token available"); + throw new APIMissingTokenError(); }; return await get(`/templates/?with_variants=${withVariants.toString()}`, { diff --git a/thallium-frontend/src/pages/StorePage.tsx b/thallium-frontend/src/pages/StorePage.tsx index 6899bd8..a3143d3 100644 --- a/thallium-frontend/src/pages/StorePage.tsx +++ b/thallium-frontend/src/pages/StorePage.tsx @@ -3,8 +3,10 @@ import { RootState } from "../store"; import { useEffect, useState } from "react"; import { Template, getTemplates } from "../api/templates"; +import { APIMissingTokenError } from "../api/client"; import StoreItem from "../components/StoreItem"; import styled from "styled-components"; +import { Link } from "react-router-dom"; const StoreGrid = styled.div` display: grid; @@ -17,11 +19,14 @@ const StoreGrid = styled.div` const StorePage = () => { const voucherToken = useSelector((state: RootState) => state.authorization.voucherToken); const [storeItems, setStoreItems] = useState<Template[] | null>(null); + const [permissionDenied, setPermissionDenied] = useState<boolean>(false); useEffect(() => { getTemplates(true).then(setStoreItems).catch((err: unknown) => { setStoreItems([]); - console.error(err); + if (err instanceof APIMissingTokenError) { + setPermissionDenied(true); + } }); }, [voucherToken]); @@ -33,7 +38,12 @@ const StorePage = () => { <StoreItem key={item.template_id} template={item} /> ))} </StoreGrid> - + {permissionDenied && ( + <> + <p>You need to have a valid voucher code to access the store.</p> + <Link to="/">Redeem a voucher</Link> + </> + )} </> ); }; |