瀏覽代碼

feat(files): enhance file upload and management functionality with new file addition handling WIP

vtugulan 6 月之前
父節點
當前提交
2b639607f2
共有 3 個文件被更改,包括 110 次插入28 次删除
  1. 33 4
      app/components/filesTable.tsx
  2. 58 22
      app/components/uploadForm.tsx
  3. 19 2
      app/files/page.tsx

+ 33 - 4
app/components/filesTable.tsx

@@ -1,6 +1,6 @@
 "use client";
 
-import { useState } from "react";
+import React, { useState, useEffect } from "react";
 import {
   ColumnDef,
   flexRender,
@@ -22,9 +22,14 @@ interface FileData {
   updatedAt: string;
 }
 
-export function FilesTable() {
+interface FilesTableProps {
+  onFileAdded?: (file: FileData) => void;
+}
+
+export function FilesTable({ onFileAdded }: FilesTableProps) {
   const [sorting, setSorting] = useState<SortingState>([]);
   const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
+  const [files, setFiles] = useState<FileData[]>([]);
 
   const { data, isLoading, isError, error, refetch } = useQuery({
     queryKey: ["files"],
@@ -38,6 +43,30 @@ export function FilesTable() {
     },
   });
 
+  // Update local files state when data changes
+  useEffect(() => {
+    if (data) {
+      setFiles(data);
+    }
+  }, [data]);
+
+  // Method to add a new file to the table
+  const addFile = (file: FileData) => {
+    setFiles(prevFiles => [file, ...prevFiles]);
+    // Call the onFileAdded prop if provided
+    if (onFileAdded) {
+      onFileAdded(file);
+    }
+  };
+
+  // Make addFile available globally for the upload form
+  useEffect(() => {
+    (window as any).addFileToTable = addFile;
+    return () => {
+      delete (window as any).addFileToTable;
+    };
+  }, [onFileAdded]);
+
   const columns: ColumnDef<FileData>[] = [
     {
       id: "select",
@@ -170,7 +199,7 @@ export function FilesTable() {
   ];
 
   const table = useReactTable({
-    data: data || [],
+    data: files,
     columns,
     state: {
       sorting,
@@ -439,7 +468,7 @@ export function FilesTable() {
         {/* Pagination */}
         <div className="flex items-center justify-between mt-4">
           <div className="text-sm text-gray-700">
-            Showing {table.getRowModel().rows.length} of {data.length} results
+            Showing {table.getRowModel().rows.length} of {files.length} results
           </div>
           <div className="flex gap-2">
             <button

+ 58 - 22
app/components/uploadForm.tsx

@@ -1,30 +1,66 @@
 "use client";
 
-export const UploadForm = () => {
-  return (
-    <input
-      type="file"
-      name="file"
-      onChange={async (e) => {
-        if (e.target.files) {
-          const formData = new FormData();
-          Object.values(e.target.files).forEach((file) => {
-            formData.append("file", file);
-          });
+import { useState } from "react";
+
+interface FileData {
+  id: string;
+  filename: string;
+  mimetype: string;
+  size: number;
+  createdAt: string;
+  updatedAt: string;
+}
+
+export const UploadForm = ({ onFileUploaded }: { onFileUploaded?: (file: FileData) => void }) => {
+  const [isUploading, setIsUploading] = useState(false);
 
-          const response = await fetch("/api/upload", {
-            method: "POST",
-            body: formData,
-          });
+  const handleFileUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
+    if (e.target.files && e.target.files[0]) {
+      setIsUploading(true);
+      const file = e.target.files[0];
+      const formData = new FormData();
+      formData.append("file", file);
 
-          const result = await response.json();
-          if (result.success) {
-            alert(`Upload successful: ${result.file.filename} (${result.file.size} bytes)`);
-          } else {
-            alert(`Upload failed: ${result.error || 'Unknown error'}`);
+      try {
+        const response = await fetch("/api/upload", {
+          method: "POST",
+          body: formData,
+        });
+
+        const result = await response.json();
+        
+        if (result.success) {
+          // Call the callback to add the new file to the table
+          if (onFileUploaded) {
+            onFileUploaded(result.file);
           }
+          
+          // Reset the file input
+          e.target.value = '';
+        } else {
+          alert(`Upload failed: ${result.error || 'Unknown error'}`);
         }
-      }}
-    />
+      } catch (error) {
+        console.error("Upload error:", error);
+        alert("Failed to upload file");
+      } finally {
+        setIsUploading(false);
+      }
+    }
+  };
+
+  return (
+    <div>
+      <input
+        type="file"
+        name="file"
+        onChange={handleFileUpload}
+        disabled={isUploading}
+        className="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
+      />
+      {isUploading && (
+        <div className="mt-2 text-sm text-gray-600">Uploading...</div>
+      )}
+    </div>
   );
 };

+ 19 - 2
app/files/page.tsx

@@ -4,8 +4,25 @@ import Image from "next/image";
 import Link from "next/link";
 import { UploadForm } from "../components/uploadForm";
 import { FilesTable } from "../components/filesTable";
+import { useState } from "react";
+
+interface FileData {
+  id: string;
+  filename: string;
+  mimetype: string;
+  size: number;
+  createdAt: string;
+  updatedAt: string;
+}
 
 export default function FilesPage() {
+  const [newFile, setNewFile] = useState<FileData | null>(null);
+
+  const handleFileUploaded = (file: FileData) => {
+    // This will trigger the FilesTable to add the new file
+    setNewFile(file);
+  };
+
   return (
     <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
       <main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
@@ -28,12 +45,12 @@ export default function FilesPage() {
 
         <div className="flex flex-col gap-4 items-center sm:items-start">
           <h2 className="text-xl font-semibold">Upload Files</h2>
-          <UploadForm />
+          <UploadForm onFileUploaded={handleFileUploaded} />
         </div>
 
         <div className="w-full max-w-6xl">
           <h2 className="text-2xl font-semibold mb-4">Files in Database</h2>
-          <FilesTable />
+          <FilesTable onFileAdded={handleFileUploaded} />
         </div>
         
         <div className="flex gap-4 items-center flex-col sm:flex-row">