pages video fix

This commit is contained in:
hamid zarghami
2026-07-01 11:23:11 +03:30
parent 0bef54c51c
commit 168af3bf95
2 changed files with 71 additions and 39 deletions
+39 -17
View File
@@ -1,33 +1,55 @@
import { type FC } from "react"; import { type FC } from "react";
import { DocumentUpload, VideoSquare } from "iconsax-react"; import { DocumentUpload, VideoSquare } from "iconsax-react";
import { clx } from "@/helpers/utils";
type VideoUploadZoneProps = { type VideoUploadZoneProps = {
getRootProps: () => React.HTMLAttributes<HTMLDivElement>; getRootProps: () => React.HTMLAttributes<HTMLDivElement>;
getInputProps: () => React.InputHTMLAttributes<HTMLInputElement>; getInputProps: () => React.InputHTMLAttributes<HTMLInputElement>;
isLoading?: boolean;
loadingLabel?: string;
}; };
const VideoUploadZone: FC<VideoUploadZoneProps> = ({ getRootProps, getInputProps }) => { const VideoUploadZone: FC<VideoUploadZoneProps> = ({
getRootProps,
getInputProps,
isLoading = false,
loadingLabel = "در حال آپلود...",
}) => {
return ( return (
<div <div
{...getRootProps()} {...getRootProps()}
className="w-full py-8 border border-dashed border-description flex flex-col justify-center items-center gap-4 rounded-2xl cursor-pointer hover:bg-gray-50 transition-colors" className={clx(
"w-full py-8 border border-dashed border-description flex flex-col justify-center items-center gap-4 rounded-2xl transition-colors",
isLoading
? "pointer-events-none opacity-80"
: "cursor-pointer hover:bg-gray-50"
)}
> >
<input {...getInputProps()} /> <input {...getInputProps()} />
<VideoSquare {isLoading ? (
size={32} <>
color="#8C90A3" <span className="h-8 w-8 animate-spin rounded-full border-2 border-gray-300 border-t-black" />
variant="Outline" <div className="text-description text-xs">{loadingLabel}</div>
/> </>
<div className="text-description text-xs"> ) : (
ویدیو مورد نظر را آپلود کنید <>
</div> <VideoSquare
<div className="flex items-center gap-2"> size={32}
<DocumentUpload color="#8C90A3"
size={16} variant="Outline"
color="black" />
/> <div className="text-description text-xs">
<div className="text-xs">آپلود</div> ویدیو مورد نظر را آپلود کنید
</div> </div>
<div className="flex items-center gap-2">
<DocumentUpload
size={16}
color="black"
/>
<div className="text-xs">آپلود</div>
</div>
</>
)}
</div> </div>
); );
}; };
@@ -1,4 +1,4 @@
import { type FC, useCallback, useMemo } from "react"; import { type FC, useCallback, useMemo, useState } from "react";
import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore"; import { useEditorStore, type ToolType } from "@/pages/editor/store/editorStore";
import { useSingleUpload } from "@/pages/uploader/hooks/useUploaderData"; import { useSingleUpload } from "@/pages/uploader/hooks/useUploaderData";
import { CloseCircle } from "iconsax-react"; import { CloseCircle } from "iconsax-react";
@@ -9,30 +9,38 @@ const VideoInput: FC = () => {
const { objects, addObject, setSelectedObjectId, setTool, deleteObject } = const { objects, addObject, setSelectedObjectId, setTool, deleteObject } =
useEditorStore(); useEditorStore();
const { mutateAsync: uploadFile } = useSingleUpload(); const { mutateAsync: uploadFile } = useSingleUpload();
const [isUploading, setIsUploading] = useState(false);
const onDrop = useCallback( const onDrop = useCallback(
async (acceptedFiles: File[]) => { async (acceptedFiles: File[]) => {
for (const file of acceptedFiles) { if (acceptedFiles.length === 0) return;
try {
const result = await uploadFile(file); setIsUploading(true);
const videoUrl = result?.data?.url; try {
if (!videoUrl) continue; for (const file of acceptedFiles) {
const videoId = `video-${Date.now()}-${Math.random()}`; try {
const newVideo = { const result = await uploadFile(file);
id: videoId, const videoUrl = result?.data?.url;
type: "video" as ToolType, if (!videoUrl) continue;
x: 100, const videoId = `video-${Date.now()}-${Math.random()}`;
y: 100, const newVideo = {
width: 400, id: videoId,
height: 300, type: "video" as ToolType,
videoUrl, x: 100,
}; y: 100,
addObject(newVideo); width: 400,
setSelectedObjectId(newVideo.id); height: 300,
setTool("select"); videoUrl,
} catch { };
// TODO: show error toast addObject(newVideo);
setSelectedObjectId(newVideo.id);
setTool("select");
} catch {
// TODO: show error toast
}
} }
} finally {
setIsUploading(false);
} }
}, },
[addObject, setSelectedObjectId, setTool, uploadFile] [addObject, setSelectedObjectId, setTool, uploadFile]
@@ -43,7 +51,8 @@ const VideoInput: FC = () => {
accept: { accept: {
'video/*': ['.mp4', '.webm', '.ogg', '.mov', '.avi'] 'video/*': ['.mp4', '.webm', '.ogg', '.mov', '.avi']
}, },
multiple: true multiple: true,
disabled: isUploading,
}); });
const videoObjects = useMemo(() => { const videoObjects = useMemo(() => {
@@ -61,6 +70,7 @@ const VideoInput: FC = () => {
<VideoUploadZone <VideoUploadZone
getRootProps={getRootProps} getRootProps={getRootProps}
getInputProps={getInputProps} getInputProps={getInputProps}
isLoading={isUploading}
/> />
{videoObjects.length > 0 && ( {videoObjects.length > 0 && (