- Criadas APIs para Health (métricas de saúde) * Registrar peso, altura, % gordura, medidas * Histórico completo de medições * Estatísticas e resumo - Criadas APIs para Tasks (tarefas) * Criar, editar e deletar tarefas * Filtros por status e data * Estatísticas detalhadas * Prioridades (baixa, média, alta) - Frontend implementado: * Página Health.tsx - registro de métricas * Página Tasks.tsx - gerenciamento de tarefas * Página Progress.tsx - visualização de progresso * Dashboard integrado com estatísticas reais - Schemas e modelos atualizados - Todas as funcionalidades testadas e operacionais
219 lines
6.0 KiB
Python
219 lines
6.0 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
|
from sqlalchemy.orm import Session
|
|
from typing import List, Optional
|
|
from datetime import date
|
|
|
|
from app.core.database import get_db
|
|
from app.core.security import decode_access_token
|
|
from app.models.task import Task
|
|
from app.schemas.task import TaskCreate, TaskResponse, TaskUpdate
|
|
|
|
router = APIRouter()
|
|
security = HTTPBearer()
|
|
|
|
def get_current_user_id(credentials: HTTPAuthorizationCredentials = Depends(security)) -> str:
|
|
"""Extrai user_id do token JWT"""
|
|
token = credentials.credentials
|
|
payload = decode_access_token(token)
|
|
if not payload:
|
|
raise HTTPException(status_code=401, detail="Token inválido")
|
|
return payload.get("sub")
|
|
|
|
@router.post("/", response_model=TaskResponse, status_code=status.HTTP_201_CREATED)
|
|
async def create_task(
|
|
task_data: TaskCreate,
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Criar nova tarefa"""
|
|
new_task = Task(
|
|
user_id=user_id,
|
|
title=task_data.title,
|
|
description=task_data.description,
|
|
priority=task_data.priority,
|
|
status=task_data.status,
|
|
due_date=task_data.due_date,
|
|
due_time=task_data.due_time,
|
|
category_id=task_data.category_id
|
|
)
|
|
|
|
db.add(new_task)
|
|
db.commit()
|
|
db.refresh(new_task)
|
|
|
|
return new_task
|
|
|
|
@router.get("/", response_model=List[TaskResponse])
|
|
async def list_tasks(
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db),
|
|
status_filter: Optional[str] = None,
|
|
include_archived: bool = False
|
|
):
|
|
"""Listar todas as tarefas do usuário"""
|
|
query = db.query(Task).filter(Task.user_id == user_id)
|
|
|
|
if not include_archived:
|
|
query = query.filter(Task.is_archived == False)
|
|
|
|
if status_filter:
|
|
query = query.filter(Task.status == status_filter)
|
|
|
|
tasks = query.order_by(Task.due_date.asc()).all()
|
|
|
|
return tasks
|
|
|
|
@router.get("/today", response_model=List[TaskResponse])
|
|
async def get_today_tasks(
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Obter tarefas de hoje"""
|
|
today = date.today()
|
|
tasks = db.query(Task).filter(
|
|
Task.user_id == user_id,
|
|
Task.due_date == today,
|
|
Task.is_archived == False
|
|
).order_by(Task.due_time.asc()).all()
|
|
|
|
return tasks
|
|
|
|
@router.get("/{task_id}", response_model=TaskResponse)
|
|
async def get_task(
|
|
task_id: str,
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Obter tarefa específica"""
|
|
task = db.query(Task).filter(
|
|
Task.id == task_id,
|
|
Task.user_id == user_id
|
|
).first()
|
|
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
|
|
|
|
return task
|
|
|
|
@router.put("/{task_id}", response_model=TaskResponse)
|
|
async def update_task(
|
|
task_id: str,
|
|
task_data: TaskUpdate,
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Atualizar tarefa"""
|
|
task = db.query(Task).filter(
|
|
Task.id == task_id,
|
|
Task.user_id == user_id
|
|
).first()
|
|
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
|
|
|
|
# Atualizar campos
|
|
update_data = task_data.dict(exclude_unset=True)
|
|
for field, value in update_data.items():
|
|
setattr(task, field, value)
|
|
|
|
db.commit()
|
|
db.refresh(task)
|
|
|
|
return task
|
|
|
|
@router.patch("/{task_id}/status")
|
|
async def update_task_status(
|
|
task_id: str,
|
|
status: str,
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Atualizar status da tarefa"""
|
|
task = db.query(Task).filter(
|
|
Task.id == task_id,
|
|
Task.user_id == user_id
|
|
).first()
|
|
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
|
|
|
|
task.status = status
|
|
db.commit()
|
|
|
|
return {"message": "Status atualizado", "status": status}
|
|
|
|
@router.delete("/{task_id}")
|
|
async def delete_task(
|
|
task_id: str,
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Deletar tarefa"""
|
|
task = db.query(Task).filter(
|
|
Task.id == task_id,
|
|
Task.user_id == user_id
|
|
).first()
|
|
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail="Tarefa não encontrada")
|
|
|
|
db.delete(task)
|
|
db.commit()
|
|
|
|
return {"message": "Tarefa deletada com sucesso"}
|
|
|
|
@router.get("/stats/summary")
|
|
async def get_task_stats(
|
|
user_id: str = Depends(get_current_user_id),
|
|
db: Session = Depends(get_db)
|
|
):
|
|
"""Estatísticas de tarefas"""
|
|
from sqlalchemy import func
|
|
|
|
total_tasks = db.query(func.count(Task.id)).filter(
|
|
Task.user_id == user_id,
|
|
Task.is_archived == False
|
|
).scalar()
|
|
|
|
pending = db.query(func.count(Task.id)).filter(
|
|
Task.user_id == user_id,
|
|
Task.status == "pending",
|
|
Task.is_archived == False
|
|
).scalar()
|
|
|
|
in_progress = db.query(func.count(Task.id)).filter(
|
|
Task.user_id == user_id,
|
|
Task.status == "in_progress",
|
|
Task.is_archived == False
|
|
).scalar()
|
|
|
|
completed = db.query(func.count(Task.id)).filter(
|
|
Task.user_id == user_id,
|
|
Task.status == "completed",
|
|
Task.is_archived == False
|
|
).scalar()
|
|
|
|
today = date.today()
|
|
today_tasks = db.query(func.count(Task.id)).filter(
|
|
Task.user_id == user_id,
|
|
Task.due_date == today,
|
|
Task.is_archived == False
|
|
).scalar()
|
|
|
|
today_completed = db.query(func.count(Task.id)).filter(
|
|
Task.user_id == user_id,
|
|
Task.due_date == today,
|
|
Task.status == "completed"
|
|
).scalar()
|
|
|
|
return {
|
|
"total_tasks": total_tasks,
|
|
"pending": pending,
|
|
"in_progress": in_progress,
|
|
"completed": completed,
|
|
"today_tasks": today_tasks,
|
|
"today_completed": today_completed
|
|
}
|
|
|