pr_01m47d15m3e54sn21z27rpy5n9/apps/web/app/routes/profile.tsx

41 lines1,413 bytesCodeBlame
1import { data } from "react-router";
2
3import type { Route } from "./+types/profile";
4import { RepoList } from "../components/repo-list";
5import { Avatar } from "../components/ui";
6import { identity, repos as reposApi } from "../lib/services.server";
7import { getViewer } from "../lib/session.server";
8
9export function meta({ params }: Route.MetaArgs) {
10 return [{ title: `${params.owner} · g1t` }];
11}
12
13export async function loader({ params, context }: Route.LoaderArgs) {
14 const [user, repos] = await Promise.all([
15 identity.userByUsername(params.owner),
16 reposApi.list(getViewer(context), { namespace: params.owner }),
17 ]);
18 if (!user) throw data(null, { status: 404 });
19 return { user, repos };
20}
21
22export default function Profile({ loaderData }: Route.ComponentProps) {
23 const { user, repos } = loaderData;
24 return (
25 <main className="mx-auto max-w-4xl px-4 py-10">
26 <div className="flex items-center gap-4">
27 <Avatar name={user.username} size={56} />
28 <div>
29 <h1 className="font-mono text-2xl font-semibold tracking-tight">
30 {user.username}
31 </h1>
32 <p className="text-sm text-muted">
33 {repos.length} {repos.length === 1 ? "repository" : "repositories"}
34 </p>
35 </div>
36 </div>
37 <h2 className="mt-10 text-sm font-medium text-muted">Repositories</h2>
38 <RepoList repos={repos} />
39 </main>
40 );
41}