summaryrefslogblamecommitdiff
path: root/makima/frontend/src/components/files/FileDetail.tsx
blob: 643f35e7646e223b248ce9f13b104061824f14c1 (plain) (tree)














































































































































                                                                                                                                                                      
import { useState } from "react";
import type { FileDetail as FileDetailType } from "../../lib/api";

interface FileDetailProps {
  file: FileDetailType;
  loading: boolean;
  onBack: () => void;
  onSave: (id: string, name: string, description: string) => void;
  onDelete: (id: string) => void;
}

export function FileDetail({
  file,
  loading,
  onBack,
  onSave,
  onDelete,
}: FileDetailProps) {
  const [isEditing, setIsEditing] = useState(false);
  const [name, setName] = useState(file.name);
  const [description, setDescription] = useState(file.description || "");

  const handleSave = () => {
    onSave(file.id, name, description);
    setIsEditing(false);
  };

  const handleCancel = () => {
    setName(file.name);
    setDescription(file.description || "");
    setIsEditing(false);
  };

  if (loading) {
    return (
      <div className="panel h-full flex items-center justify-center">
        <div className="font-mono text-[#9bc3ff] text-sm">Loading...</div>
      </div>
    );
  }

  return (
    <div className="panel h-full flex flex-col">
      {/* Header */}
      <div className="p-4 border-b border-dashed border-[rgba(117,170,252,0.35)]">
        <div className="flex items-center justify-between mb-3">
          <button
            onClick={onBack}
            className="font-mono text-xs text-[#75aafc] hover:text-[#9bc3ff] transition-colors"
          >
            &larr; Back to list
          </button>
          <div className="flex gap-2">
            {isEditing ? (
              <>
                <button
                  onClick={handleCancel}
                  className="px-3 py-1.5 font-mono text-xs text-[#9bc3ff] border border-[rgba(117,170,252,0.25)] hover:border-[#3f6fb3] transition-colors uppercase"
                >
                  Cancel
                </button>
                <button
                  onClick={handleSave}
                  className="px-3 py-1.5 font-mono text-xs text-[#dbe7ff] bg-[#0f3c78] border border-[#3f6fb3] hover:bg-[#153667] transition-colors uppercase"
                >
                  Save
                </button>
              </>
            ) : (
              <>
                <button
                  onClick={() => setIsEditing(true)}
                  className="px-3 py-1.5 font-mono text-xs text-[#dbe7ff] border border-[#0f3c78] hover:border-[#3f6fb3] transition-colors uppercase"
                >
                  Edit
                </button>
                <button
                  onClick={() => onDelete(file.id)}
                  className="px-3 py-1.5 font-mono text-xs text-red-400 border border-red-400/30 hover:border-red-400/50 transition-colors uppercase"
                >
                  Delete
                </button>
              </>
            )}
          </div>
        </div>

        {isEditing ? (
          <div className="space-y-3">
            <input
              type="text"
              value={name}
              onChange={(e) => setName(e.target.value)}
              className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-[#75aafc]"
              placeholder="File name"
            />
            <textarea
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              className="w-full px-3 py-2 bg-[#0d1b2d] border border-[#3f6fb3] text-[#dbe7ff] font-mono text-sm focus:outline-none focus:border-[#75aafc] resize-none"
              rows={2}
              placeholder="Description (optional)"
            />
          </div>
        ) : (
          <>
            <h2 className="font-mono text-lg text-[#dbe7ff] mb-1">
              {file.name}
            </h2>
            {file.description && (
              <p className="font-mono text-sm text-[#9bc3ff]">
                {file.description}
              </p>
            )}
          </>
        )}
      </div>

      {/* Transcript */}
      <div className="flex-1 overflow-y-auto p-4 space-y-3">
        {file.transcript.length === 0 ? (
          <div className="text-center text-[#9bc3ff] text-sm font-mono opacity-60 py-8">
            No transcript entries.
          </div>
        ) : (
          file.transcript.map((entry) => (
            <div key={entry.id} className="font-mono text-sm">
              <div className="flex items-baseline gap-2 mb-1">
                <span className="text-[#75aafc] text-xs">
                  [{entry.start.toFixed(2)}s - {entry.end.toFixed(2)}s]
                </span>
                <span className="text-[#9bc3ff] text-xs font-bold">
                  {entry.speaker}
                </span>
              </div>
              <p className="m-0 text-[#dbe7ff] leading-relaxed">{entry.text}</p>
            </div>
          ))
        )}
      </div>
    </div>
  );
}