1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
import { useState, useCallback, useEffect } from "react";
import { useParams, useNavigate } from "react-router";
import { Masthead } from "../components/Masthead";
import { FileList } from "../components/files/FileList";
import { FileDetail } from "../components/files/FileDetail";
import { useFiles } from "../hooks/useFiles";
import type { FileDetail as FileDetailType } from "../lib/api";
export default function FilesPage() {
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const { files, loading, error, fetchFile, editFile, removeFile } = useFiles();
const [fileDetail, setFileDetail] = useState<FileDetailType | null>(null);
const [detailLoading, setDetailLoading] = useState(false);
// Load file detail when URL has an id
useEffect(() => {
if (id) {
setDetailLoading(true);
fetchFile(id).then((detail) => {
setFileDetail(detail);
setDetailLoading(false);
});
} else {
setFileDetail(null);
}
}, [id, fetchFile]);
const handleSelectFile = useCallback(
(fileId: string) => {
navigate(`/files/${fileId}`);
},
[navigate]
);
const handleBack = useCallback(() => {
navigate("/files");
}, [navigate]);
const handleDelete = useCallback(
async (fileId: string) => {
if (confirm("Are you sure you want to delete this file?")) {
const success = await removeFile(fileId);
if (success && id === fileId) {
navigate("/files");
}
}
},
[removeFile, id, navigate]
);
const handleSave = useCallback(
async (fileId: string, name: string, description: string) => {
await editFile(fileId, { name, description });
const detail = await fetchFile(fileId);
setFileDetail(detail);
},
[editFile, fetchFile]
);
return (
<div className="relative z-10 h-screen flex flex-col overflow-hidden">
<Masthead showTicker={false} showNav />
<main className="flex-1 p-4 md:p-6 min-h-0 overflow-hidden">
{error && (
<div className="mb-4 p-3 border border-red-400/50 bg-red-400/10 text-red-400 font-mono text-sm">
{error}
</div>
)}
{id && fileDetail ? (
<FileDetail
file={fileDetail}
loading={detailLoading}
onBack={handleBack}
onSave={handleSave}
onDelete={handleDelete}
/>
) : id && detailLoading ? (
<div className="panel h-full flex items-center justify-center">
<div className="font-mono text-[#9bc3ff] text-sm">Loading...</div>
</div>
) : (
<FileList
files={files}
loading={loading}
onSelect={handleSelectFile}
onDelete={handleDelete}
/>
)}
</main>
</div>
);
}
|