add navagation handler while file upload

This commit is contained in:
smanylov
2025-12-25 13:19:32 +07:00
parent 87b8d68f41
commit e0420fa6d3
6 changed files with 136 additions and 35 deletions
+45 -32
View File
@@ -1,10 +1,10 @@
'use client'
import React, { useRef, useState, useCallback, ChangeEvent, DragEvent } from 'react';
import { useRef, useState, useCallback, ChangeEvent, DragEvent, useEffect } from 'react';
import { IconShieldAdd } from '@/app/ui/icons/icons';
import { fileUpload, cancelUpload, chunkUpload, checkChunkStatus } from '@/app/actions/file-upload';
import { useTranslations } from 'next-intl';
import { useNavigationBlocker } from '@/app/hooks/useNavigationBlocker';
interface SelectedFile {
file: File;
preview: string;
@@ -94,7 +94,6 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
const ALLOWED_EXTENSIONS: string[] = allowedExtensions;
const validateFile = (file: File): { isValid: boolean; errorMessage?: string } => {
if (!SUPPORTED_FORMATS.includes(file.type as string)) {
const extension = file.name.split('.').pop()?.toLowerCase();
@@ -308,6 +307,42 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
}
}
useEffect(() => {
// Обработка закрытия вкладки
// Тут можно попробовать изучить вопрос с navigator.sendBeacon('', blob)
// он нужен для того что бы послать запрос на бек при закрытии вкладки,
// но у него есть свои особенности и стандартные запросы не работают.
const handleUnload = () => {
if (uploadId) {
//const data = JSON.stringify({ uploadId, reason: 'tab_closed' });
//const blob = new Blob([data], { type: 'application/json' });
//navigator.sendBeacon('/api/v1/data/cancel', blob);
console.log('sendBeacon');
}
};
if (uploadId) {
window.addEventListener('unload', handleUnload);
}
return () => {
window.removeEventListener('unload', handleUnload);
};
}, [uploadId]);
useNavigationBlocker({
shouldBlock: !!uploadId,
message: t('have-unsaved-changes'),
onConfirm: async () => {
console.log('User confirmed navigation');
if (uploadId) {
await cancelUpload(uploadId);
}
},
onCancel: () => {
console.log('User cancelled navigation');
}
});
return (
<div className="upload-section">
<h3>
@@ -354,14 +389,16 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
{t('select-files-to-protect')}
</button>
{fileType === "IMAGE" && (
<p className="description">
Разрешение изображение: 100x100 - 10000x10000
</p>
)}
<p className="description">
Разрешение изображение: 100x100 - 10000x10000
Размер файла: до {(maxFileSize / 1024 / 1024)} МБ
</p>
<p className="description">
Размер файла: до 20 МБ
</p>
<p className="description">
Формат файла: JPG, PNG, GIF, BMP (WEBP НЕ поддерживается)
Формат файла: {ALLOWED_EXTENSIONS.join(', ')}
</p>
{error && (
@@ -411,17 +448,6 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
/>
)}
{fileType === 'VIDEO' && (
<video
src={selectedFile.preview}
className="uploaded-image"
controls
muted
onError={() => setError('Не удалось загрузить превью видео')}
onLoadedData={() => console.log('Видео загружено')}
/>
)}
<div className="mt-4 flex gap-3 justify-center relative">
<button
className="btn btn-cancel"
@@ -440,19 +466,6 @@ export default function UploadSectionFile({ fileType, allowedExtensions, maxFile
>
{t('upload-file')}
</button>
<button
className="btn btn-cancel"
type="button"
onClick={
async () => {
if (uploadId) {
await checkChunkStatus(uploadId);
}
}
}
>
dev-test-button
</button>
{uploadProgress !== 0 && (
<div
className={`absolute top-5 right-5 font-medium ${isFileUploaded ? "text-green-600" : ""}`}