web/app/collab/page.tsxblame
View source
0b4b5821import type { Metadata } from "next";
bc1b2ba2import { cookies, headers } from "next/headers";
0b4b5823import Link from "next/link";
bc1b2ba4import { listRepos } from "@/lib/grove-api";
0b4b5825import { CollabLogo } from "@/app/components/collab-logo";
0b4b5826import { CollabRepoList } from "./collab-repo-list";
0b4b5827
0b4b5828export const metadata: Metadata = {
0b4b5829 title: "Collab",
0b4b58210};
0b4b58211
0b4b58212interface Repo {
0b4b58213 name: string;
0b4b58214 owner_name: string;
0b4b58215 description: string | null;
0b4b58216 last_commit_ts: number | null;
0b4b58217 updated_at: string | null;
0b4b58218}
0b4b58219
bc1b2ba20async function getRepos(): Promise<Repo[]> {
bc1b2ba21 const data = await listRepos<Repo>();
bc1b2ba22 return data?.repos ?? [];
0b4b58223}
0b4b58224
0b4b58225export default async function CollabHomePage() {
0b4b58226 const cookieStore = await cookies();
0b4b58227 const token = cookieStore.get("grove_hub_token")?.value;
0b4b58228 const signedIn = !!token;
0b4b58229 const headerStore = await headers();
0b4b58230 const host =
0b4b58231 headerStore.get("x-forwarded-host") ??
0b4b58232 headerStore.get("host") ??
0b4b58233 "";
0b4b58234 const protocol = headerStore.get("x-forwarded-proto") ?? "http";
0b4b58235 const canonicalHost = host.split(",")[0]?.trim() ?? "";
0b4b58236 const groveHost = canonicalHost.replace(/^(canopy|ring|collab)\./, "");
0b4b58237 const groveOrigin = groveHost ? `${protocol}://${groveHost}` : "";
0b4b58238 const loginHref = groveOrigin ? `${groveOrigin}/login` : "/login";
0b4b58239 const exploreHref = groveOrigin ? `${groveOrigin}/` : "/";
0b4b58240
0b4b58241 if (!signedIn) {
0b4b58242 return (
0b4b58243 <div className="max-w-3xl mx-auto px-4 py-8">
0b4b58244 <div
0b4b58245 className="p-4 sm:p-8 text-center"
0b4b58246 style={{
0b4b58247 backgroundColor: "var(--bg-card)",
0b4b58248 border: "1px solid var(--border-subtle)",
0b4b58249 }}
0b4b58250 >
0b4b58251 <div className="mx-auto mb-4 w-fit opacity-70">
0b4b58252 <CollabLogo size={44} />
0b4b58253 </div>
0b4b58254 <h1 className="text-lg mb-1">Collab</h1>
0b4b58255 <p className="text-sm mb-4" style={{ color: "var(--text-faint)" }}>
0b4b58256 Collaborate on Mermaid diagrams for your Grove repositories.
0b4b58257 </p>
0b4b58258 <div className="flex items-center justify-center gap-2">
0b4b58259 <Link
0b4b58260 href={loginHref}
0b4b58261 className="px-3 py-1.5 text-sm"
0b4b58262 style={{
0b4b58263 backgroundColor: "var(--accent)",
0b4b58264 color: "var(--accent-text)",
0b4b58265 }}
0b4b58266 >
0b4b58267 Sign in
0b4b58268 </Link>
0b4b58269 <Link
0b4b58270 href={exploreHref}
0b4b58271 className="px-3 py-1.5 text-sm"
0b4b58272 style={{
0b4b58273 border: "1px solid var(--border-subtle)",
0b4b58274 color: "var(--text-secondary)",
0b4b58275 }}
0b4b58276 >
0b4b58277 Explore Grove
0b4b58278 </Link>
0b4b58279 </div>
0b4b58280 </div>
0b4b58281 </div>
0b4b58282 );
0b4b58283 }
0b4b58284
bc1b2ba85 const repos = await getRepos();
0b4b58286
0b4b58287 return <CollabRepoList repos={repos} />;
0b4b58288}