Files
cannaiq/findadispo/backend/routes/search_routes.py
Kelly a0f8d3911c feat: Add Findagram and FindADispo consumer frontends
- Add findagram.co React frontend with product search, brands, categories
- Add findadispo.com React frontend with dispensary locator
- Wire findagram to backend /api/az/* endpoints
- Update category/brand links to route to /products with filters
- Add k8s manifests for both frontends
- Add multi-domain user support migrations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 16:10:15 -07:00

202 lines
5.4 KiB
Python

from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from sqlalchemy.sql import func
from pydantic import BaseModel
from database import get_db
from auth import get_current_active_user
from models import User, SavedSearch
router = APIRouter(prefix="/searches", tags=["Saved Searches"])
class SavedSearchCreate(BaseModel):
name: str
query: str
filters: Optional[dict] = None
results_count: Optional[int] = 0
class SavedSearchUpdate(BaseModel):
name: Optional[str] = None
filters: Optional[dict] = None
results_count: Optional[int] = None
class SavedSearchResponse(BaseModel):
id: int
name: str
query: str
filters: Optional[dict]
results_count: int
last_used: str
class Config:
from_attributes = True
@router.get("/", response_model=List[SavedSearchResponse])
def get_saved_searches(
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
"""Get all saved searches for the current user"""
searches = db.query(SavedSearch).filter(
SavedSearch.user_id == current_user.id
).order_by(SavedSearch.last_used.desc()).all()
return [
SavedSearchResponse(
id=s.id,
name=s.name,
query=s.query,
filters=s.filters,
results_count=s.results_count,
last_used=s.last_used.isoformat() if s.last_used else ""
)
for s in searches
]
@router.post("/", response_model=SavedSearchResponse, status_code=status.HTTP_201_CREATED)
def create_saved_search(
search_data: SavedSearchCreate,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
"""Create a new saved search"""
search = SavedSearch(
user_id=current_user.id,
name=search_data.name,
query=search_data.query,
filters=search_data.filters,
results_count=search_data.results_count
)
db.add(search)
db.commit()
db.refresh(search)
return SavedSearchResponse(
id=search.id,
name=search.name,
query=search.query,
filters=search.filters,
results_count=search.results_count,
last_used=search.last_used.isoformat() if search.last_used else ""
)
@router.get("/{search_id}", response_model=SavedSearchResponse)
def get_saved_search(
search_id: int,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
"""Get a specific saved search"""
search = db.query(SavedSearch).filter(
SavedSearch.id == search_id,
SavedSearch.user_id == current_user.id
).first()
if not search:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Saved search not found"
)
return SavedSearchResponse(
id=search.id,
name=search.name,
query=search.query,
filters=search.filters,
results_count=search.results_count,
last_used=search.last_used.isoformat() if search.last_used else ""
)
@router.put("/{search_id}", response_model=SavedSearchResponse)
def update_saved_search(
search_id: int,
search_update: SavedSearchUpdate,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
"""Update a saved search"""
search = db.query(SavedSearch).filter(
SavedSearch.id == search_id,
SavedSearch.user_id == current_user.id
).first()
if not search:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Saved search not found"
)
update_data = search_update.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(search, field, value)
db.commit()
db.refresh(search)
return SavedSearchResponse(
id=search.id,
name=search.name,
query=search.query,
filters=search.filters,
results_count=search.results_count,
last_used=search.last_used.isoformat() if search.last_used else ""
)
@router.post("/{search_id}/use")
def mark_search_used(
search_id: int,
results_count: Optional[int] = None,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
"""Mark a saved search as used (updates last_used timestamp)"""
search = db.query(SavedSearch).filter(
SavedSearch.id == search_id,
SavedSearch.user_id == current_user.id
).first()
if not search:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Saved search not found"
)
search.last_used = func.now()
if results_count is not None:
search.results_count = results_count
db.commit()
return {"message": "Search marked as used"}
@router.delete("/{search_id}")
def delete_saved_search(
search_id: int,
current_user: User = Depends(get_current_active_user),
db: Session = Depends(get_db)
):
"""Delete a saved search"""
search = db.query(SavedSearch).filter(
SavedSearch.id == search_id,
SavedSearch.user_id == current_user.id
).first()
if not search:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Saved search not found"
)
db.delete(search)
db.commit()
return {"message": "Saved search deleted"}