Remove unused imports and components, simplify UI
This commit is contained in:
parent
7d8474f6b8
commit
75dcded81d
|
|
@ -1,16 +1,7 @@
|
|||
import { Head } from '@inertiajs/react';
|
||||
import axios from 'axios';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { PlaceholderPattern } from '@/components/ui/placeholder-pattern';
|
||||
import { Skeleton } from '@/components/ui/skeleton';
|
||||
import UnlockMessageDialog from '@/components/unlock-message-dialog';
|
||||
import { useEncryptionKey } from '@/contexts/encryption-key-context';
|
||||
import AppLayout from '@/layouts/app-layout';
|
||||
import { decrypt, importKey } from '@/lib/crypto';
|
||||
import { getStoredKey } from '@/lib/key-storage';
|
||||
import { dashboard } from '@/routes';
|
||||
import { type BreadcrumbItem } from '@/types';
|
||||
|
||||
|
|
@ -21,159 +12,15 @@ const breadcrumbs: BreadcrumbItem[] = [
|
|||
},
|
||||
];
|
||||
|
||||
interface EncryptedMessageData {
|
||||
encrypted_content: string;
|
||||
iv: string;
|
||||
salt: string;
|
||||
}
|
||||
|
||||
export default function Dashboard() {
|
||||
const { clearEncryptionKey, isKeySet } = useEncryptionKey();
|
||||
const [messageData, setMessageData] = useState<EncryptedMessageData | null>(
|
||||
null,
|
||||
);
|
||||
const [decryptedMessage, setDecryptedMessage] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
const [showUnlockDialog, setShowUnlockDialog] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchAndDecryptMessage();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isKeySet && decryptedMessage) {
|
||||
setDecryptedMessage(null);
|
||||
} else if (isKeySet && !decryptedMessage && messageData) {
|
||||
attemptAutoDecrypt();
|
||||
}
|
||||
}, [isKeySet]);
|
||||
|
||||
async function fetchAndDecryptMessage() {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await axios.get<EncryptedMessageData>(
|
||||
'/api/encryption/message',
|
||||
);
|
||||
const data = response.data;
|
||||
setMessageData(data);
|
||||
|
||||
const storedKey = getStoredKey();
|
||||
|
||||
if (storedKey) {
|
||||
try {
|
||||
const aesKey = await importKey(storedKey);
|
||||
const decrypted = await decrypt(
|
||||
data.encrypted_content,
|
||||
aesKey,
|
||||
data.iv,
|
||||
);
|
||||
setDecryptedMessage(decrypted);
|
||||
} catch (err) {
|
||||
console.error('Auto-decrypt failed:', err);
|
||||
clearEncryptionKey();
|
||||
}
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.response?.status === 404) {
|
||||
setError(
|
||||
'No encrypted message found. Please set up encryption first.',
|
||||
);
|
||||
} else {
|
||||
console.error('Fetch error:', err);
|
||||
setError('Failed to load encrypted message.');
|
||||
}
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function attemptAutoDecrypt() {
|
||||
if (!messageData) return;
|
||||
|
||||
const storedKey = getStoredKey();
|
||||
if (!storedKey) return;
|
||||
|
||||
try {
|
||||
const aesKey = await importKey(storedKey);
|
||||
const decrypted = await decrypt(
|
||||
messageData.encrypted_content,
|
||||
aesKey,
|
||||
messageData.iv,
|
||||
);
|
||||
setDecryptedMessage(decrypted);
|
||||
} catch (err) {
|
||||
console.error('Auto-decrypt failed:', err);
|
||||
clearEncryptionKey();
|
||||
}
|
||||
}
|
||||
|
||||
function handleUnlock(message: string) {
|
||||
setDecryptedMessage(message);
|
||||
}
|
||||
|
||||
function handleLock() {
|
||||
clearEncryptionKey();
|
||||
setDecryptedMessage(null);
|
||||
}
|
||||
|
||||
return (
|
||||
<AppLayout breadcrumbs={breadcrumbs}>
|
||||
<Head title="Dashboard" />
|
||||
<div className="flex h-full flex-1 flex-col gap-4 overflow-x-auto rounded-xl p-4">
|
||||
<div className="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Encrypted Message</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
{loading ? (
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-full" />
|
||||
<Skeleton className="h-4 w-3/4" />
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="text-sm text-destructive">
|
||||
{error}
|
||||
</div>
|
||||
) : decryptedMessage ? (
|
||||
<div className="space-y-4">
|
||||
<p className="text-lg font-medium text-green-600 dark:text-green-400">
|
||||
{decryptedMessage}
|
||||
</p>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleLock}
|
||||
>
|
||||
Lock Message
|
||||
</Button>
|
||||
</div>
|
||||
) : messageData ? (
|
||||
<div className="space-y-4">
|
||||
<p className="font-mono text-sm break-all text-muted-foreground">
|
||||
{messageData.encrypted_content.substring(
|
||||
0,
|
||||
100,
|
||||
)}
|
||||
...
|
||||
</p>
|
||||
<Button
|
||||
onClick={() =>
|
||||
setShowUnlockDialog(true)
|
||||
}
|
||||
>
|
||||
Unlock Message
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border">
|
||||
<PlaceholderPattern className="absolute inset-0 size-full stroke-neutral-900/20 dark:stroke-neutral-100/20" />
|
||||
</div>
|
||||
<div className="relative aspect-video overflow-hidden rounded-xl border border-sidebar-border/70 dark:border-sidebar-border">
|
||||
<PlaceholderPattern className="absolute inset-0 size-full stroke-neutral-900/20 dark:stroke-neutral-100/20" />
|
||||
</div>
|
||||
|
|
@ -185,17 +32,6 @@ export default function Dashboard() {
|
|||
<PlaceholderPattern className="absolute inset-0 size-full stroke-neutral-900/20 dark:stroke-neutral-100/20" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{messageData && (
|
||||
<UnlockMessageDialog
|
||||
open={showUnlockDialog}
|
||||
onOpenChange={setShowUnlockDialog}
|
||||
onUnlock={handleUnlock}
|
||||
encryptedContent={messageData.encrypted_content}
|
||||
iv={messageData.iv}
|
||||
salt={messageData.salt}
|
||||
/>
|
||||
)}
|
||||
</AppLayout>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue