feat(BR-155): Add search functionality to data feed - #97
Conversation
- Backend: Add search query parameter to /weekly-crises endpoint - Supports search by crisis name, location, and disaster type - Case-insensitive search with SQL ILIKE - Frontend: Add search input with 500ms debounce - Clean search UI with icon in data feed header - Auto-resets to page 1 on search - Smart empty state for no search results - API Client: Updated getWeeklyCrises() to accept search param - Uses URLSearchParams for clean query building
WalkthroughAdds a debounced search input to the crisis feed, threads a new Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as Frontend
participant Debounce as Debounce (500ms)
participant Client as API Client
participant Backend
participant DB as Database
User->>UI: Type search term
UI->>Debounce: update searchQuery
Debounce-->>Debounce: wait 500ms
Debounce->>UI: set debouncedSearch (reset page -> 1)
UI->>Client: getWeeklyCrises(days, page, pageSize, search=debouncedSearch)
Client->>Backend: GET /crises?...&search=...
Backend->>DB: WHERE (description ILIKE OR location_name ILIKE OR post.disaster_type ILIKE)
DB-->>Backend: rows
Backend-->>Client: response
Client-->>UI: render list
alt no results & search non-empty
UI->>User: show "No results found for '<term>'"
else results
UI->>User: show crises list
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
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. Comment |
✨ Version Bump PredictionWhen this PR is merged to 1.48.0 → 1.49.0 ( 💡 How to change the version bump typeThe version bump is determined by your commit messages and PR title:
What I analyzed:
Edit your PR title or commit messages to change the bump type. |
🚀 Preview Deployment Ready!Backend: https://api-kamalesh-br-155-frontend-add-s.private.bluerelief.app Commit: 🔐 AuthenticationDemo Login: Click "Google Sign In" → Use demo auth (no Google account needed) ✨ Version Bump PredictionWhen this PR is merged to main, the version will be bumped: 1.47.2 → 1.47.3 (patch) 💡 How to change the version bump type
Preview will be automatically deleted when PR is closed or merged. |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
server/routers/data_feed.py (1)
97-108: LGTM! Search filter correctly implemented with a performance note.The search implementation is functionally correct:
- Proper trimming and empty-string checks
- Case-insensitive search across the three relevant fields (description, location_name, disaster_type)
- SQLAlchemy's parameter binding safely handles the search term
Performance consideration: ILIKE with leading wildcards (
%term%) cannot leverage standard B-tree indexes. For larger datasets, consider PostgreSQL's trigram indexes (pg_trgm) or full-text search (tsvector) for better performance.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
client/app/dashboard/data-feed/page.tsx(6 hunks)client/lib/api-client.ts(2 hunks)server/routers/data_feed.py(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
server/routers/data_feed.py (1)
server/db_utils/db.py (2)
Disaster(183-202)Post(116-180)
client/app/dashboard/data-feed/page.tsx (1)
client/lib/api-client.ts (1)
getWeeklyCrises(95-130)
🪛 Ruff (0.14.5)
server/routers/data_feed.py
86-86: Do not perform function call Depends in argument defaults; instead, perform the call within the function, or read the default from a module-level singleton variable
(B008)
🔇 Additional comments (8)
client/lib/api-client.ts (1)
95-129: LGTM! Clean implementation of search parameter.The search parameter is correctly integrated:
- Default empty string is appropriate
- URLSearchParams handles encoding properly
- Conditional append prevents empty search parameters in the URL
- Trimming prevents whitespace-only searches
client/app/dashboard/data-feed/page.tsx (5)
4-4: LGTM! Necessary imports for search functionality.The Search icon and Input component are properly imported and used in the search UI.
Also applies to: 8-8
80-81: LGTM! Proper state management for debounced search.The two-state pattern (immediate
searchQueryand debounceddebouncedSearch) is the correct approach for implementing search with debounce.
103-111: LGTM! Solid debounce implementation.The 500ms debounce with page reset is well-implemented:
- Proper cleanup prevents memory leaks
- Resetting to page 1 on search ensures users see the first page of results
- Timer delay is appropriate for search UX
117-117: LGTM! Correct API integration with proper dependencies.The implementation correctly:
- Passes the debounced search term (not the immediate value) to the API
- Includes both
currentPageanddebouncedSearchin useEffect dependencies, ensuring data refetch on either changeAlso applies to: 128-128
445-467: LGTM! Excellent UX implementation.The search UI and empty states are well-designed:
- Search input is prominently placed with clear placeholder text
- Icon positioning enhances visual clarity
- Empty state messaging intelligently differentiates between "no search results" vs "no crises detected"
- The conditional messaging at lines 582-600 provides helpful user guidance
Also applies to: 582-600
server/routers/data_feed.py (2)
3-3: LGTM! Correct import for OR-based filtering.The
or_import from SQLAlchemy is properly used in the search filter implementation.
85-88: LGTM! Proper FastAPI parameter definition.The search parameter is correctly defined with appropriate defaults and description. The docstring accurately reflects the new search capability.
Note: The static analysis warning about
Depends(get_db)in line 86 is a false positive - this is the standard and correct FastAPI pattern for dependency injection.
- Merged lucide-react imports (Search + Info, X) - Added showDisclaimer state from main - Kept BR-155 search functionality intact
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
client/app/dashboard/data-feed/page.tsx (1)
458-467: Consider adding aria-label for accessibility.The search input would benefit from an explicit
aria-labelto improve screen reader accessibility, especially since the placeholder text may not be announced consistently across all screen readers.Apply this diff to add the aria-label:
<Input type="text" placeholder="Search by name, location, or disaster type..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} className="pl-9" + aria-label="Search crises by name, location, or disaster type" />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
client/app/dashboard/data-feed/page.tsx(6 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
client/app/dashboard/data-feed/page.tsx (1)
client/lib/api-client.ts (1)
getWeeklyCrises(95-130)
🔇 Additional comments (4)
client/app/dashboard/data-feed/page.tsx (4)
4-4: LGTM!The new imports are correctly added and used in the search functionality implementation.
Also applies to: 8-8
104-112: LGTM!The debounce implementation is correct with proper cleanup and an appropriate 500ms delay. Resetting to page 1 on search change provides good UX.
118-118: LGTM!The crisis fetch integration correctly passes the debounced search term to the API and includes it in the useEffect dependencies to trigger re-fetching when the search changes.
Also applies to: 129-129
583-601: LGTM!The conditional empty state rendering correctly differentiates between "no search results" and "no crises detected," providing clear, helpful feedback to users.
| const [lastUpdated, setLastUpdated] = useState<Date | null>(null) | ||
| const [searchQuery, setSearchQuery] = useState("") | ||
| const [debouncedSearch, setDebouncedSearch] = useState("") | ||
| const [showDisclaimer, setShowDisclaimer] = useState(true) |
There was a problem hiding this comment.
Remove unused state variable.
The showDisclaimer state is declared but never used anywhere in the component. This should be removed to keep the code clean.
Apply this diff to remove the unused state:
const [searchQuery, setSearchQuery] = useState("")
const [debouncedSearch, setDebouncedSearch] = useState("")
- const [showDisclaimer, setShowDisclaimer] = useState(true)Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In client/app/dashboard/data-feed/page.tsx around line 82, the component
declares an unused state variable `showDisclaimer` via useState which is never
referenced; remove the entire declaration (importing useState is optional) and
any related unused imports so the component no longer defines or references
`showDisclaimer`, and tidy up imports if useState becomes unused.
- Merged Search import from BR-155 with Info, X from main - Kept all state variables (searchQuery, debouncedSearch, showDisclaimer)
🚀 Preview Deployment Ready!Backend: https://api-kamalesh-br-155-frontend-add-s.private.bluerelief.app Commit: 🔐 AuthenticationDemo Login: Click "Google Sign In" → Use demo auth (no Google account needed) ✨ Version Bump PredictionWhen this PR is merged to main, the version will be bumped: 1.48.0 → 1.48.1 (patch) 💡 How to change the version bump type
Preview will be automatically deleted when PR is closed or merged. |
🚀 Preview Deployment Ready!Backend: https://api-kamalesh-br-155-frontend-add-s.private.bluerelief.app Commit: 🔐 AuthenticationDemo Login: Click "Google Sign In" → Use demo auth (no Google account needed) ✨ Version Bump PredictionWhen this PR is merged to main, the version will be bumped: 1.48.0 → 1.48.1 (patch) 💡 How to change the version bump type
Preview will be automatically deleted when PR is closed or merged. |
Backend: Add search query parameter to /weekly-crises endpoint
Frontend: Add search input with 500ms debounce
API Client: Updated getWeeklyCrises() to accept search param
Summary by CodeRabbit