Improve look and performance of orders table
This commit is contained in:
@@ -237,6 +237,32 @@ export const app = new Elysia()
|
||||
})
|
||||
)
|
||||
.group("/orders", (app) => app
|
||||
.get("/", async ({ query }) => {
|
||||
const wOrders = await s.Commerce.Webflow.Orders.list({
|
||||
status: query.status,
|
||||
limit: query.limit,
|
||||
offset: query.offset,
|
||||
});
|
||||
const isSyncedFlags = await Promise.all(
|
||||
wOrders.map(async (wOrder) =>
|
||||
(await s.Commerce.Printful.Orders.get(`@${wOrder.orderId}`)) !== undefined
|
||||
)
|
||||
);
|
||||
return wOrders.map((wOrder, i) => ({ wOrder, isSynced: isSyncedFlags[i] }));
|
||||
}, {
|
||||
query: t.Object({
|
||||
status: t.Optional(t.Union([
|
||||
t.Literal("pending"),
|
||||
t.Literal("unfulfilled"),
|
||||
t.Literal("fulfilled"),
|
||||
t.Literal("disputed"),
|
||||
t.Literal("dispute-lost"),
|
||||
t.Literal("refunded"),
|
||||
])),
|
||||
limit: t.Optional(t.Numeric()),
|
||||
offset: t.Optional(t.Numeric()),
|
||||
})
|
||||
})
|
||||
.get("/:wOrderId", async ({ params: { wOrderId } }) => {
|
||||
const wOrder = await s.Commerce.Webflow.Orders.get(wOrderId);
|
||||
if (!wOrder) throw new NotFoundError("Missing webflow order");
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import { printful } from "$lib/printful";
|
||||
import { webflow } from "$lib/webflow";
|
||||
import type { PageServerLoad } from "./$types";
|
||||
|
||||
export const load = async ({ }: Parameters<PageServerLoad>[0]) => {
|
||||
return {
|
||||
orders: {
|
||||
printful: printful.Orders.list({ forceAll: true }),
|
||||
webflow: webflow.Orders.list({ forceAll: true }),
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,19 +1,88 @@
|
||||
<script lang="ts">
|
||||
import { api } from "$lib/api.js";
|
||||
import type { Webflow } from "@blade-and-brawn/commerce";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
const { data } = $props();
|
||||
type OrderRow = NonNullable<
|
||||
Awaited<ReturnType<typeof api.commerce.orders.get>>["data"]
|
||||
>[number];
|
||||
|
||||
const isOrderSynced = async (wOrder: Webflow.Orders.Order) => {
|
||||
const pOrders = await data.orders.printful;
|
||||
return pOrders.some((pOrder) => pOrder.external_id === wOrder.orderId);
|
||||
};
|
||||
const LIMIT = 25;
|
||||
|
||||
let orders = $state<OrderRow[]>([]);
|
||||
let loading = $state(true);
|
||||
let loadError = $state<string | null>(null);
|
||||
let offset = $state(0);
|
||||
|
||||
function errorMessage(err: unknown): string {
|
||||
const value = (err as { value?: { error?: string } })?.value;
|
||||
return (
|
||||
value?.error ??
|
||||
(err instanceof Error ? err.message : "Unknown error")
|
||||
);
|
||||
}
|
||||
|
||||
async function refresh() {
|
||||
loading = true;
|
||||
loadError = null;
|
||||
try {
|
||||
const res = await api.commerce.orders.get({
|
||||
query: {
|
||||
limit: LIMIT,
|
||||
offset,
|
||||
},
|
||||
});
|
||||
if (res.error) throw res.error;
|
||||
orders = res.data as OrderRow[];
|
||||
} catch (err) {
|
||||
loadError = errorMessage(err);
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
offset = Math.max(0, offset - LIMIT);
|
||||
refresh();
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
offset += LIMIT;
|
||||
refresh();
|
||||
}
|
||||
|
||||
onMount(refresh);
|
||||
</script>
|
||||
|
||||
{#await data.orders.webflow}
|
||||
<p>Loading...</p>
|
||||
{:then wOrders}
|
||||
<div class="w-full mt-10 overflow-x-auto">
|
||||
<div class="w-full flex items-center gap-2 flex-wrap mt-10 mb-5">
|
||||
<button class="btn btn-sm" onclick={refresh} disabled={loading}>
|
||||
{loading ? "Refreshing..." : "Refresh"}
|
||||
</button>
|
||||
|
||||
<div class="flex-1"></div>
|
||||
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
onclick={prevPage}
|
||||
disabled={offset === 0 || loading}
|
||||
>
|
||||
Prev
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm"
|
||||
onclick={nextPage}
|
||||
disabled={orders.length < LIMIT || loading}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if loadError}
|
||||
<div role="alert" class="alert alert-error w-full mb-4">
|
||||
<span>{loadError}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div class="w-full overflow-x-auto">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -22,41 +91,38 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each wOrders as wOrder}
|
||||
{#each orders as order (order.wOrder.orderId)}
|
||||
<tr class="hover:bg-base-300">
|
||||
<td
|
||||
><button
|
||||
onclick={async () => {
|
||||
const res = await api.commerce
|
||||
.orders({
|
||||
wOrderId: wOrder.orderId,
|
||||
wOrderId: order.wOrder.orderId,
|
||||
})
|
||||
.get();
|
||||
console.log(res.data);
|
||||
}}
|
||||
class="cursor-pointer underline"
|
||||
>
|
||||
{wOrder.orderId}
|
||||
{order.wOrder.orderId}
|
||||
</button></td
|
||||
>
|
||||
<td>
|
||||
{#await isOrderSynced(wOrder) then isSynced}
|
||||
{#if isSynced}
|
||||
<div class="badge badge-success">
|
||||
Synced
|
||||
</div>
|
||||
{#if order.isSynced}
|
||||
<div class="badge badge-success">Synced</div>
|
||||
{:else}
|
||||
<div class="badge badge-error">
|
||||
Desynced
|
||||
</div>
|
||||
<div class="badge badge-error">Desynced</div>
|
||||
{/if}
|
||||
{/await}
|
||||
</td>
|
||||
</tr>
|
||||
{:else}
|
||||
<tr>
|
||||
<td colspan="2" class="text-center opacity-60">
|
||||
{loading ? "Loading..." : "No orders found"}
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{:catch error}
|
||||
<p>Something went wrong: {error.message}</p>
|
||||
{/await}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user