perf(payment): parse route params on the server

This commit is contained in:
2026-07-14 17:48:20 +08:00
parent f58f47e0a5
commit e270be9bd9
4 changed files with 74 additions and 107 deletions
+29 -13
View File
@@ -1,21 +1,37 @@
import { Suspense } from "react";
import type { PayChannel } from "@/data/dto/payment";
import {
DEFAULT_TIP_COFFEE_TYPE,
resolveTipCoffeeType,
TIP_COFFEE_TYPE_PARAM,
} from "@/lib/tip/tip_coffee";
import { PageLoadingFallback } from "@/app/_components/core";
import { TipScreen } from "./tip-screen";
import { TipPageClient } from "./tip-page-client";
type TipSearchParams = Record<string, string | string[] | undefined>;
export default async function TipPage({
searchParams,
}: {
searchParams: Promise<TipSearchParams>;
}) {
const query = await searchParams;
const coffeeType =
resolveTipCoffeeType(firstSearchParam(query[TIP_COFFEE_TYPE_PARAM])) ??
DEFAULT_TIP_COFFEE_TYPE;
export default function TipPage() {
return (
<Suspense fallback={<TipFallback />}>
<TipPageClient />
</Suspense>
<TipScreen
coffeeType={coffeeType}
shouldResumePendingOrder={firstSearchParam(query.paymentReturn) === "1"}
initialPayChannel={toPayChannel(firstSearchParam(query.payChannel))}
/>
);
}
function TipFallback() {
return (
<PageLoadingFallback background="#fff6ed" tone="warm">
Loading tip...
</PageLoadingFallback>
);
function firstSearchParam(value: string | string[] | undefined): string | null {
return Array.isArray(value) ? (value[0] ?? null) : (value ?? null);
}
function toPayChannel(value: string | null): PayChannel | null {
return value === "ezpay" || value === "stripe" ? value : null;
}
-32
View File
@@ -1,32 +0,0 @@
"use client";
import { useSearchParams } from "next/navigation";
import type { PayChannel } from "@/data/dto/payment";
import {
DEFAULT_TIP_COFFEE_TYPE,
resolveTipCoffeeType,
TIP_COFFEE_TYPE_PARAM,
} from "@/lib/tip/tip_coffee";
import { TipScreen } from "./tip-screen";
function toPayChannel(value: string | null): PayChannel | null {
if (value === "ezpay" || value === "stripe") return value;
return null;
}
export function TipPageClient() {
const searchParams = useSearchParams();
const coffeeType =
resolveTipCoffeeType(searchParams.get(TIP_COFFEE_TYPE_PARAM)) ??
DEFAULT_TIP_COFFEE_TYPE;
return (
<TipScreen
coffeeType={coffeeType}
shouldResumePendingOrder={searchParams.get("paymentReturn") === "1"}
initialPayChannel={toPayChannel(searchParams.get("payChannel"))}
/>
);
}