SPB Git forge

spb/fetcha

Public
11commits 1branches 0releases
1.5 MBsize
maindefault branch
16 days agolast push
TypeScript 97.5% SQL 1.4% Python 0.8%
4.7 KB · 101 lines tsx
Raw Blame History
1import Link from "next/link";2import { BadgeCheck, MailWarning } from "lucide-react";3import { getWorkspace } from "@/lib/session";4import { formatDate, titleCase } from "@/lib/format";5import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";6import { Badge } from "@/components/ui/badge";7import { Alert } from "@/components/ui/alert";8import { ThemeToggle } from "@/components/ui/theme";9import { ResendVerificationButton } from "@/components/dashboard/resend-verification";10import { ProfileNameForm } from "@/components/dashboard/settings/profile-form";11import { ChangeEmailDialog } from "@/components/dashboard/settings/change-email-dialog";12import { OrganizationForm } from "@/components/dashboard/settings/organization-form";13import { DeleteAccountDialog } from "@/components/dashboard/settings/delete-account-dialog";1415export const dynamic = "force-dynamic";1617export default async function SettingsProfilePage({ searchParams }: { searchParams: Promise<{ "email-changed"?: string }> }) {18  const sp = await searchParams;19  const ws = await getWorkspace();20  const canEditOrg = ["owner", "admin", "billing"].includes(ws.role);2122  return (23    <div className="grid gap-6">24      {sp["email-changed"] === "1" ? <Alert variant="success" title="Email address updated">Your new address is now your login. If it is not verified yet, use the button below.</Alert> : null}2526      <Card>27        <CardHeader>28          <CardTitle>Profile</CardTitle>29          <CardDescription>How you appear across Fetcha. Member since {formatDate(ws.user.createdAt, { timeStyle: undefined })}.</CardDescription>30        </CardHeader>31        <CardContent className="grid gap-6">32          <ProfileNameForm name={ws.user.name} />33          <div className="grid gap-2 border-t border-border pt-5">34            <div className="text-[13px] font-medium">Email</div>35            <div className="flex flex-wrap items-center gap-3">36              <span className="font-mono text-[13.5px]">{ws.user.email}</span>37              {ws.user.emailVerified ? (38                <Badge variant="success">39                  <BadgeCheck className="size-3" /> Verified40                </Badge>41              ) : (42                <Badge variant="warning">43                  <MailWarning className="size-3" /> Unverified44                </Badge>45              )}46              <div className="ml-auto flex items-center gap-2">47                {!ws.user.emailVerified ? <ResendVerificationButton email={ws.user.email} size="sm" /> : null}48                <ChangeEmailDialog currentEmail={ws.user.email} />49              </div>50            </div>51            <p className="text-xs text-fg-subtle">{ws.user.emailVerified ? "Security notices and receipts go to this address." : "Verify your address to unlock production API access."}</p>52          </div>53        </CardContent>54      </Card>5556      <Card>57        <CardHeader>58          <div className="flex items-center justify-between gap-3">59            <CardTitle>Organization</CardTitle>60            <div className="flex items-center gap-2">61              <Badge variant="outline">{titleCase(ws.role)}</Badge>62              <Badge variant="accent">{titleCase(ws.organization.plan)} plan</Badge>63            </div>64          </div>65          <CardDescription>66            Organization-wide spending limits apply on top of per-project limits. Manage your plan in{" "}67            <Link href="/dashboard/billing" className="text-fg underline-offset-4 hover:underline">68              Billing69            </Link>70            . Teams and invitations are not available yet.71          </CardDescription>72        </CardHeader>73        <CardContent>74          <OrganizationForm name={ws.organization.name} softLimitUsd={ws.organization.softLimitUsd} hardLimitUsd={ws.organization.hardLimitUsd} canEdit={canEditOrg} />75        </CardContent>76      </Card>7778      <Card>79        <CardHeader>80          <CardTitle>Appearance</CardTitle>81          <CardDescription>Theme preference is stored in this browser.</CardDescription>82        </CardHeader>83        <CardContent className="flex items-center justify-between gap-4">84          <p className="text-[13px] text-fg-muted">Light, dark, or follow your system.</p>85          <ThemeToggle className="border border-border" />86        </CardContent>87      </Card>8889      <Card className="border-danger/30">90        <CardHeader>91          <CardTitle className="text-danger">Danger zone</CardTitle>92          <CardDescription>Deleting your account removes your organization, projects, keys and request history. Requires your password and an email confirmation.</CardDescription>93        </CardHeader>94        <CardContent>95          <DeleteAccountDialog email={ws.user.email} />96        </CardContent>97      </Card>98    </div>99  );100}101