Spaces:
Runtime error
Runtime error
| """ | |
| User API routes. | |
| Provides endpoints for user profile management. | |
| """ | |
| from uuid import UUID | |
| from typing import Optional | |
| from fastapi import APIRouter, HTTPException, status, Depends, File, UploadFile | |
| from sqlmodel import Session, select, func | |
| from datetime import datetime | |
| from src.api.deps import get_current_user_id, get_db | |
| from src.models.user import User | |
| from src.models.todo import Todo, Status | |
| from src.schemas.user import UserResponse, UserProfileUpdateRequest | |
| router = APIRouter() | |
| async def get_profile( | |
| current_user_id: str = Depends(get_current_user_id), | |
| db: Session = Depends(get_db), | |
| ): | |
| """Get current user profile with todo statistics.""" | |
| # Get user | |
| query = select(User).where(User.id == UUID(current_user_id)) | |
| user = db.exec(query).first() | |
| if not user: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail='User not found', | |
| ) | |
| # Get todo statistics | |
| total_todos = db.exec( | |
| select(func.count()).select_from(Todo).where(Todo.user_id == user.id) | |
| ).one() | |
| pending_todos = db.exec( | |
| select(func.count()).select_from(Todo).where( | |
| Todo.user_id == user.id, | |
| Todo.status == Status.PENDING | |
| ) | |
| ).one() | |
| completed_todos = db.exec( | |
| select(func.count()).select_from(Todo).where( | |
| Todo.user_id == user.id, | |
| Todo.status == Status.COMPLETED | |
| ) | |
| ).one() | |
| return { | |
| 'id': str(user.id), | |
| 'name': user.name, | |
| 'email': user.email, | |
| 'avatar_url': user.avatar_url, | |
| 'created_at': user.created_at.isoformat(), | |
| 'updated_at': user.updated_at.isoformat(), | |
| 'stats': { | |
| 'total_todos': total_todos, | |
| 'pending_todos': pending_todos, | |
| 'completed_todos': completed_todos, | |
| } | |
| } | |
| async def update_profile( | |
| profile_data: UserProfileUpdateRequest, | |
| current_user_id: str = Depends(get_current_user_id), | |
| db: Session = Depends(get_db), | |
| ): | |
| """Update current user profile.""" | |
| # Get user | |
| query = select(User).where(User.id == UUID(current_user_id)) | |
| user = db.exec(query).first() | |
| if not user: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail='User not found', | |
| ) | |
| # Update fields | |
| if profile_data.name is not None: | |
| user.name = profile_data.name | |
| user.updated_at = datetime.utcnow() | |
| db.add(user) | |
| db.commit() | |
| db.refresh(user) | |
| return { | |
| 'id': str(user.id), | |
| 'name': user.name, | |
| 'email': user.email, | |
| 'avatar_url': user.avatar_url, | |
| 'created_at': user.created_at.isoformat(), | |
| 'updated_at': user.updated_at.isoformat(), | |
| } | |
| async def upload_avatar( | |
| file: UploadFile = File(...), | |
| current_user_id: str = Depends(get_current_user_id), | |
| db: Session = Depends(get_db), | |
| ): | |
| """Upload user avatar.""" | |
| # Validate file type | |
| allowed_types = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] | |
| if file.content_type not in allowed_types: | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail=f'Invalid file type. Allowed: {", ".join(allowed_types)}', | |
| ) | |
| # Validate file size (5MB max) | |
| MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB | |
| content = await file.read() | |
| if len(content) > MAX_FILE_SIZE: | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail='File too large. Maximum size: 5MB', | |
| ) | |
| # For now, return a placeholder avatar URL | |
| # In production, you would upload to Cloudinary here | |
| from src.core.config import settings | |
| if settings.cloudinary_cloud_name: | |
| # TODO: Implement Cloudinary upload | |
| avatar_url = f"https://ui-avatars.com/api/?name={file.filename}&background=random" | |
| else: | |
| # Use UI Avatars as fallback | |
| query = select(User).where(User.id == UUID(current_user_id)) | |
| user = db.exec(query).first() | |
| avatar_url = f"https://ui-avatars.com/api/?name={user.name}&background=random" | |
| # Update user avatar | |
| query = select(User).where(User.id == UUID(current_user_id)) | |
| user = db.exec(query).first() | |
| if user: | |
| user.avatar_url = avatar_url | |
| user.updated_at = datetime.utcnow() | |
| db.add(user) | |
| db.commit() | |
| return { | |
| 'avatar_url': avatar_url, | |
| 'message': 'Avatar uploaded successfully', | |
| } | |
| __all__ = ['router'] | |