Skip to content

Commit 89270c5

Browse files
done
1 parent ff53aa0 commit 89270c5

1 file changed

Lines changed: 68 additions & 87 deletions

File tree

src/app/upload/page.tsx

Lines changed: 68 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"use client";
22

33
import { useCallback, useEffect, useState } from "react";
4-
import { useDropzone } from "react-dropzone";
54
import toast from "react-hot-toast";
65
import { Button } from "@/components/ui/button";
76
import axios, { AxiosError } from "axios";
@@ -37,7 +36,7 @@ export default function Page() {
3736
{ id: string; file: File; preview: string }[]
3837
>([]);
3938
const [isUploading, setIsUploading] = useState(false);
40-
const [isDragging, setIsDragging] = useState(false);
39+
const [setIsDragging] = useState(false);
4140
const [isGlobalDragging, setIsGlobalDragging] = useState(false);
4241
const [zoomIndex, setZoomIndex] = useState<number | null>(null);
4342

@@ -57,18 +56,18 @@ export default function Page() {
5756
};
5857
}, []);
5958

60-
59+
// Cleanup URLs when component unmounts
6160
useEffect(() => {
6261
return () => {
6362
previews.forEach((item) => {
6463
try {
6564
URL.revokeObjectURL(item.preview);
6665
} catch (e) {
67-
66+
// Ignore errors
6867
}
6968
});
7069
};
71-
}, [previews]);
70+
}, []); // Only run on unmount
7271

