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
39 changes: 39 additions & 0 deletions apps/frontend/src/app/components/theme-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use client';

import { useTheme } from 'next-themes';
import { Moon, Sun } from 'lucide-react';
import { useEffect, useState } from 'react';

export function ThemeToggle() {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);

useEffect(() => {
setMounted(true);
}, []);

if (!mounted) {
return (
<button
className="flex items-center justify-center w-9 h-9 rounded-lg transition-colors cursor-pointer"
aria-label="Toggle theme"
tabIndex={-1}
style={{ visibility: 'hidden' }}
>
<Sun className="size-4" />
</button>
);
}

const isDark = theme === 'dark';

return (
<button
onClick={() => setTheme(isDark ? 'light' : 'dark')}
className="flex items-center justify-center w-9 h-9 hover:bg-white/5 rounded-lg transition-colors cursor-pointer"
aria-label={`Switch to ${isDark ? 'light' : 'dark'} mode`}
>
{isDark ? <Sun className="size-4" /> : <Moon className="size-4" />}
</button>
);
}
4 changes: 2 additions & 2 deletions apps/frontend/src/app/dashboard/api-keys/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ export default function ApiKeysLoading() {
<Skeleton className="h-11 w-44 rounded-lg" />
</div>

<div className="bg-gradient-to-br from-white/[0.03] to-transparent border border-white/5 rounded-xl overflow-hidden">
<div className="bg-card border-border rounded-xl overflow-hidden">
<div className="space-y-4 p-6">
{Array.from({ length: 2 }).map((_, i) => (
<div key={i} className="p-6 bg-white/[0.02] border border-white/5 rounded-lg">
<div key={i} className="p-6 bg-muted/30 border-border rounded-lg">
<div className="flex flex-col lg:flex-row lg:items-center gap-6">
<div className="flex-1">
<div className="flex items-center gap-3 mb-3">
Expand Down
26 changes: 13 additions & 13 deletions apps/frontend/src/app/dashboard/api-keys/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export default function ApiKeysPage() {
>
API Keys
</motion.h1>
<p className="text-sm text-neutral-400">Manage authentication credentials for API access</p>
<p className="text-sm text-muted-foreground">Manage authentication credentials for API access</p>
</div>

<motion.div
Expand All @@ -44,7 +44,7 @@ export default function ApiKeysPage() {
<Eye className="size-5 text-yellow-400 mt-0.5" />
<div>
<div className="font-medium text-yellow-400 mb-1">Keep your keys secure</div>
<div className="text-sm text-neutral-400">
<div className="text-sm text-muted-foreground">
Never share your API keys in publicly accessible areas such as GitHub, client-side code, or logging systems.
</div>
</div>
Expand All @@ -56,14 +56,14 @@ export default function ApiKeysPage() {
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
>
<button className="px-4 py-3 bg-white text-black rounded-lg hover:bg-neutral-200 transition-all flex items-center gap-2 font-medium cursor-pointer">
<button className="px-4 py-3 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-all flex items-center gap-2 font-medium cursor-pointer">
<Plus className="size-4" />
Generate New Key
</button>
</motion.div>

<motion.div
className="bg-gradient-to-br from-white/[0.03] to-transparent border border-white/5 rounded-xl overflow-hidden"
className="bg-card border-border rounded-xl overflow-hidden"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
Expand All @@ -72,7 +72,7 @@ export default function ApiKeysPage() {
{apiKeys.map((key, index) => (
<motion.div
key={key.id}
className="p-6 bg-white/[0.02] border border-white/5 rounded-lg hover:border-white/10 transition-all"
className="p-6 bg-muted/30 border-border rounded-lg hover:border-foreground/10 transition-all"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 + index * 0.05 }}
Expand All @@ -81,40 +81,40 @@ export default function ApiKeysPage() {
<div className="flex-1">
<div className="flex items-center gap-3 mb-3">
<div className="font-medium">{key.name}</div>
<span className="px-2 py-1 bg-white/5 rounded text-xs">{key.permissions}</span>
<span className="px-2 py-1 bg-muted rounded text-xs">{key.permissions}</span>
</div>

<div className="flex items-center gap-2 mb-3">
<div className="font-mono text-sm bg-black border border-white/10 rounded px-3 py-2 flex-1">
<div className="font-mono text-sm bg-background border-border rounded px-3 py-2 flex-1">
{visibleKeys.has(key.id) ? key.id : "sk_" + "•".repeat(20)}
</div>
<button
onClick={() => toggleKeyVisibility(key.id)}
className="p-2 hover:bg-white/5 rounded-lg transition-colors cursor-pointer"
className="p-2 hover:bg-accent rounded-lg transition-colors cursor-pointer"
title={visibleKeys.has(key.id) ? "Hide" : "Show"}
>
{visibleKeys.has(key.id) ? <EyeOff className="size-4" /> : <Eye className="size-4" />}
</button>
<button
className="p-2 hover:bg-white/5 rounded-lg transition-colors cursor-pointer"
className="p-2 hover:bg-accent rounded-lg transition-colors cursor-pointer"
title="Copy"
>
<Copy className="size-4" />
</button>
</div>

<div className="grid sm:grid-cols-2 gap-4 text-xs text-neutral-400">
<div className="grid sm:grid-cols-2 gap-4 text-xs text-muted-foreground">
<div>
<span className="text-neutral-500">Created:</span> {key.created}
<span className="text-muted-foreground/70">Created:</span> {key.created}
</div>
<div>
<span className="text-neutral-500">Last used:</span> {key.lastUsed}
<span className="text-muted-foreground/70">Last used:</span> {key.lastUsed}
</div>
</div>
</div>

<div className="flex gap-2">
<button className="px-4 py-2 bg-white/5 border border-white/10 rounded-lg hover:bg-white/10 transition-all text-sm cursor-pointer">
<button className="px-4 py-2 bg-muted border-border rounded-lg hover:bg-accent transition-all text-sm cursor-pointer">
Rotate
</button>
<button className="p-2 hover:bg-red-400/10 rounded-lg transition-colors text-red-400 cursor-pointer">
Expand Down
8 changes: 4 additions & 4 deletions apps/frontend/src/app/dashboard/audit-logs/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function AuditLogsLoading() {
{Array.from({ length: 4 }).map((_, i) => (
<div
key={i}
className="p-4 bg-gradient-to-br from-white/[0.05] to-transparent border border-white/10 rounded-xl"
className="p-4 bg-card border-border rounded-xl"
>
<Skeleton className="h-8 w-20 mb-1" />
<Skeleton className="h-4 w-24" />
Expand All @@ -30,11 +30,11 @@ export default function AuditLogsLoading() {
<Skeleton className="h-11 w-24 rounded-lg" />
</div>

<div className="bg-gradient-to-br from-white/[0.03] to-transparent border border-white/5 rounded-xl overflow-hidden">
<div className="bg-card border-border rounded-xl overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-white/5 bg-white/[0.02]">
<tr className="border-border bg-muted/20">
{Array.from({ length: 6 }).map((_, i) => (
<th key={i} className="py-4 px-4">
<Skeleton className="h-4 w-20" />
Expand All @@ -44,7 +44,7 @@ export default function AuditLogsLoading() {
</thead>
<tbody>
{Array.from({ length: 8 }).map((_, i) => (
<tr key={i} className="border-b border-white/5">
<tr key={i} className="border-b border-border">
{Array.from({ length: 6 }).map((_, j) => (
<td key={j} className="py-4 px-4">
<Skeleton className="h-4 w-24" />
Expand Down
38 changes: 19 additions & 19 deletions apps/frontend/src/app/dashboard/audit-logs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ export default function AuditLogsPage() {
) : auditLogs.map((log, index) => (
<motion.tr
key={index}
className="border-b border-white/5 hover:bg-white/[0.02] transition-colors"
className="border-border hover:bg-muted/20 transition-colors"
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.4 + index * 0.03 }}
>
<td className="py-4 px-4 text-neutral-400 whitespace-nowrap">{log.timestamp}</td>
<td className="py-4 px-4 text-muted-foreground whitespace-nowrap">{log.timestamp}</td>
<td className="py-4 px-4 font-medium">{log.action}</td>
<td className="py-4 px-4 font-mono text-xs text-neutral-400">{log.actor}</td>
<td className="py-4 px-4 font-mono text-xs text-neutral-400">{log.ip}</td>
<td className="py-4 px-4 text-neutral-400 text-xs">{log.details}</td>
<td className="py-4 px-4 font-mono text-xs text-muted-foreground">{log.actor}</td>
<td className="py-4 px-4 font-mono text-xs text-muted-foreground">{log.ip}</td>
<td className="py-4 px-4 text-muted-foreground text-xs">{log.details}</td>
<td className="py-4 px-4">
<span
className={`inline-flex items-center gap-1 px-2 py-1 rounded text-xs ${
Expand All @@ -59,7 +59,7 @@ export default function AuditLogsPage() {
>
Audit Logs
</motion.h1>
<p className="text-sm text-neutral-400">Complete activity history with tamper-proof logging</p>
<p className="text-sm text-muted-foreground">Complete activity history with tamper-proof logging</p>
</div>

<div className="grid sm:grid-cols-4 gap-4 mb-8">
Expand All @@ -71,13 +71,13 @@ export default function AuditLogsPage() {
].map((stat, index) => (
<motion.div
key={stat.label}
className="p-4 bg-gradient-to-br from-white/[0.05] to-transparent border border-white/10 rounded-xl"
className="p-4 bg-card border-border rounded-xl"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
>
<div className="text-2xl font-medium mb-1">{stat.value}</div>
<div className="text-xs text-neutral-500">{stat.label}</div>
<div className="text-xs text-muted-foreground/70">{stat.label}</div>
</motion.div>
))}
</div>
Expand All @@ -99,35 +99,35 @@ export default function AuditLogsPage() {
repeat: Infinity,
}}
/>
<span className="text-sm text-neutral-400">Live monitoring active</span>
<span className="text-sm text-muted-foreground">Live monitoring active</span>
</div>
<div className="flex-1" />
<button className="px-4 py-3 bg-white/5 border border-white/10 rounded-lg hover:bg-white/10 transition-all flex items-center justify-center gap-2 text-sm cursor-pointer">
<button className="px-4 py-3 bg-muted border-border rounded-lg hover:bg-accent transition-all flex items-center justify-center gap-2 text-sm cursor-pointer">
<Filter className="size-4" />
Filter
</button>
<button className="px-4 py-3 bg-white/5 border border-white/10 rounded-lg hover:bg-white/10 transition-all flex items-center justify-center gap-2 text-sm cursor-pointer">
<button className="px-4 py-3 bg-muted border-border rounded-lg hover:bg-accent transition-all flex items-center justify-center gap-2 text-sm cursor-pointer">
<Download className="size-4" />
Export
</button>
</motion.div>

<motion.div
className="bg-gradient-to-br from-white/[0.03] to-transparent border border-white/5 rounded-xl overflow-hidden"
className="bg-card border-border rounded-xl overflow-hidden"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3 }}
>
<div className="overflow-x-auto">
<table className="w-full text-sm">
<thead>
<tr className="border-b border-white/5 bg-white/[0.02]">
<th className="text-left py-4 px-4 text-neutral-500 font-medium whitespace-nowrap">Timestamp</th>
<th className="text-left py-4 px-4 text-neutral-500 font-medium">Action</th>
<th className="text-left py-4 px-4 text-neutral-500 font-medium">Actor</th>
<th className="text-left py-4 px-4 text-neutral-500 font-medium">IP Address</th>
<th className="text-left py-4 px-4 text-neutral-500 font-medium">Details</th>
<th className="text-left py-4 px-4 text-neutral-500 font-medium">Status</th>
<tr className="border-border bg-muted/20">
<th className="text-left py-4 px-4 text-muted-foreground/70 font-medium whitespace-nowrap">Timestamp</th>
<th className="text-left py-4 px-4 text-muted-foreground/70 font-medium">Action</th>
<th className="text-left py-4 px-4 text-muted-foreground/70 font-medium">Actor</th>
<th className="text-left py-4 px-4 text-muted-foreground/70 font-medium">IP Address</th>
<th className="text-left py-4 px-4 text-muted-foreground/70 font-medium">Details</th>
<th className="text-left py-4 px-4 text-muted-foreground/70 font-medium">Status</th>
</tr>
</thead>
<tbody>
Expand Down
10 changes: 5 additions & 5 deletions apps/frontend/src/app/dashboard/compliance/loading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default function ComplianceLoading() {
{Array.from({ length: 4 }).map((_, i) => (
<div
key={i}
className="p-6 bg-gradient-to-br from-white/[0.05] to-transparent border border-white/10 rounded-xl"
className="p-6 bg-card border-border rounded-xl"
>
<div className="flex items-center gap-3 mb-4">
<Skeleton className="h-9 w-9 rounded-lg" />
Expand All @@ -24,11 +24,11 @@ export default function ComplianceLoading() {
</div>

<div className="grid lg:grid-cols-2 gap-6">
<div className="p-6 bg-gradient-to-br from-white/[0.03] to-transparent border border-white/5 rounded-xl">
<div className="p-6 bg-card border-border rounded-xl">
<Skeleton className="h-6 w-44 mb-6" />
<div className="space-y-4">
{Array.from({ length: 4 }).map((_, i) => (
<div key={i} className="p-4 bg-white/[0.02] border border-white/5 rounded-lg">
<div key={i} className="p-4 bg-muted/30 border-border rounded-lg">
<div className="flex items-center justify-between">
<div>
<Skeleton className="h-5 w-36 mb-1" />
Expand All @@ -42,11 +42,11 @@ export default function ComplianceLoading() {
<Skeleton className="h-11 w-full mt-6 rounded-lg" />
</div>

<div className="p-6 bg-gradient-to-br from-white/[0.03] to-transparent border border-white/5 rounded-xl">
<div className="p-6 bg-card border-border rounded-xl">
<Skeleton className="h-6 w-44 mb-6" />
<div className="space-y-6">
{Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="pb-4 border-b border-white/5 last:border-0">
<div key={i} className="pb-4 border-b border-border last:border-0">
<div className="flex items-center justify-between mb-2">
<Skeleton className="h-4 w-32" />
<Skeleton className="h-6 w-16" />
Expand Down
Loading
Loading