From 961fcdf441254be44ff6a46ced1076d0e081890b Mon Sep 17 00:00:00 2001
From: ap-justin <89639563+ap-justin@users.noreply.github.com>
Date: Sat, 12 Oct 2024 21:53:00 +0800
Subject: [PATCH] profile loading
---
src/App/App.tsx | 6 +---
src/pages/Profile/index.tsx | 38 +++-------------------
src/pages/Profile/profile-loader.ts | 49 +++++++++++++++++++++++++++++
3 files changed, 55 insertions(+), 38 deletions(-)
create mode 100644 src/pages/Profile/profile-loader.ts
diff --git a/src/App/App.tsx b/src/App/App.tsx
index 475516ddf8..dc865a0850 100644
--- a/src/App/App.tsx
+++ b/src/App/App.tsx
@@ -40,11 +40,7 @@ const _appRoutes: RO[] = [
...blogRoutes,
...legalRoutes,
...infoRoutes,
- {
- element: , //outlet-value: legacy
- children: [{ path: appRoutes.profile + "/:id", ...profileRoute }],
- },
-
+ { path: appRoutes.profile + "/:id", ...profileRoute },
{
path: appRoutes.banking_applications,
children: [
diff --git a/src/pages/Profile/index.tsx b/src/pages/Profile/index.tsx
index 5691cacf4e..f8d40cfb83 100644
--- a/src/pages/Profile/index.tsx
+++ b/src/pages/Profile/index.tsx
@@ -3,43 +3,14 @@ import flying_character from "assets/images/flying-character.png";
import Image from "components/Image";
import Seo from "components/Seo";
import { APP_NAME, BASE_URL } from "constants/env";
-import { appRoutes } from "constants/routes";
-import {
- Navigate,
- Outlet,
- type RouteObject,
- useOutletContext,
- useParams,
-} from "react-router-dom";
-import { segment } from "schemas/string";
-import { useEndowment } from "services/aws/useEndowment";
+import { Outlet, type RouteObject, useLoaderData } from "react-router-dom";
+import type { EndowmentProfile } from "types/aws";
import { bodyRoute } from "./Body";
-import PageError from "./PageError";
import ProfileContext, { useProfileContext } from "./ProfileContext";
-import Skeleton from "./Skeleton";
+import { profileLoader } from "./profile-loader";
function Profile() {
- const legacy = useOutletContext();
- const { id = "" } = useParams<{ id: string }>();
-
- const { isLoading, isError, data } = useEndowment(
- segment.isValidSync(id) ? { slug: id } : { id: Number(id) }
- );
-
- if (isLoading) return ;
- if (isError || !data) return ;
-
- if (legacy) {
- if (data.id === null) {
- return ;
- }
-
- if (data.id !== Number(id)) {
- return ;
- }
- }
-
- // if (!data.published) return ;
+ const data = useLoaderData() as EndowmentProfile;
return (
@@ -85,5 +56,6 @@ function Logo() {
export const profileRoute: RouteObject = {
element: ,
+ loader: profileLoader,
children: [bodyRoute],
};
diff --git a/src/pages/Profile/profile-loader.ts b/src/pages/Profile/profile-loader.ts
new file mode 100644
index 0000000000..8c8de82d31
--- /dev/null
+++ b/src/pages/Profile/profile-loader.ts
@@ -0,0 +1,49 @@
+import { APIs } from "constants/urls";
+import { type LoaderFunctionArgs, redirect } from "react-router-dom";
+import { apiEnv } from "services/constants";
+import * as v from "valibot";
+
+const schema = v.union([
+ v.pipe(
+ v.string(),
+ v.transform((x) => +x),
+ v.number(),
+ v.integer(),
+ v.minValue(1)
+ ),
+ v.pipe(
+ v.string(),
+ v.trim(),
+ v.nonEmpty(),
+ //must not be id-like
+ v.regex(/^(?!^\d+$)/, "should not be an id"),
+ //valid characters
+ v.regex(/^[a-zA-Z0-9-._~]+$/, "invalid segment"),
+ v.excludes("..", "invalid segment"),
+ v.custom((x) => !(x as string).startsWith("."), "invalid segment"),
+ v.custom((x) => !(x as string).endsWith("."), "invalid segment")
+ ),
+]);
+
+export const profileLoader = async ({
+ params,
+}: LoaderFunctionArgs): Promise => {
+ const cache = await caches.open("bg");
+ const { output: id, issues } = v.safeParse(schema, params.id);
+ if (issues) return redirect("/marketplace");
+
+ const url = new URL(APIs.aws);
+ url.searchParams.set("env", apiEnv);
+ if (typeof id === "number") {
+ url.pathname = `v9/endowments/${id}`;
+ }
+ if (typeof id === "string") {
+ url.pathname = `v9/endowments`;
+ url.searchParams.set("slug", id);
+ }
+ const c = await cache.match(url);
+ if (c) return c.clone();
+
+ await cache.add(url);
+ return cache.match(url);
+};