diff --git a/.env.example b/.env.example index 815d6d0..03f7833 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ PUBLIC_SUPABASE_URL="" -PUBLIC_SUPABASE_ANON_KEY="" \ No newline at end of file +PUBLIC_SUPABASE_ANON_KEY="" +PUBLIC_STRIPE_SECRET_KEY="" \ No newline at end of file diff --git a/src/lib/components/checkout/BasketItem.svelte b/src/lib/components/checkout/BasketItem.svelte new file mode 100644 index 0000000..3924f37 --- /dev/null +++ b/src/lib/components/checkout/BasketItem.svelte @@ -0,0 +1,125 @@ + + +
+
+
+ {imgAlt} +
+
+
+ {itemName} +
+

+ {itemCategoryDescription} +

+
+ £ {price.toFixed(2)} +
+
+
+
+
+ + + +
+
+ £{(price * quantity).toFixed(2)} +
+
+
diff --git a/src/lib/stores/basket.ts b/src/lib/stores/basket.ts new file mode 100644 index 0000000..3042bdc --- /dev/null +++ b/src/lib/stores/basket.ts @@ -0,0 +1,41 @@ +import { writable } from 'svelte/store'; + +const loadInitialState = () => { + // Check if localStorage is available (i.e., we're on the client side) + if (typeof localStorage !== 'undefined') { + const storedData = localStorage.getItem('basket'); + return storedData ? JSON.parse(storedData) : getDefaultState(); + } else { + return getDefaultState(); + } +}; + +const getDefaultState = () => ({ + items: [], + subtotal: 0 +}); + +export const basket = writable(loadInitialState()); + +// Subscribe to changes in the store and update localStorage accordingly +if (typeof localStorage !== 'undefined') { + basket.subscribe((value) => { + localStorage.setItem('basket', JSON.stringify(value)); + }); +} + +export type Basket = { + items: Item[]; + subtotal: number; +}; + +export type Item = { + id: number; + categoryDescription: string; + name: string; + imgAlt: string; + imgSrc: string; + price: number; + priceId: string; + quantity: number; +}; diff --git a/src/routes/api/checkout/+server.ts b/src/routes/api/checkout/+server.ts index e618d5b..ff12fa0 100644 --- a/src/routes/api/checkout/+server.ts +++ b/src/routes/api/checkout/+server.ts @@ -1,28 +1,29 @@ import { type RequestHandler, redirect } from '@sveltejs/kit'; - -// This is a public sample test API key. -// Don’t submit any personally identifiable information in requests made with this key. -// Sign in to see your own test API key embedded in code samples. -// eslint-disable-next-line @typescript-eslint/no-var-requires +import { PUBLIC_STRIPE_SECRET_KEY } from '$env/static/public'; import stripe from 'stripe'; -const stripeSecretKey = - 'sk_test_51PBMpZLiKlsU6INBHEsWwU2ekDfmotWTZghSl0XRLhtWp6mU7cBIfyBs6eBnG5kgC6MUhnvH5lUm2AbSWxgGfnKm00qTpaUnAP'; -const stripeClient = new stripe(stripeSecretKey); + +const stripeClient = new stripe(PUBLIC_STRIPE_SECRET_KEY); // Create a checkout session export const POST: RequestHandler = async ({ request }) => { - // const { priceId } = await request.json(); // Assuming you'll send the price ID from the client + const formData = new URLSearchParams(await request.text()); + const items: { priceId: string; quantity: number }[] = []; + + // Iterate over form data to extract basket items and their details + for (const [key, value] of formData) { + items.push({ priceId: key, quantity: parseInt(value, 10) }); + } + + const lineItems = items.map((item) => ({ + price: item.priceId, + quantity: item.quantity + })); + const session = await stripeClient.checkout.sessions.create({ - line_items: [ - { - // Provide the exact Price ID (for example, pr_1234) of the product you want to sell - price: 'price_1PBNHRLiKlsU6INBjXMcRxxS', //priceId, - quantity: 1 - } - ], + line_items: lineItems, mode: 'payment', success_url: `${request.headers.get('origin')}/checkout/success`, - cancel_url: `${request.headers.get('origin')}/checkout/cancel` + cancel_url: `${request.headers.get('origin')}/checkout/cancelled` }); return redirect(303, session.url as string); diff --git a/src/routes/checkout/+page.svelte b/src/routes/checkout/+page.svelte index 72c2b88..4c69160 100644 --- a/src/routes/checkout/+page.svelte +++ b/src/routes/checkout/+page.svelte @@ -1,14 +1,129 @@ - + + +
+
+

+ Basket +

+ + + {#each localBasket.items as item (item.id)} + + {/each} +
+
+

+ Shipping, taxes and discounts calculated at checkout +

+
+
+

Subtotal

+
+ £{localBasket.subtotal.toFixed(2)} +
+
+
+
+ {#each localBasket.items as item (item.id)} + + {/each} + +
+ + Continue shopping + + + + + +
+
-
- -