feat: add FileDescriptionContainer for managing file descriptions and integrate with FileActions
This commit is contained in:
parent
344334592e
commit
1d302eb217
@ -1,5 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import {useFileActions} from "~/app/_components/FileActions";
|
import { useRef, useState } from "react";
|
||||||
|
import { useFileActions } from "~/app/_components/FileActions";
|
||||||
|
|
||||||
export function FileActionsContainer({
|
export function FileActionsContainer({
|
||||||
fileId,
|
fileId,
|
||||||
@ -12,7 +13,7 @@ export function FileActionsContainer({
|
|||||||
fileUrl: string;
|
fileUrl: string;
|
||||||
isOwner: boolean;
|
isOwner: boolean;
|
||||||
}) {
|
}) {
|
||||||
const { handleDownload, handleCopyUrl, handleRemove } = useFileActions(() => fileId, (description: string) => {
|
const { handleDownload, handleCopyUrl, handleRemove} = useFileActions(() => fileId, (description: string) => {
|
||||||
if (isOwner) {
|
if (isOwner) {
|
||||||
console.log(description);
|
console.log(description);
|
||||||
}
|
}
|
||||||
@ -84,4 +85,36 @@ export function FileActionsContainer({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function FileDescriptionContainer({
|
||||||
|
fileId,
|
||||||
|
fileDescriprtion,
|
||||||
|
}: {
|
||||||
|
fileId: string;
|
||||||
|
fileDescriprtion?: string;
|
||||||
|
}) {
|
||||||
|
|
||||||
|
const [description, setDescription] = useState(fileDescriprtion || ""); // Add state for description
|
||||||
|
const { handleDescriptionChange } = useFileActions(() => {}, (description: string) => {
|
||||||
|
setDescription(description);
|
||||||
|
return undefined;
|
||||||
|
}, fileId); // Wrap setDescription in a function
|
||||||
|
const debounceTimer = useRef<NodeJS.Timeout | null>(null); // Initialize debounce timer
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
|
handleDescriptionChange(e, debounceTimer); // Pass the debounce timer
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex self-center gap-2">
|
||||||
|
<textarea
|
||||||
|
className="w-full h-24 p-2 border rounded-md bg-gray-800 text-white"
|
||||||
|
value={description} // Use state value
|
||||||
|
onChange={handleChange}
|
||||||
|
placeholder="Enter file description..."
|
||||||
|
maxLength={200} // Limit to 200 characters
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
@ -4,7 +4,7 @@ import { notifyClients } from "~/utils/notifyClients";
|
|||||||
|
|
||||||
export const useFileActions = (
|
export const useFileActions = (
|
||||||
setFiles: (callback: (prevFiles: any[]) => any[]) => void,
|
setFiles: (callback: (prevFiles: any[]) => any[]) => void,
|
||||||
setDescription?: (description: string) => void,
|
setDescription?: (description: string) => undefined,
|
||||||
fileId?: string
|
fileId?: string
|
||||||
) => {
|
) => {
|
||||||
const pageUrl = `${env.NEXT_PUBLIC_PAGE_URL}`;
|
const pageUrl = `${env.NEXT_PUBLIC_PAGE_URL}`;
|
||||||
@ -75,7 +75,9 @@ export const useFileActions = (
|
|||||||
e: React.ChangeEvent<HTMLTextAreaElement>,
|
e: React.ChangeEvent<HTMLTextAreaElement>,
|
||||||
debounceTimer: React.RefObject<NodeJS.Timeout | null>
|
debounceTimer: React.RefObject<NodeJS.Timeout | null>
|
||||||
) => {
|
) => {
|
||||||
if (!setDescription) return;
|
if (setDescription === undefined) {console.error("setDescription function is not provided")
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
const newDescription = e.target.value;
|
const newDescription = e.target.value;
|
||||||
setDescription(newDescription);
|
setDescription(newDescription);
|
||||||
@ -83,7 +85,9 @@ export const useFileActions = (
|
|||||||
if (debounceTimer.current) {
|
if (debounceTimer.current) {
|
||||||
clearTimeout(debounceTimer.current);
|
clearTimeout(debounceTimer.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
debounceTimer.current = setTimeout(() => {
|
debounceTimer.current = setTimeout(() => {
|
||||||
|
console.log("Calling handleDescriptionSave"); // Debug log
|
||||||
handleDescriptionSave(newDescription);
|
handleDescriptionSave(newDescription);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
};
|
};
|
||||||
@ -99,7 +103,8 @@ export const useFileActions = (
|
|||||||
const response = await fetch(`/api/files/share?id=${encodeURIComponent(fileId)}`, {
|
const response = await fetch(`/api/files/share?id=${encodeURIComponent(fileId)}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ description }),
|
// pass the fileId and description in the request body
|
||||||
|
body: JSON.stringify({ description, id: fileId }),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.status === 403) {
|
if (response.status === 403) {
|
||||||
|
|||||||
@ -48,7 +48,8 @@ export async function PUT(req: Request) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const body = (await req.json()) as { id: string; description: string } | null;
|
const body = (await req.json()) as { id: string; description: string } | null;
|
||||||
if (!body?.id || !body.description) {
|
if (!body?.id || body.description === undefined) {
|
||||||
|
// Allow empty description but ensure id is present
|
||||||
return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
|
return NextResponse.json({ error: "Invalid request body" }, { status: 400 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import { notFound } from "next/navigation";
|
|||||||
import { FilePreview } from "~/app/_components/FilePreview";
|
import { FilePreview } from "~/app/_components/FilePreview";
|
||||||
import { HomeButton } from "~/app/_components/HomeButton"; // Import the client component
|
import { HomeButton } from "~/app/_components/HomeButton"; // Import the client component
|
||||||
import { Toaster } from "react-hot-toast";
|
import { Toaster } from "react-hot-toast";
|
||||||
import { FileActionsContainer } from "~/app/_components/ActionButtons"; // Import the client component
|
import { FileActionsContainer, FileDescriptionContainer } from "~/app/_components/ActionButtons"; // Import the client component
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
|
|
||||||
interface FileDetails {
|
interface FileDetails {
|
||||||
@ -143,10 +143,10 @@ export default async function FilePreviewContainer({
|
|||||||
<strong>Upload Date:</strong>{" "}
|
<strong>Upload Date:</strong>{" "}
|
||||||
{new Date(fileDetails.uploadDate).toLocaleString()}
|
{new Date(fileDetails.uploadDate).toLocaleString()}
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<div>
|
||||||
<strong>Description:</strong>{" "}
|
<strong>Description:</strong>{" "}
|
||||||
{fileDetails.description || "No description available"}
|
<FileDescriptionContainer fileId={fileDetails.id} fileDescriprtion={fileDetails.description}/>
|
||||||
</p>
|
</div>
|
||||||
<div className="mt-4 flex justify-center">
|
<div className="mt-4 flex justify-center">
|
||||||
<FileActionsContainer
|
<FileActionsContainer
|
||||||
fileId={fileDetails.id}
|
fileId={fileDetails.id}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user