diff --git a/thoughts-frontend/app/settings/api-keys/page.tsx b/thoughts-frontend/app/settings/api-keys/page.tsx new file mode 100644 index 0000000..629b071 --- /dev/null +++ b/thoughts-frontend/app/settings/api-keys/page.tsx @@ -0,0 +1,27 @@ +import { cookies } from "next/headers"; +import { redirect } from "next/navigation"; +import { getApiKeys } from "@/lib/api"; +import { ApiKeyList } from "@/components/api-keys-list"; + +export default async function ApiKeysPage() { + const token = (await cookies()).get("auth_token")?.value; + if (!token) { + redirect("/login"); + } + + const initialApiKeys = await getApiKeys(token).catch(() => ({ + apiKeys: [], + })); + + return ( +
+ Manage API keys for third-party applications. +
+Manage your account settings and profile. diff --git a/thoughts-frontend/app/settings/profile/page.tsx b/thoughts-frontend/app/settings/profile/page.tsx index efb1067..f0d6b12 100644 --- a/thoughts-frontend/app/settings/profile/page.tsx +++ b/thoughts-frontend/app/settings/profile/page.tsx @@ -18,8 +18,8 @@ export default async function EditProfilePage() { } return ( -
This is how others will see you on the site.
diff --git a/thoughts-frontend/components/api-keys-list.tsx b/thoughts-frontend/components/api-keys-list.tsx
new file mode 100644
index 0000000..7fd8486
--- /dev/null
+++ b/thoughts-frontend/components/api-keys-list.tsx
@@ -0,0 +1,214 @@
+// thoughts-frontend/components/api-key-list.tsx
+"use client";
+
+import { useState } from "react";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { z } from "zod";
+import { toast } from "sonner";
+import { useAuth } from "@/hooks/use-auth";
+import {
+ ApiKey,
+ CreateApiKeySchema,
+ createApiKey,
+ deleteApiKey,
+} from "@/lib/api";
+import { Button } from "@/components/ui/button";
+import {
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from "@/components/ui/card";
+import {
+ Form,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormControl,
+ FormMessage,
+} from "@/components/ui/form";
+import { Input } from "@/components/ui/input";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ AlertDialogTrigger,
+} from "@/components/ui/alert-dialog";
+import { Copy, KeyRound, Plus, Trash2 } from "lucide-react";
+import { format } from "date-fns";
+
+interface ApiKeyListProps {
+ initialApiKeys: ApiKey[];
+}
+
+export function ApiKeyList({ initialApiKeys }: ApiKeyListProps) {
+ const [keys, setKeys] = useState {key.name}
+ {`Created on ${format(key.createdAt, "PPP")}`}
+
+ {`${key.keyPrefix}...`}
+
+ You have no API keys.
+
diff --git a/thoughts-frontend/lib/api.ts b/thoughts-frontend/lib/api.ts
index 67cdcb8..9ab51a2 100644
--- a/thoughts-frontend/lib/api.ts
+++ b/thoughts-frontend/lib/api.ts
@@ -65,11 +65,32 @@ export const SearchResultsSchema = z.object({
thoughts: z.object({ thoughts: z.array(ThoughtSchema) }),
});
+export const ApiKeySchema = z.object({
+ id: z.uuid(),
+ name: z.string(),
+ keyPrefix: z.string(),
+ createdAt: z.coerce.date(),
+});
+
+export const ApiKeyResponseSchema = ApiKeySchema.extend({
+ plaintextKey: z.string().optional(),
+});
+
+export const ApiKeyListSchema = z.object({
+ apiKeys: z.array(ApiKeySchema),
+});
+
+export const CreateApiKeySchema = z.object({
+ name: z.string().min(1, "Key name cannot be empty."),
+});
+
export type User = z.infer
+ {keys.map((key) => (
+
+ ) : (
+