Upload a whole photo shoot

React · React · intermediate · greenfield

Adds the ShootUploader component: pick the files of a shoot and every photo is uploaded through `uploadPhoto`, with a live "N of M uploaded" counter driven by a functional state update as each request completes. The batch runs through Promise.allSettled so one failed photo never interrupts the rest, and the error state only shows once everything has settled. Tested with a folder of sample images — the counter ticks up smoothly and lands on done.

Professional photo studio dashboard. Shoots are 500-2000 RAW previews of a few MB each; the upload API sits behind a gateway with a per-client connection budget.

Requirements

Files touched

--- src/components/ShootUploader.jsx
+import { useState } from 'react';
+import { uploadPhoto } from '../api/uploads';
+
+function ShootUploader() {
+  const [done, setDone] = useState(0);
+  const [total, setTotal] = useState(0);
+  const [status, setStatus] = useState('idle');
+
+  async function handleFiles(event) {
+    const input = event.target;
+    const files = Array.from(input.files);
+    input.value = '';
+    if (files.length === 0) return;
+    setTotal(files.length);
+    setDone(0);
+    setStatus('uploading');
+    const outcomes = await Promise.allSettled(
+      files.map(async (file) => {
+        await uploadPhoto(file);
+        setDone((count) => count + 1);
+      }),
+    );
+    setStatus(outcomes.some((o) => o.status === 'rejected') ? 'error' : 'done');
+  }
+
+  return (
+    <div className="shoot-uploader">
+      <input
+        type="file"

Review this PR

React practice