mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-07-19 09:02:43 -05:00
Move user page data loading to layout route
This commit is contained in:
parent
185295d54e
commit
f2d547fa01
|
|
@ -1,13 +1,72 @@
|
|||
import { Outlet } from "@remix-run/react";
|
||||
import type { LoaderFunction } from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import { Outlet, useLoaderData } from "@remix-run/react";
|
||||
import { countries } from "countries-list";
|
||||
import { z } from "zod";
|
||||
import { Main } from "~/components/Main";
|
||||
import { SubNav, SubNavLink } from "~/components/SubNav";
|
||||
import { db } from "~/db";
|
||||
import type { User } from "~/db/types";
|
||||
import { useUser } from "~/hooks/useUser";
|
||||
import { notFoundIfFalsy } from "~/utils/remix";
|
||||
|
||||
export const userParamsSchema = z.object({ identifier: z.string() });
|
||||
|
||||
export type UserPageLoaderData = Pick<
|
||||
User,
|
||||
| "id"
|
||||
| "discordName"
|
||||
| "discordAvatar"
|
||||
| "discordDiscriminator"
|
||||
| "discordId"
|
||||
| "youtubeId"
|
||||
| "twitch"
|
||||
| "twitter"
|
||||
> & { country?: { name: string; emoji: string; code: string } };
|
||||
|
||||
export const loader: LoaderFunction = ({ params }) => {
|
||||
const { identifier } = userParamsSchema.parse(params);
|
||||
const user = notFoundIfFalsy(db.users.findByIdentifier(identifier));
|
||||
|
||||
const countryObj = user.country
|
||||
? countries[user.country as keyof typeof countries]
|
||||
: undefined;
|
||||
|
||||
return json<UserPageLoaderData>({
|
||||
id: user.id,
|
||||
discordAvatar: user.discordAvatar,
|
||||
discordDiscriminator: user.discordDiscriminator,
|
||||
discordId: user.discordId,
|
||||
discordName: user.discordName,
|
||||
twitch: user.twitch,
|
||||
twitter: user.twitter,
|
||||
youtubeId: user.youtubeId,
|
||||
country:
|
||||
countryObj && user.country
|
||||
? {
|
||||
name: countryObj.name,
|
||||
emoji: countryObj.emoji,
|
||||
code: user.country,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
export default function UserPageLayout() {
|
||||
const data = useLoaderData<UserPageLoaderData>();
|
||||
const user = useUser();
|
||||
|
||||
const isOwnPage = data.id === user?.id;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SubNav>
|
||||
<SubNavLink to="">Profile</SubNavLink>
|
||||
<SubNavLink to="edit">Edit</SubNavLink>
|
||||
{isOwnPage ? (
|
||||
<SubNavLink to="edit" data-cy="edit-page-link">
|
||||
Edit
|
||||
</SubNavLink>
|
||||
) : null}
|
||||
</SubNav>
|
||||
<Main>
|
||||
<Outlet />
|
||||
|
|
|
|||
|
|
@ -1,23 +1,13 @@
|
|||
import type {
|
||||
ActionFunction,
|
||||
LinksFunction,
|
||||
LoaderFunction,
|
||||
} from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import { Form, useLoaderData, useTransition } from "@remix-run/react";
|
||||
import type { ActionFunction, LinksFunction } from "@remix-run/node";
|
||||
import { Form, useMatches, useTransition } from "@remix-run/react";
|
||||
import { countries } from "countries-list";
|
||||
import { Button } from "~/components/Button";
|
||||
import styles from "~/styles/u-edit.css";
|
||||
import { z } from "zod";
|
||||
import { falsyToNull } from "~/utils/zod";
|
||||
import {
|
||||
notFoundIfFalsy,
|
||||
parseRequestFormData,
|
||||
requireUser,
|
||||
} from "~/utils/remix";
|
||||
import { Button } from "~/components/Button";
|
||||
import { db } from "~/db";
|
||||
import type { User } from "~/db/types";
|
||||
import { userParamsSchema } from "./index";
|
||||
import styles from "~/styles/u-edit.css";
|
||||
import { parseRequestFormData, requireUser } from "~/utils/remix";
|
||||
import { falsyToNull } from "~/utils/zod";
|
||||
import type { UserPageLoaderData } from "../u.$identifier";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
|
|
@ -47,20 +37,9 @@ export const action: ActionFunction = async ({ request }) => {
|
|||
return null;
|
||||
};
|
||||
|
||||
type UserEditLoaderData = Pick<User, "country">;
|
||||
|
||||
export const loader: LoaderFunction = async ({ request, params }) => {
|
||||
const user = await requireUser(request);
|
||||
const { identifier } = userParamsSchema.parse(params);
|
||||
|
||||
const userFromDb = notFoundIfFalsy(db.users.findByIdentifier(identifier));
|
||||
if (userFromDb.id !== user.id) throw new Response(null, { status: 401 });
|
||||
|
||||
return json<UserEditLoaderData>({ country: userFromDb?.country });
|
||||
};
|
||||
|
||||
export default function UserEditPage() {
|
||||
const data = useLoaderData<UserEditLoaderData>();
|
||||
const [, parentRoute] = useMatches();
|
||||
const data = parentRoute.data as UserPageLoaderData;
|
||||
const transition = useTransition();
|
||||
|
||||
return (
|
||||
|
|
@ -71,7 +50,7 @@ export default function UserEditPage() {
|
|||
className="u-edit__country-select"
|
||||
name="country"
|
||||
id="country"
|
||||
defaultValue={data.country ?? ""}
|
||||
defaultValue={data.country?.code ?? ""}
|
||||
>
|
||||
<option value="" />
|
||||
{Object.entries(countries).map(([code, country]) => (
|
||||
|
|
|
|||
|
|
@ -1,59 +1,18 @@
|
|||
import type { LinksFunction, LoaderFunction } from "@remix-run/node";
|
||||
import { json } from "@remix-run/node";
|
||||
import { db } from "~/db";
|
||||
import { z } from "zod";
|
||||
import type { User } from "~/db/types";
|
||||
import { notFoundIfFalsy } from "~/utils/remix";
|
||||
import { useLoaderData } from "@remix-run/react";
|
||||
import type { LinksFunction } from "@remix-run/node";
|
||||
import { useMatches } from "@remix-run/react";
|
||||
import { Avatar } from "~/components/Avatar";
|
||||
import styles from "~/styles/u.css";
|
||||
import { SocialLink } from "~/components/u/SocialLink";
|
||||
import { countries } from "countries-list";
|
||||
import styles from "~/styles/u.css";
|
||||
import type { UserPageLoaderData } from "../u.$identifier";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
};
|
||||
|
||||
export const userParamsSchema = z.object({ identifier: z.string() });
|
||||
|
||||
type UserPageLoaderData = Pick<
|
||||
User,
|
||||
| "discordName"
|
||||
| "discordAvatar"
|
||||
| "discordDiscriminator"
|
||||
| "discordId"
|
||||
| "youtubeId"
|
||||
| "twitch"
|
||||
| "twitter"
|
||||
> & { country?: { name: string; emoji: string } };
|
||||
|
||||
export const loader: LoaderFunction = ({ params }) => {
|
||||
const { identifier } = userParamsSchema.parse(params);
|
||||
const user = notFoundIfFalsy(db.users.findByIdentifier(identifier));
|
||||
|
||||
const countryObj = user.country
|
||||
? countries[user.country as keyof typeof countries]
|
||||
: undefined;
|
||||
|
||||
return json<UserPageLoaderData>({
|
||||
discordAvatar: user.discordAvatar,
|
||||
discordDiscriminator: user.discordDiscriminator,
|
||||
discordId: user.discordId,
|
||||
discordName: user.discordName,
|
||||
twitch: user.twitch,
|
||||
twitter: user.twitter,
|
||||
youtubeId: user.youtubeId,
|
||||
country: countryObj
|
||||
? {
|
||||
name: countryObj.name,
|
||||
emoji: countryObj.emoji,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
};
|
||||
|
||||
export default function UserInfoPage() {
|
||||
const data = useLoaderData<UserPageLoaderData>();
|
||||
const [, parentRoute] = useMatches();
|
||||
const data = parentRoute.data as UserPageLoaderData;
|
||||
|
||||
return (
|
||||
<div className="u__avatar-container">
|
||||
<Avatar
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user