Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 85 additions & 23 deletions apps/dashboard/src/routes/_protected/dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@quickhub/ui/components/avatar";
import { Badge } from "@quickhub/ui/components/badge";
import { Button } from "@quickhub/ui/components/button";
import {
Card,
CardDescription,
CardHeader,
CardTitle,
} from "@quickhub/ui/components/card";
import { createFileRoute } from "@tanstack/react-router";
import { signOut } from "#/lib/auth.client";

Expand All @@ -7,31 +20,80 @@ export const Route = createFileRoute("/_protected/dashboard")({

function DashboardPage() {
const { user } = Route.useRouteContext();
const displayName = user.name ?? user.email ?? "QuickHub user";
const initials = displayName
.split(" ")
.map((part) => part[0])
.join("")
.slice(0, 2)
.toUpperCase();

return (
<main className="p-8">
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
{user.image && (
<img
src={user.image}
alt={user.name}
className="h-10 w-10 rounded-full"
/>
)}
<h1 className="text-2xl font-bold">Welcome, {user.name}</h1>
</div>
<button
type="button"
onClick={() =>
signOut().then(() => {
window.location.href = "/";
})
}
className="rounded-md border px-4 py-2 hover:bg-neutral-100 transition-colors"
>
Sign out
</button>
<main className="min-h-screen bg-[linear-gradient(180deg,_color-mix(in_oklch,_var(--color-secondary)_55%,_transparent)_0%,_transparent_38%)] p-4 sm:p-8">
<div className="mx-auto grid max-w-5xl gap-6">
<Card className="border-border/70 bg-background/95 shadow-sm">
<CardHeader className="flex flex-col gap-5 sm:flex-row sm:items-center sm:justify-between">
<div className="flex items-center gap-4">
<Avatar className="size-14 border border-border/70">
<AvatarImage src={user.image ?? undefined} alt={displayName} />
<AvatarFallback>{initials}</AvatarFallback>
</Avatar>
<div className="space-y-1">
<div className="flex items-center gap-2">
<CardTitle className="text-2xl tracking-tight">
Welcome, {displayName}
</CardTitle>
<Badge variant="secondary">Connected</Badge>
</div>
<CardDescription className="text-sm">
The dashboard now pulls from the shared Circle-derived
component library in <code>@quickhub/ui</code>.
</CardDescription>
</div>
</div>
<Button
type="button"
variant="outline"
onClick={() =>
signOut().then(() => {
window.location.href = "/";
})
}
>
Sign out
</Button>
</CardHeader>
</Card>

<section className="grid gap-4 md:grid-cols-3">
<Card className="border-border/70 bg-background/90">
<CardHeader>
<CardTitle className="text-base">Theme</CardTitle>
<CardDescription>
Circle tokens now define the workspace palette and surface
language.
</CardDescription>
</CardHeader>
</Card>
<Card className="border-border/70 bg-background/90">
<CardHeader>
<CardTitle className="text-base">Primitives</CardTitle>
<CardDescription>
Shared buttons, cards, badges, dialogs, forms, and more now live
in the UI package.
</CardDescription>
</CardHeader>
</Card>
<Card className="border-border/70 bg-background/90">
<CardHeader>
<CardTitle className="text-base">Next step</CardTitle>
<CardDescription>
Build QuickHub-specific layouts on top of these imported
foundation pieces.
</CardDescription>
</CardHeader>
</Card>
</section>
</div>
</main>
);
Expand Down
184 changes: 126 additions & 58 deletions apps/dashboard/src/routes/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import { Badge } from "@quickhub/ui/components/badge";
import { Button } from "@quickhub/ui/components/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@quickhub/ui/components/card";
import { createFileRoute, Link } from "@tanstack/react-router";
import { getSession } from "#/lib/auth.functions";
import { getUserRepos } from "#/lib/github.functions";
Expand All @@ -18,68 +27,127 @@ export const Route = createFileRoute("/")({
function Home() {
const { session } = Route.useRouteContext();
const { repos } = Route.useLoaderData();
const ctaCopy = session ? "Open dashboard" : "Continue with GitHub";
const ctaLink = session ? "/dashboard" : "/login";

return (
<main className="mx-auto max-w-2xl px-4 py-16">
<div className="text-center space-y-6">
<h1 className="text-4xl font-bold tracking-tight">QuickHub</h1>
<p className="text-muted-foreground">
A lightweight, focused view of GitHub.
</p>
{session ? (
<Link
to="/dashboard"
className="inline-block rounded-md bg-neutral-900 px-6 py-3 text-white hover:bg-neutral-800 transition-colors"
>
Go to Dashboard
</Link>
) : (
<Link
to="/login"
className="inline-block rounded-md bg-neutral-900 px-6 py-3 text-white hover:bg-neutral-800 transition-colors"
>
Sign in with GitHub
</Link>
<main className="min-h-screen bg-[radial-gradient(circle_at_top,_color-mix(in_oklch,_var(--color-primary)_6%,_transparent),_transparent_48%),linear-gradient(180deg,_color-mix(in_oklch,_var(--color-secondary)_65%,_white)_0%,_transparent_45%)]">
<div className="mx-auto flex w-full max-w-6xl flex-col gap-10 px-4 py-10 sm:px-6 lg:px-8">
<section className="grid gap-6 lg:grid-cols-[minmax(0,1.2fr)_minmax(320px,420px)]">
<Card className="border-border/70 bg-background/90 shadow-sm backdrop-blur">
<CardHeader className="gap-5">
<Badge variant="outline" className="w-fit">
Circle base imported
</Badge>
<div className="space-y-3">
<CardTitle className="text-4xl tracking-tight sm:text-5xl">
QuickHub, now on a shared UI foundation.
</CardTitle>
<CardDescription className="max-w-2xl text-base leading-7 text-muted-foreground">
Circle&apos;s tokens and primitives are now the baseline for
QuickHub, so the app can grow from a consistent design system
instead of ad hoc styles.
</CardDescription>
</div>
</CardHeader>
<CardContent className="flex flex-col gap-4 sm:flex-row sm:items-center">
<Button asChild size="lg">
<Link to={ctaLink}>{ctaCopy}</Link>
</Button>
<p className="text-sm text-muted-foreground">
Shared theme tokens live in <code>@quickhub/ui</code> and can
now drive future screens.
</p>
</CardContent>
</Card>

<Card className="border-border/70 bg-container text-foreground shadow-sm">
<CardHeader>
<CardTitle className="text-lg">Base kit</CardTitle>
<CardDescription>
Imported primitives ready to extend.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-3 text-sm text-muted-foreground">
<div className="flex items-center justify-between rounded-lg border border-border/70 bg-background/80 px-4 py-3">
<span>Theme tokens</span>
<Badge variant="secondary">active</Badge>
</div>
<div className="flex items-center justify-between rounded-lg border border-border/70 bg-background/80 px-4 py-3">
<span>32 UI primitives</span>
<Badge variant="secondary">shared</Badge>
</div>
<div className="flex items-center justify-between rounded-lg border border-border/70 bg-background/80 px-4 py-3">
<span>Dashboard wired</span>
<Badge variant="secondary">validated</Badge>
</div>
</CardContent>
</Card>
</section>

{repos.length > 0 && (
<section className="grid gap-4">
<div>
<h2 className="text-xl font-semibold tracking-tight">
Recent repositories
</h2>
<p className="text-sm text-muted-foreground">
Current data rendered with the shared card, badge, and button
language.
</p>
</div>
<div className="grid gap-4 md:grid-cols-2">
{repos.map((repo) => (
<Card
key={repo.id}
className="border-border/70 bg-background/90 shadow-sm"
>
<CardHeader className="gap-3">
<div className="flex items-start justify-between gap-3">
<div className="space-y-1">
<CardTitle className="text-lg">
<a
href={repo.url}
target="_blank"
rel="noopener noreferrer"
className="transition-opacity hover:opacity-70"
>
{repo.name}
</a>
</CardTitle>
<CardDescription>
{repo.description ??
"A focused repository surfaced from your GitHub account."}
</CardDescription>
</div>
{repo.isPrivate ? (
<Badge variant="outline">Private</Badge>
) : (
<Badge variant="secondary">Public</Badge>
)}
</div>
</CardHeader>
<CardContent className="flex items-center justify-between gap-3 text-sm text-muted-foreground">
<div className="flex items-center gap-3">
{repo.language ? <span>{repo.language}</span> : null}
{repo.stars ? <span>{repo.stars} stars</span> : null}
</div>
<Button asChild variant="ghost" size="sm">
<a
href={repo.url}
target="_blank"
rel="noopener noreferrer"
>
View repo
</a>
</Button>
</CardContent>
</Card>
))}
</div>
</section>
)}
</div>

{repos.length > 0 && (
<div className="mt-12 space-y-3">
<h2 className="text-lg font-semibold">Recent repositories</h2>
<ul className="divide-y divide-neutral-200">
{repos.map((repo) => (
<li key={repo.id} className="py-3">
<div className="flex items-center justify-between">
<div>
<a
href={repo.url}
target="_blank"
rel="noopener noreferrer"
className="font-medium hover:underline"
>
{repo.name}
</a>
{repo.isPrivate && (
<span className="ml-2 rounded-full border px-2 py-0.5 text-xs text-muted-foreground">
private
</span>
)}
</div>
<div className="flex items-center gap-3 text-sm text-muted-foreground">
{repo.language && <span>{repo.language}</span>}
{repo.stars ? <span>{repo.stars} stars</span> : null}
</div>
</div>
{repo.description && (
<p className="mt-1 text-sm text-muted-foreground">
{repo.description}
</p>
)}
</li>
))}
</ul>
</div>
)}
</main>
);
}
44 changes: 30 additions & 14 deletions apps/dashboard/src/routes/login.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
import { Button } from "@quickhub/ui/components/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@quickhub/ui/components/card";
import { createFileRoute, redirect } from "@tanstack/react-router";
import { signIn } from "#/lib/auth.client";
import { getSession } from "#/lib/auth.functions";
Expand All @@ -12,20 +20,28 @@ export const Route = createFileRoute("/login")({

function LoginPage() {
return (
<main className="flex min-h-screen items-center justify-center">
<div className="text-center space-y-6">
<h1 className="text-3xl font-bold">Sign in to QuickHub</h1>
<p className="text-muted-foreground">
Connect your GitHub account to get started.
</p>
<button
type="button"
onClick={() => signIn.social({ provider: "github" })}
className="rounded-md bg-neutral-900 px-6 py-3 text-white hover:bg-neutral-800 transition-colors"
>
Continue with GitHub
</button>
</div>
<main className="flex min-h-screen items-center justify-center bg-[radial-gradient(circle_at_top,_color-mix(in_oklch,_var(--color-primary)_6%,_transparent),_transparent_48%),linear-gradient(180deg,_color-mix(in_oklch,_var(--color-secondary)_65%,_white)_0%,_transparent_45%)] px-4">
<Card className="w-full max-w-md border-border/70 bg-background/95 shadow-sm backdrop-blur">
<CardHeader className="text-center">
<CardTitle className="text-3xl tracking-tight">
Sign in to QuickHub
</CardTitle>
<CardDescription className="text-base">
Connect GitHub to start from the imported Circle base theme and grow
your own workflow from there.
</CardDescription>
</CardHeader>
<CardContent>
<Button
type="button"
size="lg"
className="w-full"
onClick={() => signIn.social({ provider: "github" })}
>
Continue with GitHub
</Button>
</CardContent>
</Card>
</main>
);
}
Loading