7372
const fileCheckAndSelect = useCallback(
7473
(acceptedFiles: File[]) => {
@@ -90,11 +89,23 @@ export default function Page() {
9089
(file) => file.type === "application/pdf",
9190
);
9291

92+
const hasExistingImages = files.some((file) =>
93+
file.type.startsWith("image/"),
94+
);
95+
96+
const hasExistingPdf = files.some(
97+
(file) => file.type === "application/pdf",
98+
);
99+
93100
if (
94101
(isNewPdf && acceptedFiles.length > 1) ||
95-
(isNewPdf && files.length > 0)
102+
(isNewPdf && hasExistingImages) ||
103+
(isNewPdf && hasExistingPdf) ||
104+
(!isNewPdf && hasExistingPdf)
96105
) {
97-
toast.error("PDFs must be uploaded separately", { id: toastId });
106+
toast.error("PDFs must be uploaded separately from images", {
107+
id: toastId,
108+
});
98109
return;
99110
}
100111

@@ -117,9 +128,8 @@ export default function Page() {
117128
return;
118129
}
119130

120-
121131
const newPreviews = acceptedFiles.map((file, idx) => ({
122-
id: `${file.name}-${file.lastModified}-${Date.now()}-${files.length + idx}-add`,
132+
id: `${file.name}-${file.lastModified}-${Date.now()}-${files.length + idx}`,
123133
file,
124134
preview: URL.createObjectURL(file),
125135
}));
@@ -131,25 +141,13 @@ export default function Page() {
131141
},
132142
[files],
133143
);
134-
135144
const onDrop = useCallback(
136145
(acceptedFiles: File[]) => {
137146
fileCheckAndSelect(acceptedFiles);
138147
},
139148
[fileCheckAndSelect],
140149
);
141150

142-
const { getRootProps, getInputProps } = useDropzone({
143-
onDrop,
144-
multiple: true,
145-
noClick: false,
146-
noKeyboard: false,
147-
accept: {
148-
"application/pdf": [".pdf"],
149-
"image/*": [".jpeg", ".jpg", ".png", ".gif"],
150-
},
151-
});
152-
153151
const sensors = useSensors(
154152
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
155153
);
@@ -169,18 +167,18 @@ export default function Page() {
169167
transition,
170168
isDragging,
171169
} = useSortable({ id });
172-
170+
173171
const style = {
174172
transform: CSS.Transform.toString(transform),
175173
transition,
176174
zIndex: isDragging ? 1000 : 1,
177175
};
178-
176+
179177
return (
180-
<div
181-
ref={setNodeRef}
182-
style={style}
183-
{...attributes}
178+
<div
179+
ref={setNodeRef}
180+
style={style}
181+
{...attributes}
184182
{...listeners}
185183
className={isDragging ? "cursor-grabbing" : "cursor-grab"}
186184
>
@@ -195,20 +193,8 @@ export default function Page() {
195193
const oldIndex = previews.findIndex((item) => item.id === active.id);
196194
const newIndex = previews.findIndex((item) => item.id === over.id);
197195

198-
const newFiles = arrayMove(
199-
previews.map((p) => p.file),
200-
oldIndex,
201-
newIndex,
202-
);
203-
204-
previews.forEach((item) => URL.revokeObjectURL(item.preview));
205-
206-
207-
const newPreviews = newFiles.map((file, idx) => ({
208-
id: `${file.name}-${file.lastModified}-${Date.now()}-${idx}-reorder`,
209-
file,
210-
preview: URL.createObjectURL(file),
211-
}));
196+
const newPreviews = arrayMove(previews, oldIndex, newIndex);
197+
const newFiles = arrayMove(files, oldIndex, newIndex);
212198

213199
setFiles(newFiles);
214200
setPreviews(newPreviews);
@@ -220,28 +206,26 @@ export default function Page() {
220206
if (deletedPreview) {
221207
URL.revokeObjectURL(deletedPreview.preview);
222208
}
223-
224-
209+
225210
const remainingFiles = files.filter((_, i) => i !== index);
226-
227-
228-
previews.forEach((item, i) => {
229-
if (i !== index) {
230-
URL.revokeObjectURL(item.preview);
231-
}
232-
});
233-
234-
235-
const newPreviews = remainingFiles.map((file, idx) => ({
236-
id: `${file.name}-${file.lastModified}-${Date.now()}-${idx}-delete`,
237-
file,
238-
preview: URL.createObjectURL(file),
239-
}));
240-
211+
const remainingPreviews = previews.filter((_, i) => i !== index);
212+
241213
setFiles(remainingFiles);
242-
setPreviews(newPreviews);
214+
setPreviews(remainingPreviews);
243215
};
244216

217+
const clearAllFiles = useCallback(() => {
218+
// Clean up all URLs
219+
previews.forEach((item) => {
220+
try {
221+
URL.revokeObjectURL(item.preview);
222+
} catch (e) {}
223+
});
224+
225+
setFiles([]);
226+
setPreviews([]);
227+
}, [previews]);
228+
245229
const handlePrint = async () => {
246230
const isPdf = files.length === 1 && files[0]?.type === "application/pdf";
247231

@@ -280,26 +264,17 @@ export default function Page() {
280264
},
281265
);
282266

283-
setFiles([]);
284-
setPreviews([]);
285-
286-
287-
previews.forEach((item) => {
288-
try {
289-
URL.revokeObjectURL(item.preview);
290-
} catch (e) {
291-
292-
}
293-
});
267+
clearAllFiles();
294268
} catch (error) {
269+
295270
} finally {
296271
setIsUploading(false);
297272
}
298273
};
299274

300275
return (
301276
<main className="mx-auto max-w-3xl px-4 py-8">
302-
<div className="flex h-[calc(100vh-85px)] flex-col justify-center px-6 font-play">
277+
<div className="flex h-[calc(100vh-90px)] flex-col justify-center px-6 font-play">
303278
<div className="2xl:my-15 flex flex-col items-center">
304279
{previews.length === 0 && (
305280
<fieldset className="mb-4 w-full max-w-md rounded-lg border-2 border-gray-300 p-4 pr-8">
@@ -328,8 +303,6 @@ export default function Page() {
328303
? "border-solid border-[#6D28D9] bg-purple-50 dark:bg-[#130E1F]"
329304
: "border-dashed border-gray-300"
330305
} p-8 text-center transition-all duration-200`}
331-
onDragEnter={() => setIsDragging(true)}
332-
onDragLeave={() => setIsDragging(false)}
333306
>
334307
<input {...getInputProps()} />
335308
{isDragActive || isGlobalDragging ? (
@@ -340,11 +313,11 @@ export default function Page() {
340313
<Upload className="mt-2 h-10 w-10 animate-bounce text-[#6D28D9]" />
341314
</div>
342315
) : (
343-
<p>
316+
<div>
344317
Drag &apos;n&apos; drop some files here, or{" "}
345318
<span className="text-[#6D28D9]">click</span> to
346319
select files
347-
</p>
320+
</div>
348321
)}
349322
<div
350323
className={`mt-2 text-xs ${
@@ -355,6 +328,12 @@ export default function Page() {
355328
>
356329
{files.length} files selected
357330
</div>
331+
<div className="mt-4 text-sm text-gray-500">
332+
Note: Uploaded papers are first reviewed by our team
333+
before appearing on the website. If your paper doesn&apos;t
334+
show up immediately, please be patient, it&apos;s likely
335+
still under review.
336+
</div>
358337
</section>
359338
)}
360339
</Dropzone>
@@ -372,7 +351,7 @@ export default function Page() {
372351
<div className="flex w-max gap-4">
373352
<div
374353
className="scrollbar-hide flex aspect-[2/1] w-full max-w-4xl flex-col justify-between overflow-x-auto overflow-y-hidden rounded-[40px] border-[6px] border-indigo-900 bg-indigo-900/10 p-8"
375-
style={{ minHeight: 320 }}
354+
style={{ minHeight: 340, maxHeight: 340 }}
376355
>
377356
<DndContext
378357
sensors={sensors}
@@ -387,16 +366,13 @@ export default function Page() {
387366
{previews.map((item, index) => (
388367
<SortablePreview key={item.id} id={item.id}>
389368
<div className="group relative flex-shrink-0">
390-
391369
<div className="relative h-60 w-48 overflow-hidden rounded-2xl outline outline-2 outline-white">
392-
393370
<div className="absolute left-0 top-0 z-20 flex h-10 w-10 items-center justify-center rounded-br-2xl rounded-tl-2xl bg-slate-600">
394371
<span className="text-xl font-bold text-white">
395372
{index + 1}
396373
</span>
397374
</div>
398375

399-
400376
<Button
401377
onClick={(e) => {
402378
e.preventDefault();
@@ -411,7 +387,6 @@ export default function Page() {
411387
<FiTrash className="h-5 w-5" />
412388
</Button>
413389

414-
{/* File preview content */}
415390
<div className="absolute inset-0 z-10">
416391
{item.file.type.startsWith("image/") ? (
417392
<Image
@@ -435,7 +410,6 @@ export default function Page() {
435410
</SortablePreview>
436411
))}
437412

438-
{/* Add more button */}
439413
<Dropzone
440414
onDrop={onDrop}
441415
accept={{
@@ -453,7 +427,7 @@ export default function Page() {
453427
>
454428
{({ getRootProps, getInputProps }) => (
455429
<div
456-
className="relative h-20 w-20 cursor-pointer flex-shrink-0"
430+
className="relative h-20 w-20 flex-shrink-0 cursor-pointer"
457431
{...getRootProps()}
458432
>
459433
<input {...getInputProps()} />
@@ -469,14 +443,21 @@ export default function Page() {
469443
</div>
470444
)}
471445
</Dropzone>
472-
</div>
446+
</div>{" "}
447+
{previews.length > 2 && (
448+
<div className="text-l mt-4 text-right text-white/50">
449+
scroll to view more &gt;&gt;
450+
</div>
451+
)}
473452
</SortableContext>
474453
</DndContext>
475-
<p className="mt-4 text-center text-xl text-white/50">
476-
Drag to re-order.
477-
</p>
478454
</div>
479455
</div>
456+
{previews.length > 1 && (
457+
<div className="mt-4 text-right text-xl text-white/50">
458+
Drag to reorder
459+
</div>
460+
)}
480461
</section>
481462
)}
482463

@@ -529,4 +510,4 @@ export default function Page() {
529510
)}
530511
</main>
531512
);
532-
}
513+
}

0 commit comments

Comments
 (0)