Skip to content

feat: Add lightweight issue tracking UI, HF OD model, and fix camera unmount bug#703

Open
RohanExploit wants to merge 4 commits intomainfrom
feature/lightweight-issues-tracking-hf-1984330708984751353
Open

feat: Add lightweight issue tracking UI, HF OD model, and fix camera unmount bug#703
RohanExploit wants to merge 4 commits intomainfrom
feature/lightweight-issues-tracking-hf-1984330708984751353

Conversation

@RohanExploit
Copy link
Copy Markdown
Owner

@RohanExploit RohanExploit commented Apr 26, 2026

This PR adds several features:

  1. "Track Your Issue" UI component leveraging existing backend /api/issues/{id} endpoint.
  2. Lightweight object detection endpoint using Hugging Face's facebook/detr-resnet-50 serverless inference.
  3. Bugfix to ensure camera fully unmounts and tracks stop properly on CameraCheckModal close.
  4. Installed missing testing dependencies for TS/React so tests run successfully.
  5. Ensured _redirects and _headers are properly placed for Netlify deployments.

PR created automatically by Jules for task 1984330708984751353 started by @RohanExploit


Summary by cubic

Adds a lightweight issue tracking UI and a Hugging Face object detection API. Fixes camera unmount and moves Netlify redirects/headers into root config to resolve CI.

  • New Features

    • API: /api/detect-objects using Hugging Face facebook/detr-resnet-50; returns { detections: [{ score, label, box }, ...] }.
    • UI: “Track Your Issue” on Home; queries /api/issues/{id} and shows status, category, description, and created date.
  • Bug Fixes

    • CameraCheckModal: stop all tracks and clear videoRef.srcObject on unmount.
    • Netlify: root netlify.toml with base = "frontend" now includes React Router redirect and security headers; removed frontend/public/_redirects and _headers to fix CI.
    • Add playwright to dev dependencies to unblock TS/React tests.

Written for commit e6b8a02. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Object detection functionality now available
    • Issue tracking with status updates and creation timestamps

- Added 'Track Your Issue' component in frontend Home.jsx
- Integrated facebook/detr-resnet-50 Hugging Face model for /api/detect-objects endpoint
- Fixed camera not fully shutting off in CameraCheckModal on unmount
- Cleaned up temp scripts and corrected dev dependencies for tests
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@github-actions
Copy link
Copy Markdown

🙏 Thank you for your contribution, @RohanExploit!

PR Details:

Quality Checklist:
Please ensure your PR meets the following criteria:

  • Code follows the project's style guidelines
  • Self-review of code completed
  • Code is commented where necessary
  • Documentation updated (if applicable)
  • No new warnings generated
  • Tests added/updated (if applicable)
  • All tests passing locally
  • No breaking changes to existing functionality

Review Process:

  1. Automated checks will run on your code
  2. A maintainer will review your changes
  3. Address any requested changes promptly
  4. Once approved, your PR will be merged! 🎉

Note: The maintainers will monitor code quality and ensure the overall project flow isn't broken.

@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 26, 2026

Deploy Preview for fixmybharat failed. Why did it fail? →

Name Link
🔨 Latest commit e6b8a02
🔍 Latest deploy log https://app.netlify.com/projects/fixmybharat/deploys/69edeca17081f80008dc5df0

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 26, 2026

📝 Walkthrough

Walkthrough

This PR introduces object detection capabilities by adding a new Hugging Face-based detector function and corresponding FastAPI endpoint to the backend, alongside frontend updates for issue tracking functionality and dependency management adjustments.

Changes

Cohort / File(s) Summary
Backend Detection Service
backend/hf_api_service.py, backend/routers/detection.py
Adds new async detect_objects_hf function that converts images to bytes and calls the HF object-detection API with authenticated POST requests, and introduces /detect-objects endpoint that validates uploads, processes images, and returns detection results with standardized error handling (400 for validation failures, 500 for detection errors).
Frontend Issue Tracking
frontend/src/views/Home.jsx
Adds state management for tracking ID, loading flag, and results; implements fetch handler to query /api/issues/{trackingId} and conditionally renders success/error panels; improves camera cleanup in CameraCheckModal by clearing video srcObject.
Build Configuration & Script Management
package.json, patch_home.py
Adds playwright to devDependencies; removes the patch_home.py script that previously patched Home.jsx in-place.

Sequence Diagram

sequenceDiagram
    participant Client as Client/Frontend
    participant Endpoint as FastAPI Endpoint
    participant Service as HF Service
    participant HFApi as Hugging Face API

    Client->>Endpoint: POST /detect-objects (image file)
    Endpoint->>Endpoint: validate_uploaded_file()
    Note over Endpoint: Image validation
    Endpoint->>Endpoint: process_uploaded_image()
    Note over Endpoint: Convert to bytes
    Endpoint->>Service: detect_objects_hf(image_bytes)
    Service->>HFApi: POST with auth headers
    Note over HFApi: Object detection processing
    HFApi-->>Service: JSON response (detections or error)
    alt List response
        Service-->>Endpoint: detections list
    else Non-list success
        Service-->>Endpoint: empty list
    else Error response
        Service-->>Endpoint: {error: "..."}
    end
    Endpoint-->>Client: Detection results or 500 error
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

size/l

Poem

