diff --git a/client/src/components/ArtefactDetailPanel.jsx b/client/src/components/ArtefactDetailPanel.jsx index 648797e..5c65623 100644 --- a/client/src/components/ArtefactDetailPanel.jsx +++ b/client/src/components/ArtefactDetailPanel.jsx @@ -73,10 +73,10 @@ export default function ArtefactDetailPanel({ artefact, onClose, onUpdate, onDel // File upload (for design/video) const [uploading, setUploading] = useState(false) - // Video modal (for video type with Drive link) - const [showVideoModal, setShowVideoModal] = useState(false) - const [videoMode, setVideoMode] = useState('upload') // 'upload' or 'drive' + // Video inline (Drive link input) const [driveUrl, setDriveUrl] = useState('') + const [dragOver, setDragOver] = useState(false) + const [uploadProgress, setUploadProgress] = useState(0) // Comments const [comments, setComments] = useState([]) @@ -190,15 +190,20 @@ export default function ArtefactDetailPanel({ artefact, onClose, onUpdate, onDel } } - const handleFileUpload = async (e) => { - const file = e.target.files?.[0] + const handleFileUpload = async (fileOrEvent) => { + const file = fileOrEvent instanceof File ? fileOrEvent : fileOrEvent.target?.files?.[0] if (!file) return setUploading(true) + setUploadProgress(0) try { const formData = new FormData() formData.append('file', file) - await api.upload(`/artefacts/${artefact.Id}/versions/${selectedVersion.Id}/attachments`, formData) + await api.upload(`/artefacts/${artefact.Id}/versions/${selectedVersion.Id}/attachments`, formData, { + onUploadProgress: (e) => { + if (e.total) setUploadProgress(Math.round((e.loaded / e.total) * 100)) + } + }) toast.success(t('artefacts.fileUploaded')) loadVersionData(selectedVersion.Id) } catch (err) { @@ -206,6 +211,16 @@ export default function ArtefactDetailPanel({ artefact, onClose, onUpdate, onDel toast.error(t('artefacts.uploadFailed')) } finally { setUploading(false) + setUploadProgress(0) + } + } + + const handleVideoDrop = (e) => { + e.preventDefault() + setDragOver(false) + const file = e.dataTransfer.files?.[0] + if (file && file.type.startsWith('video/')) { + handleFileUpload(file) } } @@ -221,7 +236,6 @@ export default function ArtefactDetailPanel({ artefact, onClose, onUpdate, onDel drive_url: driveUrl, }) toast.success(t('artefacts.videoLinkAdded')) - setShowVideoModal(false) setDriveUrl('') loadVersionData(selectedVersion.Id) } catch (err) { @@ -608,68 +622,87 @@ export default function ArtefactDetailPanel({ artefact, onClose, onUpdate, onDel )} - {/* VIDEO TYPE: Files and Drive links */} + {/* VIDEO TYPE: Files and Drive links — all inline */} {artefact.type === 'video' && (
-
-

{t('artefacts.videosLabel')}

- -
+

{t('artefacts.videosLabel')}

- {versionData.attachments && versionData.attachments.length > 0 ? ( -
+ {/* Existing attachments */} + {versionData.attachments && versionData.attachments.length > 0 && ( +
{versionData.attachments.map(att => (
{att.drive_url ? (
{t('artefacts.googleDriveVideo')} -
-