vistas de ciudadano, escalar animaciones de mascota, implementacion de chatbot para concientizacion, modificacion de datos de ciudadano, modificacion de vista principal
This commit is contained in:
132
backend/app/api/incidents.py
Normal file
132
backend/app/api/incidents.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""Reportes ciudadanos sobre unidades (incidents)."""
|
||||
import uuid
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile
|
||||
|
||||
from app.core.deps import get_current_user
|
||||
from app.core.supabase_client import supabase_admin
|
||||
from app.schemas.incidents import (
|
||||
IncidentOut,
|
||||
UnitPublic,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/incidents", tags=["incidents"])
|
||||
|
||||
BUCKET = "incident-photos"
|
||||
VALID_CATEGORIES = {"derrame", "dano_propiedad", "conducta", "no_recoleccion", "otro"}
|
||||
|
||||
|
||||
@router.get("/units", response_model=list[UnitPublic])
|
||||
def list_units(_user: dict = Depends(get_current_user)):
|
||||
"""Lista unidades activas para que el ciudadano elija al reportar."""
|
||||
try:
|
||||
res = (
|
||||
supabase_admin.table("units")
|
||||
.select("id, plate, status")
|
||||
.eq("status", "active")
|
||||
.order("id")
|
||||
.execute()
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error al listar unidades: {e}")
|
||||
|
||||
return [UnitPublic(**r) for r in (res.data or [])]
|
||||
|
||||
|
||||
def _upload_photo(user_id: str, photo: UploadFile) -> str:
|
||||
ext = (photo.filename or "").rsplit(".", 1)[-1].lower() or "jpg"
|
||||
if ext not in {"jpg", "jpeg", "png", "webp"}:
|
||||
ext = "jpg"
|
||||
path = f"{user_id}/{uuid.uuid4().hex}.{ext}"
|
||||
|
||||
content = photo.file.read()
|
||||
content_type = photo.content_type or f"image/{ext}"
|
||||
|
||||
try:
|
||||
supabase_admin.storage.from_(BUCKET).upload(
|
||||
path=path,
|
||||
file=content,
|
||||
file_options={"content-type": content_type, "upsert": "false"},
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error al subir foto: {e}")
|
||||
|
||||
try:
|
||||
public = supabase_admin.storage.from_(BUCKET).get_public_url(path)
|
||||
return public if isinstance(public, str) else str(public)
|
||||
except Exception:
|
||||
return path
|
||||
|
||||
|
||||
@router.post("", response_model=IncidentOut, status_code=201)
|
||||
async def create_incident(
|
||||
category: str = Form(...),
|
||||
description: str = Form(...),
|
||||
unit_id: Optional[int] = Form(None),
|
||||
photo: Optional[UploadFile] = File(None),
|
||||
current_user: dict = Depends(get_current_user),
|
||||
):
|
||||
if category not in VALID_CATEGORIES:
|
||||
raise HTTPException(status_code=400, detail="Categoría inválida")
|
||||
if len(description.strip()) < 3:
|
||||
raise HTTPException(status_code=400, detail="Descripción demasiado corta")
|
||||
|
||||
user_id = current_user["user_id"]
|
||||
photo_url: Optional[str] = None
|
||||
if photo is not None and photo.filename:
|
||||
photo_url = _upload_photo(user_id, photo)
|
||||
|
||||
payload = {
|
||||
"user_id": user_id,
|
||||
"unit_id": unit_id,
|
||||
"category": category,
|
||||
"description": description.strip(),
|
||||
"photo_url": photo_url,
|
||||
}
|
||||
try:
|
||||
res = supabase_admin.table("incidents").insert(payload).execute()
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error al guardar reporte: {e}")
|
||||
|
||||
row = (res.data or [{}])[0]
|
||||
return IncidentOut(
|
||||
id=row.get("id"),
|
||||
user_id=row.get("user_id"),
|
||||
unit_id=row.get("unit_id"),
|
||||
category=row.get("category"),
|
||||
description=row.get("description"),
|
||||
photo_url=row.get("photo_url"),
|
||||
status=row.get("status") or "open",
|
||||
created_at=row.get("created_at") and str(row["created_at"]),
|
||||
)
|
||||
|
||||
|
||||
@router.get("/me", response_model=list[IncidentOut])
|
||||
def my_incidents(current_user: dict = Depends(get_current_user)):
|
||||
try:
|
||||
res = (
|
||||
supabase_admin.table("incidents")
|
||||
.select("*")
|
||||
.eq("user_id", current_user["user_id"])
|
||||
.order("created_at", desc=True)
|
||||
.execute()
|
||||
)
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=f"Error al listar reportes: {e}")
|
||||
|
||||
out: list[IncidentOut] = []
|
||||
for row in res.data or []:
|
||||
out.append(
|
||||
IncidentOut(
|
||||
id=row.get("id"),
|
||||
user_id=row.get("user_id"),
|
||||
unit_id=row.get("unit_id"),
|
||||
category=row.get("category"),
|
||||
description=row.get("description"),
|
||||
photo_url=row.get("photo_url"),
|
||||
status=row.get("status") or "open",
|
||||
created_at=row.get("created_at") and str(row["created_at"]),
|
||||
)
|
||||
)
|
||||
return out
|
||||
Reference in New Issue
Block a user