🐰 A fuzzy detector hops along,
New HF endpoints, strong and long,
Objects dance in frames so bright,
Frontend tracks with issue's light,
Playwright joins the testing spree! 🎬

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes all three main changes in the PR: issue tracking UI, HF OD model integration, and camera unmount bug fix.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description covers all required template sections including a clear description of changes, type of change selection, and related issue information.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/lightweight-issues-tracking-hf-1984330708984751353

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
backend/hf_api_service.py (1)

530-559: LGTM — consistent with existing HF detector pattern.

detect_objects_hf mirrors detect_nsfw_content / detect_facial_emotion: prepares bytes, optionally reuses the shared client, returns {"detections": [...]} on success and a generic {"error": ...} on failure with details only logged server-side. The DETR response shape ([{"score","label","box":{xmin,ymin,xmax,ymax}}, ...]) is preserved verbatim under detections, which downstream consumers can render directly.

Minor optional nit: headers_bin (line 537) is identical to the module-level headers; you could drop the local rebinding to reduce duplication, but the existing functions in this file all do the same thing — so leaving it consistent is also fine.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/hf_api_service.py` around lines 530 - 559, The function
detect_objects_hf creates a local headers_bin identical to the module-level
headers; remove the local headers_bin and use the existing headers variable when
calling OBJECT_DETECTION_API_URL (update references inside the nested do_post
and any calls that pass headers_bin), or if you prefer to keep symmetry with
other functions, add a short comment explaining why the local copy is retained;
locate and edit detect_objects_hf and the nested do_post to replace headers_bin
with headers (or add the explanatory comment) so duplication is eliminated or
justified.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/routers/detection.py`:
- Around line 522-528: The endpoint currently treats validate_uploaded_file's
return as a dict and wrongly wraps process_uploaded_image in run_in_threadpool;
instead call process_uploaded_image(image) directly (it is async), let
validate_uploaded_file raise HTTPException if needed, unpack its return as (_,
image_bytes), remove the "error" dict checks and the run_in_threadpool call,
then pass image_bytes to detect_objects_hf with the client from get_http_client;
apply the same fix pattern used in detect_nsfw_endpoint/detect_emotion_endpoint
to match other HF endpoints.

In `@frontend/src/views/Home.jsx`:
- Around line 161-176: Add accessible labels and live region announcements for
tracking UI: give the input an id and either add a visible <label htmlFor="...">
or set aria-label on the input tied to trackingId used in the form that calls
handleTrackIssue; mark the submit state by setting aria-busy={isTracking} on the
<form> (or on the input) and wrap the tracking result panel (the element
rendering trackingResult) with role="status" and aria-live="polite" so
success/error updates are announced to assistive tech.
- Around line 153-194: The new tracker UI in Home.jsx uses hardcoded strings
(header "Track Your Issue", input placeholder, button labels when isTracking is
true/false, "Status:", and the trackingResult error messages) which bypass i18n;
update the JSX to call t(...) for each user-facing string (e.g.
t('home.tracker.title'), t('home.tracker.placeholder'), t('home.tracker.track'),
t('home.tracker.tracking'), t('home.tracker.status'),
t('home.tracker.notFound'), t('home.tracker.serverError')), add those keys into
the i18n resource files under home.tracker.*, and localize the date display
(replace new Date(...).toLocaleDateString() with a localized formatter using the
current locale or Intl.DateTimeFormat with i18n.language) so all visible text in
the Track Issue form and trackingResult flows uses translations.
- Around line 75-86: In handleTrackIssue, ensure trackingId is sanitized and
encoded by using encodeURIComponent(trackingId.trim()) when building the fetch
URL (replace the raw interpolation), improve error messaging by branching on
response.status (or reading the response error body) instead of treating every
non-OK as "Issue not found" and map 401/403/500 to appropriate messages when
calling setTrackingResult, and guarantee the UI unlock by moving
setIsTracking(false) into a finally block so it always runs regardless of
success or exceptions; update references accordingly for trackingId,
handleTrackIssue, setTrackingResult, and setIsTracking.
- Line 76: The fetch URL construction in Home.jsx (const response = await
fetch(...)) and the same pattern in ChatWidget.jsx uses the || fallback, which
causes an empty string VITE_API_URL to resolve to 'http://localhost:8000' in
production; change the fallback to use the nullish coalescing operator (??) so
import.meta.env.VITE_API_URL ?? 'http://localhost:8000' is used instead,
ensuring the hardcoded localhost is only used when VITE_API_URL is actually
undefined or null; alternatively ensure VITE_API_URL is set per-environment
(e.g., .env.production) if you prefer configuring at build time rather than
using a JS-side fallback.

In `@package.json`:
- Line 36: Remove the redundant devDependency "playwright" from package.json's
devDependencies (it duplicates functionality already provided by
"@playwright/test"), delete the "playwright" entry, then run your package
manager (npm/yarn/pnpm) to update the lockfile and node_modules so the change is
reflected; finally run the test suite/CI to ensure nothing breaks after removing
"playwright".

---

Nitpick comments:
In `@backend/hf_api_service.py`:
- Around line 530-559: The function detect_objects_hf creates a local
headers_bin identical to the module-level headers; remove the local headers_bin
and use the existing headers variable when calling OBJECT_DETECTION_API_URL
(update references inside the nested do_post and any calls that pass
headers_bin), or if you prefer to keep symmetry with other functions, add a
short comment explaining why the local copy is retained; locate and edit
detect_objects_hf and the nested do_post to replace headers_bin with headers (or
add the explanatory comment) so duplication is eliminated or justified.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 609c563e-27b5-4420-96f7-a1a5a1a7bb7a

📥 Commits

Reviewing files that changed from the base of the PR and between 3166316 and 1b8e13b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • backend/hf_api_service.py
  • backend/routers/detection.py
  • frontend/src/views/Home.jsx
  • package.json
  • patch_home.py
💤 Files with no reviewable changes (1)
  • patch_home.py

Comment on lines +522 to +528
img_data = await validate_uploaded_file(image)
if "error" in img_data:
raise HTTPException(status_code=400, detail=img_data["error"])

processed_bytes = await run_in_threadpool(process_uploaded_image, img_data["bytes"])
client = get_http_client(request)
result = await detect_objects_hf(processed_bytes, client)
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm the actual signatures/return types of validate_uploaded_file and process_uploaded_image
# to make sure the endpoint really is misusing them.
fd -t f 'utils.py' backend | xargs -I {} sh -c 'echo "=== {} ==="; cat {}'

Repository: RohanExploit/VishwaGuru

Length of output: 27535


🏁 Script executed:

#!/bin/bash
# Show how other endpoints in this router consume these helpers, for the correct pattern.
rg -nP -C2 '\b(validate_uploaded_file|process_uploaded_image)\s*\(' --type=py

Repository: RohanExploit/VishwaGuru

Length of output: 12658


Endpoint will fail at runtime — validate_uploaded_file returns a PIL Image, not a dict, and process_uploaded_image is already async.

validate_uploaded_file(file: UploadFile) -> Optional[Image.Image] (per backend/utils.py line 150) and process_uploaded_image(file: UploadFile) -> tuple[Image.Image, bytes] is already async (line 225). The new endpoint code instead:

  • if "error" in img_data: against a PIL.Image object → raises TypeError
  • img_data["bytes"] — Image is not subscriptable → raises TypeError
  • await run_in_threadpool(process_uploaded_image, ...) — wrapping an already-async function schedules the coroutine creation in a thread but never awaits it

This broken pattern is already present in detect_nsfw_endpoint (lines 478–480) and detect_emotion_endpoint (lines 500–502). Follow the working pattern used by 15+ other HF endpoints: call process_uploaded_image directly on the UploadFile, unpack the tuple (_, image_bytes), and let validation HTTPExceptions bubble up (e.g. detect_illegal_parking_endpoint at line 160, detect_street_light_endpoint at line 173).

🔧 Proposed fix
 `@router.post`("/detect-objects")
 async def detect_objects_endpoint(
     request: Request,
     image: UploadFile = File(...)
 ):
     """
     Detects general objects in the image using Hugging Face object detection model.
     """
-    img_data = await validate_uploaded_file(image)
-    if "error" in img_data:
-        raise HTTPException(status_code=400, detail=img_data["error"])
-
-    processed_bytes = await run_in_threadpool(process_uploaded_image, img_data["bytes"])
-    client = get_http_client(request)
-    result = await detect_objects_hf(processed_bytes, client)
-
-    if "error" in result:
-        raise HTTPException(status_code=500, detail="Internal server error")
-
-    return result
+    # process_uploaded_image validates, resizes and strips EXIF; raises HTTPException on bad input.
+    _, image_bytes = await process_uploaded_image(image)
+
+    try:
+        client = get_http_client(request)
+        result = await detect_objects_hf(image_bytes, client=client)
+    except HTTPException:
+        raise
+    except Exception as e:
+        logger.error(f"Object detection error: {e}", exc_info=True)
+        raise HTTPException(status_code=500, detail="Internal server error")
+
+    if "error" in result:
+        raise HTTPException(status_code=500, detail="Internal server error")
+
+    return result
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/routers/detection.py` around lines 522 - 528, The endpoint currently
treats validate_uploaded_file's return as a dict and wrongly wraps
process_uploaded_image in run_in_threadpool; instead call
process_uploaded_image(image) directly (it is async), let validate_uploaded_file
raise HTTPException if needed, unpack its return as (_, image_bytes), remove the
"error" dict checks and the run_in_threadpool call, then pass image_bytes to
detect_objects_hf with the client from get_http_client; apply the same fix
pattern used in detect_nsfw_endpoint/detect_emotion_endpoint to match other HF
endpoints.

Comment on lines +75 to +86
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
if (response.ok) {
const data = await response.json();
setTrackingResult({ success: true, data });
} else {
setTrackingResult({ success: false, error: 'Issue not found. Please check the ID.' });
}
} catch (error) {
setTrackingResult({ success: false, error: 'Error connecting to server.' });
}
setIsTracking(false);
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 | 🟡 Minor

Robustness nits in handleTrackIssue.

  • trackingId is interpolated raw into the URL path. If a user pastes anything containing /, ?, #, or whitespace, the request goes to the wrong endpoint. Wrap with encodeURIComponent(trackingId.trim()).
  • All non-OK responses surface as "Issue not found.", but a 401/403/500 is not the same as a 404. Branch on response.status (or read the server error body) so users get a meaningful message.
  • setIsTracking(false) runs after the try/catch; move it into a finally block so future early-returns or rethrows can't accidentally leave the button stuck in the disabled state.
🔧 Proposed fix
   const handleTrackIssue = async (e) => {
     e.preventDefault();
-    if (!trackingId.trim()) return;
+    const id = trackingId.trim();
+    if (!id) return;

     setIsTracking(true);
     setTrackingResult(null);
     try {
-      const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
+      const apiBase = import.meta.env.VITE_API_URL ?? '';
+      const response = await fetch(`${apiBase}/api/issues/${encodeURIComponent(id)}`);
       if (response.ok) {
         const data = await response.json();
         setTrackingResult({ success: true, data });
+      } else if (response.status === 404) {
+        setTrackingResult({ success: false, error: t('home.tracker.errors.notFound') });
       } else {
-        setTrackingResult({ success: false, error: 'Issue not found. Please check the ID.' });
+        setTrackingResult({ success: false, error: t('home.tracker.errors.server', { status: response.status }) });
       }
     } catch (error) {
-      setTrackingResult({ success: false, error: 'Error connecting to server.' });
+      setTrackingResult({ success: false, error: t('home.tracker.errors.network') });
+    } finally {
+      setIsTracking(false);
     }
-    setIsTracking(false);
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/views/Home.jsx` around lines 75 - 86, In handleTrackIssue,
ensure trackingId is sanitized and encoded by using
encodeURIComponent(trackingId.trim()) when building the fetch URL (replace the
raw interpolation), improve error messaging by branching on response.status (or
reading the response error body) instead of treating every non-OK as "Issue not
found" and map 401/403/500 to appropriate messages when calling
setTrackingResult, and guarantee the UI unlock by moving setIsTracking(false)
into a finally block so it always runs regardless of success or exceptions;
update references accordingly for trackingId, handleTrackIssue,
setTrackingResult, and setIsTracking.

setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm how VITE_API_URL is resolved at build time and whether other call sites use the same pattern.
fd -t f 'vite.config.*' | xargs -I{} sh -c 'echo "=== {} ==="; cat "{}"'
echo "--- other VITE_API_URL usages ---"
rg -nP --type=js --type=jsx --type=ts --type=tsx -C2 'VITE_API_URL'

Repository: RohanExploit/VishwaGuru

Length of output: 1985


🏁 Script executed:

#!/bin/bash
# Search for VITE_API_URL usages with broader search to work around file type issue
echo "=== All VITE_API_URL usages ==="
rg 'VITE_API_URL' -C 3

echo ""
echo "=== Line count and location in vite.config.js ==="
cat -n frontend/vite.config.js | grep -A 5 -B 5 'VITE_API_URL'

echo ""
echo "=== Environment files ==="
fd -t f '\.env' | head -20

echo ""
echo "=== Home.jsx around line 76 ==="
sed -n '70,85p' frontend/src/views/Home.jsx | cat -n

Repository: RohanExploit/VishwaGuru

Length of output: 34779


Production builds will call http://localhost:8000 — issue tracking will be broken for end users.

Per frontend/vite.config.js line 74, import.meta.env.VITE_API_URL is replaced with "" at build time. Since an empty string is falsy, import.meta.env.VITE_API_URL || 'http://localhost:8000' always resolves to the hardcoded localhost URL in shipped bundles. This affects:

  • frontend/src/views/Home.jsx (line 76)
  • frontend/src/components/ChatWidget.jsx

User browsers will attempt requests to http://localhost:8000/api/... and fail.

Use the nullish coalescing operator to only fall back to localhost when VITE_API_URL is genuinely undefined (not empty):

🔧 Proposed fix
- const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
+ const apiBase = import.meta.env.VITE_API_URL ?? 'http://localhost:8000';
+ const response = await fetch(`${apiBase}/api/issues/${encodeURIComponent(trackingId)}`);

