diff --git a/dashboard/src/assets/hero.png b/dashboard/src/assets/hero.png
deleted file mode 100644
index 02251f4..0000000
Binary files a/dashboard/src/assets/hero.png and /dev/null differ
diff --git a/dashboard/src/assets/react.svg b/dashboard/src/assets/react.svg
deleted file mode 100644
index 6c87de9..0000000
--- a/dashboard/src/assets/react.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/dashboard/src/assets/vite.svg b/dashboard/src/assets/vite.svg
deleted file mode 100644
index 5101b67..0000000
--- a/dashboard/src/assets/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/dashboard/src/components/ConfigModal.jsx b/dashboard/src/components/ConfigModal.jsx
index 8db284c..66dbd89 100644
--- a/dashboard/src/components/ConfigModal.jsx
+++ b/dashboard/src/components/ConfigModal.jsx
@@ -22,11 +22,11 @@ function useScanPoller(onDone) {
const data = await apiFetch('/scan-status')
if (!data?.scanning) {
stop()
- onDoneRef.current()
+ onDoneRef.current(data)
}
} catch {
stop()
- onDoneRef.current()
+ onDoneRef.current(null)
}
}, 2000)
}, [stop])
@@ -61,7 +61,6 @@ export default function ConfigModal({ onClose, currentUserId = null }) {
const [activeTab, setActiveTab] = useState('general')
const [form, setForm] = useState({})
const [saveError, setSaveError] = useState(null)
- const [isRescanning, setIsRescanning] = useState(false)
const [isScanning, setIsScanning] = useState(false)
const [isSavingTimes, setIsSavingTimes] = useState(false)
const [users, setUsers] = useState([])
@@ -74,11 +73,13 @@ export default function ConfigModal({ onClose, currentUserId = null }) {
const [createForm, setCreateForm] = useState({ username: '', password: '', role: 'viewer' })
const [passwordForm, setPasswordForm] = useState({ userId: '', password: '' })
- const scanPoller = useScanPoller(() => {
+ const scanPoller = useScanPoller((data) => {
queryClient.invalidateQueries({ queryKey: ['stats'] })
queryClient.invalidateQueries({ queryKey: ['tests'] })
- setIsRescanning(false)
setIsScanning(false)
+ if (data?.errors?.length) {
+ setSaveError(data.errors.join('\n'))
+ }
})
useEffect(() => {
@@ -150,24 +151,6 @@ export default function ConfigModal({ onClose, currentUserId = null }) {
}
}
- async function handleRescanResults() {
- setSaveError(null)
- setIsRescanning(true)
- try {
- const data = await apiFetch('/config/rescan-results', { method: 'POST' })
- if (data?.scanning) {
- scanPoller.start()
- } else {
- setIsRescanning(false)
- queryClient.invalidateQueries({ queryKey: ['stats'] })
- queryClient.invalidateQueries({ queryKey: ['tests'] })
- }
- } catch (err) {
- setSaveError(err?.message ?? 'Rescan failed')
- setIsRescanning(false)
- }
- }
-
const AVG_FIELDS = [
{ key: 'avg_time_coe', label: 'COE avg time (min)' },
{ key: 'avg_time_p2p', label: 'P2P avg time (min)' },
@@ -306,8 +289,8 @@ export default function ConfigModal({ onClose, currentUserId = null }) {
{/* Error banner */}
{saveError && (
-
- {saveError}
+
+ {saveError.split('\n').map((line, i) =>
{line}
)}
)}
@@ -331,14 +314,6 @@ export default function ConfigModal({ onClose, currentUserId = null }) {
)}
- {/* Rescan indicator (rescan button used) */}
- {!isScanning && isRescanning && (
-
- ⟳
- Results scan in progress…
-
- )}
-
{activeTab === 'general' && isLoading ? (
Loading…
) : activeTab === 'general' ? (
@@ -561,23 +536,16 @@ export default function ConfigModal({ onClose, currentUserId = null }) {
{activeTab === 'general' ? (
<>
-