Skip to content

Commit 607a631

Browse files
authored
Merge pull request #22 from yashica-kuki/frontend-upload-page
feat(fix): add upload modal by react-dropzone
2 parents 6b369f2 + 4f73ef3 commit 607a631

File tree

9 files changed

+612
-42
lines changed

9 files changed

+612
-42
lines changed

frontend/.env.sample

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VITE_CLOUDINARY_PUBLIC_ID=<product_environment_name>

frontend/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<script src="https://upload-widget.cloudinary.com/latest/global/all.js" type="text/javascript"></script>
78
<title>Vite + React</title>
89
</head>
910
<body>

frontend/package-lock.json

Lines changed: 113 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

frontend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13-
"nprogress": "^0.2.0",
1413
"react": "^19.1.0",
1514
"react-dom": "^19.1.0",
15+
"react-router-dom": "^7.6.0",
16+
"react-dropzone": "^14.3.8",
17+
"cloudinary": "^2.6.1"
1618
"react-icons": "^5.5.0",
1719
"react-router-dom": "^7.6.0"
1820
},
Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,33 @@
11
import { useEffect, useState } from 'react';
2+
import UploadModal from './Upload';
23

34
export default function LabList({ subjectId }) {
45
const [labs, setLabs] = useState([]);
56
const [title, setTitle] = useState('');
6-
const [file, setFile] = useState(null);
7+
const [modalOpen, setmodalOpen] = useState(false);
78

89
const load = ()=>fetch(`http://localhost:4000/subjects/${subjectId}/labs`)
910
.then(r=>r.json())
1011
.then(res => setLabs(res.data));
1112

1213
useEffect(load, [subjectId]);
1314

14-
const add = async e => {
15-
e.preventDefault();
16-
const fd = new FormData();
17-
fd.append('title', title);
18-
fd.append('file', file);
15+
const add = async (uploadTitle, cloudinaryUrl) => {
16+
const payload = {
17+
title: uploadTitle,
18+
url: cloudinaryUrl
19+
};
20+
1921
await fetch(`http://localhost:4000/subjects/${subjectId}/labs`, {
20-
method:'POST',
21-
headers: { 'x-user-id': 1, 'x-user-role': 'USER' },
22-
body: fd
22+
method: 'POST',
23+
headers: {
24+
'x-user-id': 1,
25+
'x-user-role': 'USER',
26+
'Content-Type': 'application/json'
27+
},
28+
body: JSON.stringify(payload)
2329
});
24-
setTitle(''); setFile(null);
30+
setTitle('');
2531
load();
2632
};
2733

@@ -30,23 +36,42 @@ export default function LabList({ subjectId }) {
3036
load();
3137
};
3238

39+
const handleUploadComplete = async ({ url, public_id }) => {
40+
await add(public_id, url);
41+
setTitle("")
42+
setmodalOpen(false)
43+
}
44+
45+
const handleButtonClick = () => {
46+
if (title.trim() === "") {
47+
alert("Please enter a title before uploading.")
48+
return
49+
}
50+
setmodalOpen(true)
51+
}
52+
3353
return (
3454
<div>
3555
<h2>Lab Materials</h2>
3656
<form onSubmit={add}>
3757
<input value={title} onChange={e=>setTitle(e.target.value)} placeholder="Title" required/>
38-
<input type="file" onChange={e=>setFile(e.target.files[0])} required/>
39-
<button type="submit">Upload Lab</button>
58+
<button type="button" onClick={handleButtonClick} disabled={title.trim()===""}>Upload Lab</button>
59+
<UploadModal
60+
open={modalOpen}
61+
onClose={() => setmodalOpen(false)}
62+
onComplete={handleUploadComplete}
63+
title={title}
64+
/>
4065
</form>
4166
<ul>
4267
{labs.map(l=>(
4368
<li key={l.id}>
44-
<a href={`http://localhost:4000${l.url}`} target="_blank">{l.title}</a>
69+
<a href={l.url} target="_blank" rel="noopener noreferrer">{l.title}</a>
4570
<span> by {l.user.name}</span>
4671
<button onClick={()=>del(l.id)}>Delete</button>
4772
</li>
4873
))}
4974
</ul>
5075
</div>
5176
);
52-
}
77+
}

0 commit comments

Comments
 (0)