Or configure VITE_API_URL per-environment (.env.production) instead of relying on the JS-side fallback.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/views/Home.jsx` at line 76, The fetch URL construction in
Home.jsx (const response = await fetch(...)) and the same pattern in
ChatWidget.jsx uses the || fallback, which causes an empty string VITE_API_URL
to resolve to 'http://localhost:8000' in production; change the fallback to use
the nullish coalescing operator (??) so import.meta.env.VITE_API_URL ??
'http://localhost:8000' is used instead, ensuring the hardcoded localhost is
only used when VITE_API_URL is actually undefined or null; alternatively ensure
VITE_API_URL is set per-environment (e.g., .env.production) if you prefer
configuring at build time rather than using a JS-side fallback.

Comment on lines +153 to +194
{/* Issue Tracker Component */}
<div className="bg-white rounded-3xl p-6 shadow-sm border border-slate-100 mb-8 mt-8">
<div className="flex items-center gap-3 mb-4">
<div className="bg-indigo-100 p-2 rounded-xl text-indigo-600">
<Search size={24} />
</div>
<h3 className="text-xl font-bold">Track Your Issue</h3>
</div>
<form onSubmit={handleTrackIssue} className="flex gap-2">
<input
type="text"
placeholder="Enter Tracking ID (e.g., 1)"
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
value={trackingId}
onChange={(e) => setTrackingId(e.target.value)}
/>
<button
type="submit"
disabled={isTracking}
className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold hover:bg-indigo-700 transition disabled:opacity-70"
>
{isTracking ? 'Tracking...' : 'Track'}
</button>
</form>

{trackingResult && trackingResult.success && (
<div className="mt-4 p-4 bg-green-50 rounded-xl border border-green-100">
<div className="flex items-center justify-between mb-2">
<span className="font-bold text-green-800 uppercase text-sm">Status: {trackingResult.data.status}</span>
<span className="text-xs text-green-600">{new Date(trackingResult.data.created_at).toLocaleDateString()}</span>
</div>
<p className="text-green-900 font-medium">{trackingResult.data.category}</p>
<p className="text-sm text-green-700 mt-1 line-clamp-2">{trackingResult.data.description}</p>
</div>
)}

{trackingResult && !trackingResult.success && (
<div className="mt-4 p-3 bg-red-50 text-red-600 rounded-xl text-sm font-medium">
{trackingResult.error}
</div>
)}
</div>
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

New UI strings bypass i18n — inconsistent with the rest of Home.jsx.

Every other label in this view goes through t(...) (e.g. t('home.privacyActive'), t('home.tools.cameraCheck')), but the new tracker hardcodes "Track Your Issue", "Enter Tracking ID (e.g., 1)", "Tracking...", "Track", "Status:", "Issue not found. Please check the ID.", and "Error connecting to server.". This breaks localization for every non-English user.

Move these strings into the i18n resources (e.g. home.tracker.*) and reference them via t(). Also consider localizing the date formatter:

🔧 Suggested skeleton
-            <h3 className="text-xl font-bold">Track Your Issue</h3>
+            <h3 className="text-xl font-bold">{t('home.tracker.title')}</h3>
@@
-              placeholder="Enter Tracking ID (e.g., 1)"
+              placeholder={t('home.tracker.placeholder')}
@@
-              {isTracking ? 'Tracking...' : 'Track'}
+              {isTracking ? t('home.tracker.loading') : t('home.tracker.submit')}
@@
-                <span className="font-bold text-green-800 uppercase text-sm">Status: {trackingResult.data.status}</span>
-                <span className="text-xs text-green-600">{new Date(trackingResult.data.created_at).toLocaleDateString()}</span>
+                <span className="font-bold text-green-800 uppercase text-sm">
+                  {t('home.tracker.statusLabel', { status: trackingResult.data.status })}
+                </span>
+                <span className="text-xs text-green-600">
+                  {new Date(trackingResult.data.created_at).toLocaleDateString(i18n.language)}
+                </span>
📝 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
{/* Issue Tracker Component */}
<div className="bg-white rounded-3xl p-6 shadow-sm border border-slate-100 mb-8 mt-8">
<div className="flex items-center gap-3 mb-4">
<div className="bg-indigo-100 p-2 rounded-xl text-indigo-600">
<Search size={24} />
</div>
<h3 className="text-xl font-bold">Track Your Issue</h3>
</div>
<form onSubmit={handleTrackIssue} className="flex gap-2">
<input
type="text"
placeholder="Enter Tracking ID (e.g., 1)"
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
value={trackingId}
onChange={(e) => setTrackingId(e.target.value)}
/>
<button
type="submit"
disabled={isTracking}
className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold hover:bg-indigo-700 transition disabled:opacity-70"
>
{isTracking ? 'Tracking...' : 'Track'}
</button>
</form>
{trackingResult && trackingResult.success && (
<div className="mt-4 p-4 bg-green-50 rounded-xl border border-green-100">
<div className="flex items-center justify-between mb-2">
<span className="font-bold text-green-800 uppercase text-sm">Status: {trackingResult.data.status}</span>
<span className="text-xs text-green-600">{new Date(trackingResult.data.created_at).toLocaleDateString()}</span>
</div>
<p className="text-green-900 font-medium">{trackingResult.data.category}</p>
<p className="text-sm text-green-700 mt-1 line-clamp-2">{trackingResult.data.description}</p>
</div>
)}
{trackingResult && !trackingResult.success && (
<div className="mt-4 p-3 bg-red-50 text-red-600 rounded-xl text-sm font-medium">
{trackingResult.error}
</div>
)}
</div>
{/* Issue Tracker Component */}
<div className="bg-white rounded-3xl p-6 shadow-sm border border-slate-100 mb-8 mt-8">
<div className="flex items-center gap-3 mb-4">
<div className="bg-indigo-100 p-2 rounded-xl text-indigo-600">
<Search size={24} />
</div>
<h3 className="text-xl font-bold">{t('home.tracker.title')}</h3>
</div>
<form onSubmit={handleTrackIssue} className="flex gap-2">
<input
type="text"
placeholder={t('home.tracker.placeholder')}
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
value={trackingId}
onChange={(e) => setTrackingId(e.target.value)}
/>
<button
type="submit"
disabled={isTracking}
className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold hover:bg-indigo-700 transition disabled:opacity-70"
>
{isTracking ? t('home.tracker.loading') : t('home.tracker.submit')}
</button>
</form>
{trackingResult && trackingResult.success && (
<div className="mt-4 p-4 bg-green-50 rounded-xl border border-green-100">
<div className="flex items-center justify-between mb-2">
<span className="font-bold text-green-800 uppercase text-sm">
{t('home.tracker.statusLabel', { status: trackingResult.data.status })}
</span>
<span className="text-xs text-green-600">
{new Date(trackingResult.data.created_at).toLocaleDateString(i18n.language)}
</span>
</div>
<p className="text-green-900 font-medium">{trackingResult.data.category}</p>
<p className="text-sm text-green-700 mt-1 line-clamp-2">{trackingResult.data.description}</p>
</div>
)}
{trackingResult && !trackingResult.success && (
<div className="mt-4 p-3 bg-red-50 text-red-600 rounded-xl text-sm font-medium">
{trackingResult.error}
</div>
)}
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/views/Home.jsx` around lines 153 - 194, The new tracker UI in
Home.jsx uses hardcoded strings (header "Track Your Issue", input placeholder,
button labels when isTracking is true/false, "Status:", and the trackingResult
error messages) which bypass i18n; update the JSX to call t(...) for each
user-facing string (e.g. t('home.tracker.title'), t('home.tracker.placeholder'),
t('home.tracker.track'), t('home.tracker.tracking'), t('home.tracker.status'),
t('home.tracker.notFound'), t('home.tracker.serverError')), add those keys into
the i18n resource files under home.tracker.*, and localize the date display
(replace new Date(...).toLocaleDateString() with a localized formatter using the
current locale or Intl.DateTimeFormat with i18n.language) so all visible text in
the Track Issue form and trackingResult flows uses translations.

