Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 27 additions & 7 deletions src/pages/AnalysisDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import GlassCard from '../components/GlassCard';
import StatusTerminal from '../components/StatusTerminal';
import { api } from '../lib/api';
import type { ScanResult } from '../lib/types';

const BIOMARKER_META = {
gill_saturation: { label: 'Gill Saturation', icon: Droplets },
corneal_clarity: { label: 'Corneal Clarity', icon: EyeIcon },
Expand All @@ -27,12 +26,14 @@ export default function AnalysisDashboard() {
const [error, setError] = useState('');

useEffect(() => {

async function load() {
setLoading(true);
setError('');
setError("");

try {
const idParam = params.get('id');
const lastId = sessionStorage.getItem('lastScanId');
const idParam = params.get("id");
const lastId = sessionStorage.getItem("lastScanId");
const targetId = idParam || lastId;
Comment on lines +35 to 37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Guard fallback data against request-ID mismatch.

When id is explicitly requested, catch-path fallback currently accepts any cached offlineScanResult, which can show unrelated scan data.

Use fallback only when no explicit id exists, or when cached scan_id matches the requested ID.

Suggested patch
-      try {
-        const idParam = params.get("id");
-        const lastId = sessionStorage.getItem("lastScanId");
-        const targetId = idParam || lastId;
+      const idParam = params.get("id");
+      const lastId = sessionStorage.getItem("lastScanId");
+      const targetId = idParam || lastId;
+      try {
@@
-        if (offlineData) {
+        if (offlineData) {
           try {
             const parsed = JSON.parse(offlineData);
-
-            if (parsed?.freshness_index != null) {
+            const matchesRequestedId =
+              !idParam || parsed?.scan_id === idParam;
+            if (parsed?.freshness_index != null && matchesRequestedId) {
               setScan(parsed);
               setLoading(false); 
               return;
             }
           } catch (e) {

Also applies to: 45-55

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/AnalysisDashboard.tsx` around lines 35 - 37, The fallback data
validation needs to ensure that cached offline scan results are only used when
they match the requested ID. In the AnalysisDashboard component where targetId
is determined from idParam or lastId, add validation logic to check that any
offlineScanResult being used has a scan_id that matches the targetId.
Specifically, when an explicit id parameter is provided (idParam is not null),
only use the cached offlineScanResult if its scan_id matches idParam, otherwise
discard it. This validation should be applied at the point where
offlineScanResult is accessed and used (lines 45-55) to prevent displaying
unrelated scan data from the cache when a specific scan ID is explicitly
requested.


const res = targetId
Expand All @@ -41,16 +42,35 @@ export default function AnalysisDashboard() {

setScan(res.scan);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load scan data.');
const offlineData = sessionStorage.getItem("offlineScanResult");

if (offlineData) {
try {
const parsed = JSON.parse(offlineData);

if (parsed?.freshness_index != null) {
setScan(parsed);
setLoading(false);
return;
}
} catch (e) {
console.warn("Failed to parse offline scan result", e);
}
}

setError(
err instanceof Error ? err.message : "Failed to load scan data."
);
} finally {
setLoading(false);
}
}

load();
}, [params]);

// ── Loading state ────────────────────────────────────────────────────────
if (loading) {

if (loading) {
return (
<div className="min-h-[calc(100vh-4rem)] flex items-center justify-center">
<StatusTerminal messages={['LOADING_ANALYSIS...', 'FETCHING_RESULT']} />
Expand Down
51 changes: 51 additions & 0 deletions src/pages/ScannerPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,57 @@ export default function ScannerPage() {

stopProgress(100);
const freshness = Math.round(fusion.fusedScore * 100);
const offlineScanResult = {
scan_id: "offline-scan",
scan_display_id: "OFFLINE_SCAN",
freshness_index: freshness,
grade: deriveGrade(freshness),
confidence: parseFloat(fusion.confidence),
classification:
fusion.label === "Fresh"
? "FRESH"
: fusion.label === "Moderate"
? "FRESH"
: "SPOILED",
is_fresh: fusion.label !== "Spoiled",
uncertain_flag: false,
species: {
common_name: "Unknown Fish",
scientific_name: "N/A",
habitat: "N/A",
tags: [],
weight_estimate_kg: 0,
catch_age_hours: 0,
},
biomarkers: {
gill_saturation: {
score: freshness,
status: "NOMINAL",
detail: "Offline edge inference",
},
corneal_clarity: {
score: freshness,
status: "NOMINAL",
detail: "Offline edge inference",
},
epidermal_tension: {
score: freshness,
status: "NOMINAL",
detail: "Offline edge inference",
},
},
recommendations: {
consume_within_hours: 0,
storage_temp: "Unknown",
alert_flags: ["Generated from offline scan"],
},
};

sessionStorage.setItem(
"offlineScanResult",
JSON.stringify(offlineScanResult),
);
Comment on lines +302 to +305

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Make offlineScanResult persistence non-fatal.

A sessionStorage.setItem(...) failure here aborts the successful offline inference path and sends users to error state. The cache write should be best-effort only.

Suggested patch
-        sessionStorage.setItem(
-          "offlineScanResult",
-          JSON.stringify(offlineScanResult),
-        );
+        try {
+          sessionStorage.setItem(
+            "offlineScanResult",
+            JSON.stringify(offlineScanResult),
+          );
+        } catch (storageErr) {
+          console.warn("Failed to persist offline scan result", storageErr);
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sessionStorage.setItem(
"offlineScanResult",
JSON.stringify(offlineScanResult),
);
try {
sessionStorage.setItem(
"offlineScanResult",
JSON.stringify(offlineScanResult),
);
} catch (storageErr) {
console.warn("Failed to persist offline scan result", storageErr);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/ScannerPage.tsx` around lines 302 - 305, The sessionStorage.setItem
call for persisting offlineScanResult is not handling potential failures, which
causes the entire offline inference operation to abort if the write fails. Wrap
the sessionStorage.setItem call in a try-catch block so that if the persistence
fails (due to quota exceeded or other reasons), the error is caught and logged
without interrupting the successful offline inference flow.


setResult({
label: fusion.label,
freshness,
Expand Down
Loading