mirror of
https://github.com/KevinMidboe/planetposen-frontend.git
synced 2025-10-29 13:10:12 +00:00
Polls for order status & displays loading while status=initiated
This is the page sent to after the payment is verified clientside at /checkout. While status is only initiated and not updated from stripe webhook we display spinner. TODO should still timeout to content message
This commit is contained in:
@@ -1,10 +1,33 @@
|
||||
import validOrderId from '$lib/utils/validOrderId';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = ({ params }) => {
|
||||
export const load: PageServerLoad = async ({ fetch, params, url }) => {
|
||||
const { id } = params;
|
||||
const email = url.searchParams.get('email');
|
||||
|
||||
let order = null;
|
||||
|
||||
try {
|
||||
const res = await fetch(`/api/v1/order/${id}`);
|
||||
if (res?.status === 404) {
|
||||
return {
|
||||
id,
|
||||
email,
|
||||
order: null
|
||||
};
|
||||
}
|
||||
const orderResponse = await res.json();
|
||||
|
||||
if (orderResponse?.order && orderResponse?.order?.lineItems?.length > 0) {
|
||||
order = orderResponse?.order;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('unable to parse order response');
|
||||
throw error;
|
||||
}
|
||||
|
||||
return {
|
||||
id,
|
||||
isValidReceipt: validOrderId(id)
|
||||
email,
|
||||
order
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
<script lang="ts">
|
||||
import PoolInitiatedOrder from './PoolInitiatedOrder.svelte';
|
||||
import ReceiptNotFound from './ReceiptNotFound.svelte';
|
||||
import BadgeType from '$lib/interfaces/BadgeType';
|
||||
|
||||
import type { PageData } from './$types';
|
||||
import PageMeta from '$lib/components/PageMeta.svelte';
|
||||
|
||||
export let data: PageData;
|
||||
const isValidReceipt = data.isValidReceipt as boolean;
|
||||
const id = data.id as string;
|
||||
let orderStatus: BadgeType = BadgeType.NOT_FOUND;
|
||||
|
||||
if (data?.order) {
|
||||
orderStatus = data.order?.status;
|
||||
}
|
||||
|
||||
const id = data?.id as string;
|
||||
</script>
|
||||
|
||||
{#if isValidReceipt}
|
||||
<slot />
|
||||
{:else}
|
||||
<PageMeta title="Kvittering" description="Søk og finn din ordre kvittering" />
|
||||
|
||||
{#if orderStatus === BadgeType.NOT_FOUND}
|
||||
<ReceiptNotFound id="{id}" />
|
||||
{:else if orderStatus === BadgeType.INITIATED}
|
||||
<PoolInitiatedOrder />
|
||||
{:else}
|
||||
<slot />
|
||||
{/if}
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import validOrderId from '$lib/utils/validOrderId';
|
||||
import type { Actions, PageServerLoad } from './$types';
|
||||
|
||||
export const load: PageServerLoad = ({ params, url }) => {
|
||||
const { id } = params;
|
||||
const email = url.searchParams.get('email');
|
||||
|
||||
return {
|
||||
id,
|
||||
email
|
||||
};
|
||||
};
|
||||
|
||||
export const actions: Actions = {
|
||||
default: async ({ request }) => {
|
||||
const data = await request.formData();
|
||||
@@ -19,12 +8,8 @@ export const actions: Actions = {
|
||||
const orderId = data.get('order-id');
|
||||
const email = data.get('order-email');
|
||||
|
||||
// TODO replace with posting form (json) to backend to check??
|
||||
// also return statusCode from the backend directly.
|
||||
if (validOrderId(String(orderId)) && email) {
|
||||
const receiptUrl = `/receipt/${orderId}?email=${email}`;
|
||||
throw redirect(303, receiptUrl);
|
||||
}
|
||||
const receiptUrl = `/receipt/${orderId}?email=${email}`;
|
||||
throw redirect(303, receiptUrl);
|
||||
|
||||
return { success: false };
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<script lang="ts">
|
||||
import CircleCheckmark from '$lib/icons/CircleCheckmark.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import CircleCheckmark from '$lib/components/loading/CircleCheckmark.svelte';
|
||||
import CircleError from '$lib/components/loading/CircleError.svelte';
|
||||
|
||||
import type { PageServerData } from './$types';
|
||||
import type { ILineItem, IOrder } from '$lib/interfaces/IOrder';
|
||||
import CircleWarning from '$lib/components/loading/CircleWarning.svelte';
|
||||
|
||||
function subTotal(lineItems: Array<ILineItem> = []) {
|
||||
let total = 0;
|
||||
@@ -10,20 +13,32 @@
|
||||
return total;
|
||||
}
|
||||
|
||||
export let data: PageServerData;
|
||||
const id = data.id as string;
|
||||
const email = data.email as string;
|
||||
const order = data.order as IOrder;
|
||||
let id: string;
|
||||
let email: string;
|
||||
let order: IOrder;
|
||||
|
||||
// export let currentRoute;
|
||||
// const id = currentRoute?.namedParams?.id;
|
||||
// const email = currentRoute?.queryParams?.email;
|
||||
const { data } = $page;
|
||||
if (data) {
|
||||
id = data.id as string;
|
||||
email = data.email || (data?.order?.customer?.email as string);
|
||||
order = data.order as IOrder;
|
||||
}
|
||||
</script>
|
||||
|
||||
<section class="order-confirmation">
|
||||
<CircleCheckmark />
|
||||
{#if order.status === 'SUCCESS' || order.status === 'CONFIRMED'}
|
||||
<CircleCheckmark />
|
||||
{:else if order.status === 'CANCELLED' || order.status === 'REJECTED'}
|
||||
<CircleError />
|
||||
{:else}
|
||||
<CircleWarning />
|
||||
{/if}
|
||||
|
||||
<h1>Takk for din bestilling!</h1>
|
||||
{#if order.status === 'SUCCESS' || order.status === 'CONFIRMED'}
|
||||
<h1>Takk for din bestilling!</h1>
|
||||
{:else}
|
||||
<h1>Bestilling ikke gjennomført!</h1>
|
||||
{/if}
|
||||
|
||||
<div class="order-description">
|
||||
<p>
|
||||
@@ -42,7 +57,7 @@
|
||||
{/each}
|
||||
<p>
|
||||
<code>Shipping</code>
|
||||
<code>NOK 79</code>
|
||||
<code>NOK 75</code>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
@@ -55,6 +70,10 @@
|
||||
<style lang="scss">
|
||||
@import './styles-receipt-page.scss';
|
||||
|
||||
.order-description .underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.order-receipt {
|
||||
background-color: #f7f7f7;
|
||||
max-width: 500px;
|
||||
|
||||
60
src/routes/receipt/[[id]]/PoolInitiatedOrder.svelte
Normal file
60
src/routes/receipt/[[id]]/PoolInitiatedOrder.svelte
Normal file
@@ -0,0 +1,60 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { goto } from '$app/navigation';
|
||||
import { onMount } from 'svelte';
|
||||
import CircleLoading from '$lib/components/loading/CircleLoading.svelte';
|
||||
import { buildApiUrl } from '$lib/utils/apiUrl';
|
||||
import type { PageServerData } from './$types';
|
||||
|
||||
const { data } = $page;
|
||||
const id = data?.id as string;
|
||||
|
||||
let maxPoolTime: Date = new Date();
|
||||
maxPoolTime.setSeconds(maxPoolTime.getSeconds() + 15);
|
||||
|
||||
if (!id) {
|
||||
console.log('no id found after all:(');
|
||||
}
|
||||
|
||||
function redirect() {
|
||||
const url = `/receipt/${id}`;
|
||||
window.location.href = url;
|
||||
goto(url);
|
||||
}
|
||||
|
||||
function checkOrder() {
|
||||
const url = buildApiUrl(`/api/v1/order/${id}`);
|
||||
return fetch(url)
|
||||
.then((resp) => resp.json())
|
||||
.then((response) => {
|
||||
response?.order?.status !== 'INITIATED' ? redirect() : null;
|
||||
});
|
||||
}
|
||||
|
||||
function pool() {
|
||||
if (new Date() < maxPoolTime) {
|
||||
setTimeout(() => checkOrder().then(() => pool()), 1500);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
onMount(pool);
|
||||
</script>
|
||||
|
||||
<section class="order-confirmation">
|
||||
<CircleLoading />
|
||||
|
||||
<h1>Bestillingen din behandles</h1>
|
||||
|
||||
<div class="order-description">
|
||||
<p>Vent noen sekunder mens betalingen din blir godkjent</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
@import './styles-receipt-page.scss';
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -1,33 +1,16 @@
|
||||
<script lang="ts">
|
||||
import Input from '$lib/components/Input.svelte';
|
||||
import PlanetButton from '$lib/components/Button.svelte';
|
||||
import CircleError from '$lib/icons/CircleError.svelte';
|
||||
import CircleWarning from '$lib/icons/CircleWarning.svelte';
|
||||
|
||||
const CircleComponent = Math.random() > 0.5 ? CircleWarning : CircleError;
|
||||
import CircleWarning from '$lib/components/loading/CircleWarning.svelte';
|
||||
|
||||
export let id: string;
|
||||
|
||||
// async function handleSubmit(event) {
|
||||
// const data = new FormData(this);
|
||||
// console.log('formdata::', data);
|
||||
|
||||
// const orderId = data.get('order-id');
|
||||
// const orderEmail = data.get('order-email');
|
||||
|
||||
// console.log('orderId:', orderId)
|
||||
// console.log('orderEmail:', orderEmail)
|
||||
|
||||
// const url = `/receipt/${orderId}?email=${orderEmail}`;
|
||||
// goto(url);
|
||||
// }
|
||||
|
||||
let searchOrderNumber: string;
|
||||
let searchOrderEmail: string;
|
||||
</script>
|
||||
|
||||
<section class="order-confirmation">
|
||||
<svelte:component this="{CircleComponent}" />
|
||||
<CircleWarning />
|
||||
|
||||
<h1>Fant ikke din bestilling!</h1>
|
||||
|
||||
@@ -40,7 +23,8 @@
|
||||
<form class="order-search" method="POST">
|
||||
<span>Du kan forsøke søke opp din ordre her:</span>
|
||||
|
||||
<Input name="order-id" label="Ordre id (hex)" bind:value="{searchOrderNumber}" />
|
||||
<Input name="order-id" label="Ordre id " bind:value="{searchOrderNumber}" />
|
||||
<br />
|
||||
<Input name="order-email" label="Epost adresse" bind:value="{searchOrderEmail}" />
|
||||
|
||||
<PlanetButton text="Søk" />
|
||||
@@ -62,6 +46,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
:global(.order-search button) {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@import '../../../styles/media-queries.scss';
|
||||
|
||||
.order-confirmation {
|
||||
margin: 6rem auto 0;
|
||||
margin: 10rem auto 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 0 0.5rem;
|
||||
@@ -10,8 +10,6 @@
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
// @include pageMargin;
|
||||
|
||||
@include tablet {
|
||||
padding: 0 1rem;
|
||||
}
|
||||
@@ -31,8 +29,4 @@
|
||||
padding: 1rem;
|
||||
margin: 1rem 0;
|
||||
text-align: center;
|
||||
|
||||
.underline {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user