Comment on lines +161 to +176
<form onSubmit={handleTrackIssue} className="flex gap-2">
<input
type="text"
placeholder="Enter Tracking ID (e.g., 1)"
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
value={trackingId}
onChange={(e) => setTrackingId(e.target.value)}
/>
<button
type="submit"
disabled={isTracking}
className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold hover:bg-indigo-700 transition disabled:opacity-70"
>
{isTracking ? 'Tracking...' : 'Track'}
</button>
</form>
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 | 🟡 Minor

Accessibility: form input lacks an associated label.

The <input> only has a placeholder, which screen readers and assistive tech don't treat as a label. Add a visible <label htmlFor=...> (or at minimum aria-label) and an id on the input. Also consider aria-busy={isTracking} on the form, or aria-live region for trackingResult so announcements reach AT users.

🔧 Proposed fix
-          <form onSubmit={handleTrackIssue} className="flex gap-2">
+          <form onSubmit={handleTrackIssue} className="flex gap-2" aria-busy={isTracking}>
+            <label htmlFor="tracking-id" className="sr-only">
+              {t('home.tracker.placeholder')}
+            </label>
             <input
+              id="tracking-id"
               type="text"
               placeholder="Enter Tracking ID (e.g., 1)"
+              aria-label={t('home.tracker.placeholder')}
               className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
               value={trackingId}
               onChange={(e) => setTrackingId(e.target.value)}
             />

Wrap the result panels (lines 178-193) in role="status" aria-live="polite" so success/error states are announced.

