summaryrefslogtreecommitdiff
path: root/makima/frontend/src/components/files/FileList.tsx
blob: a859aa185601ade401cad148195a3d43684fdc5d (plain) (blame)
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
96
97
98
99
100
101
102
103
104
105
106
import type { FileSummary } from "../../lib/api";

interface FileListProps {
  files: FileSummary[];
  loading: boolean;
  onSelect: (id: string) => void;
  onDelete: (id: string) => void;
  onCreate: () => void;
}

function formatDuration(seconds: number | null): string {
  if (seconds === null) return "-";
  const mins = Math.floor(seconds / 60);
  const secs = Math.floor(seconds % 60);
  return `${mins}:${secs.toString().padStart(2, "0")}`;
}

function formatDate(dateStr: string): string {
  const date = new Date(dateStr);
  return date.toLocaleDateString("en-US", {
    month: "short",
    day: "numeric",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  });
}

export function FileList({
  files,
  loading,
  onSelect,
  onDelete,
  onCreate,
}: FileListProps) {
  if (loading) {
    return (
      <div className="panel h-full flex items-center justify-center">
        <div className="font-mono text-[#9bc3ff] text-sm">Loading files...</div>
      </div>
    );
  }

  return (
    <div className="panel h-full flex flex-col">
      <div className="flex items-center justify-between p-4 pb-2 border-b border-dashed border-[rgba(117,170,252,0.35)]">
        <div className="font-mono text-xs text-[#9bc3ff] tracking-wide uppercase">
          FILES//
        </div>
        <button
          onClick={onCreate}
          className="px-3 py-1 font-mono text-xs text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] hover:bg-[rgba(117,170,252,0.05)] transition-colors uppercase"
        >
          + New
        </button>
      </div>

      <div className="flex-1 overflow-y-auto">
        {files.length === 0 ? (
          <div className="text-center text-[#9bc3ff] text-sm font-mono opacity-60 py-8">
            No saved files yet. Start recording to create one.
          </div>
        ) : (
          <div className="divide-y divide-[rgba(117,170,252,0.15)]">
            {files.map((file) => (
              <div
                key={file.id}
                className="p-4 hover:bg-[rgba(117,170,252,0.05)] transition-colors"
              >
                <div className="flex items-start justify-between gap-4">
                  <button
                    onClick={() => onSelect(file.id)}
                    className="flex-1 text-left"
                  >
                    <h3 className="font-mono text-sm text-[#dbe7ff] mb-1">
                      {file.name}
                    </h3>
                    {file.description && (
                      <p className="font-mono text-xs text-[#9bc3ff] mb-2 line-clamp-2">
                        {file.description}
                      </p>
                    )}
                    <div className="flex gap-4 font-mono text-[10px] text-[#75aafc]">
                      <span>{file.transcriptCount} segments</span>
                      <span>{formatDuration(file.duration)}</span>
                      <span>{formatDate(file.createdAt)}</span>
                    </div>
                  </button>
                  <button
                    onClick={(e) => {
                      e.stopPropagation();
                      onDelete(file.id);
                    }}
                    className="px-2 py-1 font-mono text-[10px] text-red-400 hover:bg-red-400/10 border border-red-400/30 hover:border-red-400/50 transition-colors uppercase"
                  >
                    Delete
                  </button>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}