+ {/* Service */}
+ |
+
+
+ {serviceLabel}
+
+ |
+
+ {/* Name */}
+
+ {credential.name}
+ |
+
+ {/* Created */}
+
+
+ {timeAgo(credential.created_at)}
+
+ |
+
+ {/* Last Used */}
+
+
+ {credential.last_used_at ? timeAgo(credential.last_used_at) : "Never"}
+
+ |
+
+ {/* Action */}
+
+ {confirming ? (
+
+ Remove?
+
+
+
+ ) : (
+
+ )}
+ |
+
+ );
+}
diff --git a/dashboard/src/pages/credentials/CredentialsPage.tsx b/dashboard/src/pages/credentials/CredentialsPage.tsx
new file mode 100644
index 0000000..1a4ca91
--- /dev/null
+++ b/dashboard/src/pages/credentials/CredentialsPage.tsx
@@ -0,0 +1,84 @@
+import { useState } from "react";
+import { Key, Plus } from "lucide-react";
+import { Card } from "@/components/ui/Card";
+import { EmptyState } from "@/components/ui/EmptyState";
+import { SkeletonCard } from "@/components/ui/Skeleton";
+import { useCredentials } from "@/hooks/use-credentials";
+import { CredentialRow } from "./CredentialRow";
+import { AddCredentialModal } from "./AddCredentialModal";
+
+export default function CredentialsPage() {
+ const { credentials, loading, add, remove } = useCredentials();
+ const [showAddModal, setShowAddModal] = useState(false);
+
+ return (
+
+ {/* Toolbar */}
+
+
+ {loading
+ ? "Loading..."
+ : `${credentials.length} credential${credentials.length !== 1 ? "s" : ""}`}
+
+
+
+
+ {/* Content */}
+ {loading ? (
+
+ ) : credentials.length === 0 ? (
+
}
+ title="No credentials stored"
+ subtitle="Add your first API key to get started."
+ />
+ ) : (
+
+
+
+
+ |
+ Service
+ |
+
+ Name
+ |
+
+ Created
+ |
+
+ Last Used
+ |
+
+ Actions
+ |
+
+
+
+ {credentials.map((cred) => (
+
+ ))}
+
+
+
+ )}
+
+ {/* Add modal */}
+
setShowAddModal(false)}
+ onSubmit={add}
+ />
+
+ );
+}