📝 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
<form onSubmit={handleTrackIssue} className="flex gap-2">
<input
type="text"
placeholder="Enter Tracking ID (e.g., 1)"
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
value={trackingId}
onChange={(e) => setTrackingId(e.target.value)}
/>
<button
type="submit"
disabled={isTracking}
className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold hover:bg-indigo-700 transition disabled:opacity-70"
>
{isTracking ? 'Tracking...' : 'Track'}
</button>
</form>
<form onSubmit={handleTrackIssue} className="flex gap-2" aria-busy={isTracking}>
<label htmlFor="tracking-id" className="sr-only">
{t('home.tracker.placeholder')}
</label>
<input
id="tracking-id"
type="text"
placeholder="Enter Tracking ID (e.g., 1)"
aria-label={t('home.tracker.placeholder')}
className="flex-1 border border-gray-200 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-indigo-500"
value={trackingId}
onChange={(e) => setTrackingId(e.target.value)}
/>
<button
type="submit"
disabled={isTracking}
className="bg-indigo-600 text-white px-6 py-3 rounded-xl font-bold hover:bg-indigo-700 transition disabled:opacity-70"
>
{isTracking ? 'Tracking...' : 'Track'}
</button>
</form>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/views/Home.jsx` around lines 161 - 176, Add accessible labels
and live region announcements for tracking UI: give the input an id and either
add a visible <label htmlFor="..."> or set aria-label on the input tied to
trackingId used in the form that calls handleTrackIssue; mark the submit state
by setting aria-busy={isTracking} on the <form> (or on the input) and wrap the
tracking result panel (the element rendering trackingResult) with role="status"
and aria-live="polite" so success/error updates are announced to assistive tech.

Comment thread package.json
"jest": "^29.7.0",
"jest-environment-jsdom": "^30.3.0",
"jest-util": "^30.3.0",
"playwright": "^1.59.1",
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 | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Check if the base 'playwright' package is imported or used anywhere

# Search for direct imports of 'playwright' (excluding `@playwright/test`)
rg -n --type=js --type=ts -C3 "(?:require\(['\"]playwright['\"]\)|from ['\"]playwright['\"])" --pcre2

# Also check for dynamic imports
rg -n --type=js --type=ts -C3 "import\(['\"]playwright['\"]\)" --pcre2

Repository: RohanExploit/VishwaGuru

Length of output: 49


Remove the redundant playwright package from devDependencies.

The @playwright/test package (line 28) already includes the full Playwright library. The base playwright package at line 36 is unused in the codebase and only adds unnecessary installation time, disk usage, and maintenance overhead.

Fix
-    "playwright": "^1.59.1",
📝 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
"playwright": "^1.59.1",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 36, Remove the redundant devDependency "playwright"
from package.json's devDependencies (it duplicates functionality already
provided by "@playwright/test"), delete the "playwright" entry, then run your
package manager (npm/yarn/pnpm) to update the lockfile and node_modules so the
change is reflected; finally run the test suite/CI to ensure nothing breaks
after removing "playwright".

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a small “Track Your Issue” UI to the Home page, introduces a new Hugging Face-backed object detection endpoint, fixes camera cleanup on modal close, and updates root-level test tooling dependencies.

Changes:

  • Add “Track Your Issue” form + results panel to Home.jsx and improve camera stream teardown.
  • Add /api/detect-objects endpoint wired to HF facebook/detr-resnet-50 via detect_objects_hf.
  • Add Playwright dependency updates in root package.json / lockfile (to support existing Playwright spec usage).

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
patch_home.py Removes a one-off patch script previously used to modify Home.jsx.
package.json Adds Playwright dependency entries for root tooling.
package-lock.json Locks Playwright-related packages/versions.
frontend/src/views/Home.jsx Adds issue-tracking UI and clears video.srcObject on unmount.
backend/routers/detection.py Adds /detect-objects API endpoint and imports detect_objects_hf.
backend/hf_api_service.py Adds detect_objects_hf() and the DETR model URL constant.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +71 to +79
if (!trackingId.trim()) return;

setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
if (response.ok) {
const data = await response.json();
setTrackingResult({ success: true, data });
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

handleTrackIssue calls /api/issues/${trackingId}, but the backend router mounted at /api does not currently expose a GET /issues/{id} endpoint (see backend/routers/issues.py, which only has /issues/recent, /issues/nearby, /issues/user, etc.). As-is, the new “Track Your Issue” UI will always get a 404. Either add the missing backend GET-by-id endpoint, or update this UI to call an endpoint that actually exists.

Suggested change
if (!trackingId.trim()) return;
setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
if (response.ok) {
const data = await response.json();
setTrackingResult({ success: true, data });
const normalizedTrackingId = trackingId.trim();
if (!normalizedTrackingId) return;
setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/recent`);
if (response.ok) {
const data = await response.json();
const issues = Array.isArray(data)
? data
: Array.isArray(data?.issues)
? data.issues
: Array.isArray(data?.data)
? data.data
: [];
const matchedIssue = issues.find((issue) => {
const candidateIds = [issue?.id, issue?._id, issue?.tracking_id]
.filter((value) => value !== undefined && value !== null)
.map((value) => String(value).trim());
return candidateIds.includes(normalizedTrackingId);
});
if (matchedIssue) {
setTrackingResult({ success: true, data: matchedIssue });
} else {
setTrackingResult({ success: false, error: 'Issue not found. Please check the ID.' });
}

Copilot uses AI. Check for mistakes.
Comment on lines +71 to +76
if (!trackingId.trim()) return;

setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

The tracking request URL interpolates user input directly into the path. If the user enters characters like /, ?, or #, this can produce an unintended request path. Encode the ID segment (and/or validate it as an integer if that’s what the backend expects) before building the URL.

Suggested change
if (!trackingId.trim()) return;
setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
const trimmedTrackingId = trackingId.trim();
if (!trimmedTrackingId) return;
setIsTracking(true);
setTrackingResult(null);
try {
const encodedTrackingId = encodeURIComponent(trimmedTrackingId);
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${encodedTrackingId}`);

Copilot uses AI. Check for mistakes.
Comment on lines +181 to +183
<span className="font-bold text-green-800 uppercase text-sm">Status: {trackingResult.data.status}</span>
<span className="text-xs text-green-600">{new Date(trackingResult.data.created_at).toLocaleDateString()}</span>
</div>
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

new Date(trackingResult.data.created_at).toLocaleDateString() can throw (RangeError: Invalid time value) if created_at is missing/null/not parseable. Several backend issue responses in this repo serialize created_at conditionally (... if row.created_at else None), so this UI should guard and render a fallback (or omit the date) when created_at isn’t present.

Copilot uses AI. Check for mistakes.
Comment on lines +522 to +527
img_data = await validate_uploaded_file(image)
if "error" in img_data:
raise HTTPException(status_code=400, detail=img_data["error"])

processed_bytes = await run_in_threadpool(process_uploaded_image, img_data["bytes"])
client = get_http_client(request)
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

This endpoint treats validate_uploaded_file() as if it returns a dict containing bytes/error, but in backend/utils.py it returns a PIL Image.Image (or raises an HTTPException). As written, "error" in img_data will raise a TypeError, and img_data["bytes"] will also fail. Align this with the other detection endpoints that use process_uploaded_image(image) to obtain validated image bytes before calling the HF service.

Copilot uses AI. Check for mistakes.
Comment thread package.json
"jest": "^29.7.0",
"jest-environment-jsdom": "^30.3.0",
"jest-util": "^30.3.0",
"playwright": "^1.59.1",
Copy link

Copilot AI Apr 26, 2026

Choose a reason for hiding this comment

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

@playwright/test already pulls in playwright (and exposes the Playwright CLI via npx playwright). Adding playwright separately is typically redundant and increases install size/time. If you don’t have a specific need for playwright as a direct devDependency, consider removing it and keeping only @playwright/test.

Suggested change
"playwright": "^1.59.1",

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

3 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frontend/src/views/Home.jsx">

<violation number="1" location="frontend/src/views/Home.jsx:76">
P1: In production builds, `VITE_API_URL` is statically replaced with `""` (empty string) by Vite. Since empty string is falsy, the `||` operator causes the fallback to `'http://localhost:8000'`, making all API requests go to localhost in production. Use nullish coalescing (`??`) instead so empty string is treated as a valid value (relative URL), or set `VITE_API_URL` properly in `.env.production`.</violation>

<violation number="2" location="frontend/src/views/Home.jsx:159">
P2: All other labels in this view use `t(...)` for i18n, but the new tracker section hardcodes English strings (`"Track Your Issue"`, `"Tracking..."`, `"Issue not found. Please check the ID."`, etc.). This breaks localization for non-English users. Move these strings to i18n resources and reference them via `t('home.tracker.*')`.</violation>
</file>

<file name="backend/routers/detection.py">

<violation number="1" location="backend/routers/detection.py:522">
P1: The new object-detection endpoint misuses `validate_uploaded_file` as a dict result, causing runtime errors before detection runs.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

setIsTracking(true);
setTrackingResult(null);
try {
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 26, 2026

Choose a reason for hiding this comment

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

P1: In production builds, VITE_API_URL is statically replaced with "" (empty string) by Vite. Since empty string is falsy, the || operator causes the fallback to 'http://localhost:8000', making all API requests go to localhost in production. Use nullish coalescing (??) instead so empty string is treated as a valid value (relative URL), or set VITE_API_URL properly in .env.production.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/views/Home.jsx, line 76:

<comment>In production builds, `VITE_API_URL` is statically replaced with `""` (empty string) by Vite. Since empty string is falsy, the `||` operator causes the fallback to `'http://localhost:8000'`, making all API requests go to localhost in production. Use nullish coalescing (`??`) instead so empty string is treated as a valid value (relative URL), or set `VITE_API_URL` properly in `.env.production`.</comment>

<file context>
@@ -58,6 +61,31 @@ const Home = ({ setView, fetchResponsibilityMap, recentIssues, handleUpvote, loa
+    setIsTracking(true);
+    setTrackingResult(null);
+    try {
+      const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
+      if (response.ok) {
+        const data = await response.json();
</file context>
Suggested change
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:8000'}/api/issues/${trackingId}`);
const apiBase = import.meta.env.VITE_API_URL ?? 'http://localhost:8000';
const response = await fetch(`${apiBase}/api/issues/${encodeURIComponent(trackingId.trim())}`);
Fix with Cubic

Comment on lines +522 to +526
img_data = await validate_uploaded_file(image)
if "error" in img_data:
raise HTTPException(status_code=400, detail=img_data["error"])

processed_bytes = await run_in_threadpool(process_uploaded_image, img_data["bytes"])
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 26, 2026

Choose a reason for hiding this comment

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

P1: The new object-detection endpoint misuses validate_uploaded_file as a dict result, causing runtime errors before detection runs.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At backend/routers/detection.py, line 522:

<comment>The new object-detection endpoint misuses `validate_uploaded_file` as a dict result, causing runtime errors before detection runs.</comment>

<file context>
@@ -510,3 +510,24 @@ async def detect_emotion_endpoint(
+    """
+    Detects general objects in the image using Hugging Face object detection model.
+    """
+    img_data = await validate_uploaded_file(image)
+    if "error" in img_data:
+        raise HTTPException(status_code=400, detail=img_data["error"])
</file context>
Suggested change
img_data = await validate_uploaded_file(image)
if "error" in img_data:
raise HTTPException(status_code=400, detail=img_data["error"])
processed_bytes = await run_in_threadpool(process_uploaded_image, img_data["bytes"])
_, processed_bytes = await process_uploaded_image(image)
Fix with Cubic

<div className="bg-indigo-100 p-2 rounded-xl text-indigo-600">
<Search size={24} />
</div>
<h3 className="text-xl font-bold">Track Your Issue</h3>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 26, 2026

Choose a reason for hiding this comment

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

P2: All other labels in this view use t(...) for i18n, but the new tracker section hardcodes English strings ("Track Your Issue", "Tracking...", "Issue not found. Please check the ID.", etc.). This breaks localization for non-English users. Move these strings to i18n resources and reference them via t('home.tracker.*').

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/views/Home.jsx, line 159:

<comment>All other labels in this view use `t(...)` for i18n, but the new tracker section hardcodes English strings (`"Track Your Issue"`, `"Tracking..."`, `"Issue not found. Please check the ID."`, etc.). This breaks localization for non-English users. Move these strings to i18n resources and reference them via `t('home.tracker.*')`.</comment>

<file context>
@@ -122,6 +150,50 @@ const Home = ({ setView, fetchResponsibilityMap, recentIssues, handleUpvote, loa
+            <div className="bg-indigo-100 p-2 rounded-xl text-indigo-600">
+              <Search size={24} />
+            </div>
+            <h3 className="text-xl font-bold">Track Your Issue</h3>
+          </div>
+          <form onSubmit={handleTrackIssue} className="flex gap-2">
</file context>
Fix with Cubic

- Moved netlify.toml to frontend/ directory where the Vite build is actually configured
- Removed the `base = "frontend"` directive since the toml is now inside the frontend folder
- This ensures Netlify correctly picks up the Vite build command and dist folder
- Restored `netlify.toml` in the repository root with `base = "frontend"` directive.
- This configuration is required for Netlify to properly execute `npm install && npm run build` inside the `frontend` subdirectory, allowing the `_redirects` and `_headers` routing rules to correctly deploy for React Router.
@github-actions
Copy link
Copy Markdown

🔍 Quality Reminder

Thanks for the updates! Please ensure:
- Your changes don't break existing functionality
- All tests still pass
- Code quality standards are maintained

*The maintainers will verify that the overall project flow remains intact.*

- Moved React routing redirects and security headers from `frontend/public/_redirects` and `_headers` into the root `netlify.toml` file.
- When `base = "frontend"` is used in `netlify.toml`, Netlify often expects the routing and header rules to be defined in the toml file rather than physical files in the dist directory to pass CI validation checks for those rules.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants