Files
stack/apps/web/src/app/(authenticated)/settings/credentials/page.tsx
Jason Woltje edcff6a0e0
All checks were successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/api Pipeline was successful
fix(api,web): add workspace context to widgets and auto-detect workspace ID (#532)
Co-authored-by: Jason Woltje <jason@diversecanvas.com>
Co-committed-by: Jason Woltje <jason@diversecanvas.com>
2026-02-27 04:53:07 +00:00

101 lines
3.2 KiB
TypeScript

"use client";
import { useState, useEffect } from "react";
import { Plus, History } from "lucide-react";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
import { fetchCredentials, type Credential } from "@/lib/api/credentials";
import { useWorkspaceId } from "@/lib/hooks";
export default function CredentialsPage(): React.ReactElement {
const [credentials, setCredentials] = useState<Credential[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const workspaceId = useWorkspaceId();
useEffect(() => {
if (!workspaceId) return;
void loadCredentials(workspaceId);
}, [workspaceId]);
async function loadCredentials(wsId: string): Promise<void> {
try {
setIsLoading(true);
const response = await fetchCredentials(wsId);
setCredentials(response.data);
setError(null);
} catch (err) {
setError(err instanceof Error ? err.message : "Failed to load credentials");
} finally {
setIsLoading(false);
}
}
return (
<div className="max-w-6xl mx-auto p-6">
{/* Header */}
<div className="mb-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold">Credentials</h1>
<p className="text-muted-foreground mt-1">
Securely store and manage API keys, tokens, and passwords
</p>
</div>
<div className="flex gap-2">
<Button disabled>
<Plus className="mr-2 h-4 w-4" />
Add Credential
</Button>
<Link href="/settings/credentials/audit">
<Button variant="outline">
<History className="mr-2 h-4 w-4" />
Audit Log
</Button>
</Link>
</div>
</div>
</div>
{/* Error Display */}
{error && <div className="mb-4 p-4 bg-red-50 text-red-800 rounded-md">{error}</div>}
{/* Loading State */}
{isLoading ? (
<div className="text-center py-12">
<p className="text-gray-500">Loading credentials...</p>
</div>
) : credentials.length === 0 ? (
<Card>
<CardContent className="flex flex-col items-center justify-center py-12">
<p className="text-gray-500 mb-4">No credentials found</p>
<Button disabled>
<Plus className="mr-2 h-4 w-4" />
Add First Credential
</Button>
</CardContent>
</Card>
) : (
<div className="grid gap-4 grid-cols-1">
<Card>
<CardContent className="pt-6">
<div className="text-sm text-gray-600">
<p>Credentials feature coming soon.</p>
<p className="mt-2">
<Link href="/settings/credentials/audit">
<Button variant="link" className="p-0">
View Audit Log
</Button>
</Link>
</p>
</div>
</CardContent>
</Card>
</div>
)}
</div>
);
}