mirror of
https://github.com/escalante29/healthy-fit.git
synced 2026-03-21 11:08:48 +01:00
Migrate frontend to TypeScript and extend user profile
Converted frontend codebase from JavaScript to TypeScript, including pages, components, and context. Added new layout and UI kit components. Updated backend user model and schemas to support profile fields (firstname, lastname, age, gender, height, weight, unit_preference) and added endpoints for reading/updating current user. Introduced food log listing endpoint and migration script for user table. Updated dependencies and build configs for TypeScript and Tailwind v4.
This commit is contained in:
@@ -61,9 +61,7 @@ class NutritionModule(dspy.Module):
|
||||
pred = self.extract(description=description)
|
||||
|
||||
# Assertion: Check Macro Consistency
|
||||
calc_cals = (
|
||||
(pred.nutritional_info.protein * 4) + (pred.nutritional_info.carbs * 4) + (pred.nutritional_info.fats * 9)
|
||||
)
|
||||
# calc_cals calculation removed as dspy.Suggest is disabled
|
||||
|
||||
# dspy.Suggest is not available in dspy>=3.1.0
|
||||
# dspy.Suggest(
|
||||
@@ -78,9 +76,7 @@ class NutritionModule(dspy.Module):
|
||||
pred = self.analyze_image(image=image, description=description)
|
||||
|
||||
# Assertion: Check Macro Consistency
|
||||
calc_cals = (
|
||||
(pred.nutritional_info.protein * 4) + (pred.nutritional_info.carbs * 4) + (pred.nutritional_info.fats * 9)
|
||||
)
|
||||
# calc_cals calculation removed as dspy.Suggest is disabled
|
||||
|
||||
# dspy.Suggest is not available in dspy>=3.1.0
|
||||
# dspy.Suggest(
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import litellm
|
||||
import dspy
|
||||
from typing import Any
|
||||
|
||||
import litellm
|
||||
from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile
|
||||
from pydantic import BaseModel
|
||||
from sqlmodel import Session
|
||||
@@ -70,3 +69,25 @@ def log_food(
|
||||
session.commit()
|
||||
session.refresh(food_log)
|
||||
return food_log
|
||||
|
||||
|
||||
@router.get("/logs", response_model=list[FoodLog])
|
||||
def read_logs(
|
||||
current_user: deps.CurrentUser,
|
||||
session: Session = Depends(deps.get_session),
|
||||
skip: int = 0,
|
||||
limit: int = 100,
|
||||
) -> Any:
|
||||
"""
|
||||
Get food logs for current user.
|
||||
"""
|
||||
from sqlmodel import select
|
||||
|
||||
statement = (
|
||||
select(FoodLog)
|
||||
.where(FoodLog.user_id == current_user.id)
|
||||
.order_by(FoodLog.timestamp.desc())
|
||||
.offset(skip)
|
||||
.limit(limit)
|
||||
)
|
||||
return session.exec(statement).all()
|
||||
|
||||
@@ -6,7 +6,7 @@ from sqlmodel import Session, select
|
||||
from app.api import deps
|
||||
from app.core import security
|
||||
from app.models.user import User
|
||||
from app.schemas.user import UserCreate, UserRead
|
||||
from app.schemas.user import UserCreate, UserRead, UserUpdate
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -36,3 +36,31 @@ def create_user(
|
||||
session.commit()
|
||||
session.refresh(user)
|
||||
return user
|
||||
|
||||
|
||||
@router.get("/me", response_model=UserRead)
|
||||
def read_user_me(
|
||||
current_user: deps.CurrentUser,
|
||||
) -> Any:
|
||||
"""
|
||||
Get current user.
|
||||
"""
|
||||
return current_user
|
||||
|
||||
|
||||
@router.put("/me", response_model=UserRead)
|
||||
def update_user_me(
|
||||
*,
|
||||
session: Session = Depends(deps.get_session),
|
||||
user_in: UserUpdate,
|
||||
current_user: deps.CurrentUser,
|
||||
) -> Any:
|
||||
"""
|
||||
Update own user.
|
||||
"""
|
||||
user_data = user_in.model_dump(exclude_unset=True)
|
||||
current_user.sqlmodel_update(user_data)
|
||||
session.add(current_user)
|
||||
session.commit()
|
||||
session.refresh(current_user)
|
||||
return current_user
|
||||
|
||||
@@ -9,4 +9,14 @@ class User(SQLModel, table=True):
|
||||
username: str = Field(index=True, unique=True)
|
||||
email: str = Field(index=True, unique=True)
|
||||
password_hash: str
|
||||
|
||||
# Profile Info
|
||||
firstname: Optional[str] = None
|
||||
lastname: Optional[str] = None
|
||||
age: Optional[int] = None
|
||||
gender: Optional[str] = None
|
||||
height: Optional[float] = None
|
||||
weight: Optional[float] = None
|
||||
unit_preference: str = Field(default="metric") # "metric" or "imperial"
|
||||
|
||||
created_at: datetime = Field(default_factory=datetime.utcnow)
|
||||
|
||||
@@ -14,9 +14,23 @@ class UserCreate(UserBase):
|
||||
|
||||
class UserRead(UserBase):
|
||||
id: int
|
||||
firstname: Optional[str] = None
|
||||
lastname: Optional[str] = None
|
||||
age: Optional[int] = None
|
||||
gender: Optional[str] = None
|
||||
height: Optional[float] = None
|
||||
weight: Optional[float] = None
|
||||
unit_preference: str = "metric"
|
||||
|
||||
|
||||
class UserUpdate(SQLModel):
|
||||
email: Optional[str] = None
|
||||
username: Optional[str] = None
|
||||
password: Optional[str] = None
|
||||
firstname: Optional[str] = None
|
||||
lastname: Optional[str] = None
|
||||
age: Optional[int] = None
|
||||
gender: Optional[str] = None
|
||||
height: Optional[float] = None
|
||||
weight: Optional[float] = None
|
||||
unit_preference: Optional[str] = None
|
||||
|
||||
32
backend/migrate_user_table.py
Normal file
32
backend/migrate_user_table.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from sqlmodel import Session, text
|
||||
|
||||
from app.db import engine
|
||||
|
||||
|
||||
def migrate():
|
||||
print("Starting migration...")
|
||||
with Session(engine) as session:
|
||||
columns = [
|
||||
("firstname", "VARCHAR"),
|
||||
("lastname", "VARCHAR"),
|
||||
("age", "INTEGER"),
|
||||
("gender", "VARCHAR"),
|
||||
("height", "FLOAT"),
|
||||
("weight", "FLOAT"),
|
||||
("unit_preference", "VARCHAR DEFAULT 'metric'"),
|
||||
]
|
||||
|
||||
for col, type_ in columns:
|
||||
try:
|
||||
print(f"Adding {col}...")
|
||||
# Using "user" with quotes to avoid reserved keyword issues, though SQLModel usually handles it
|
||||
session.exec(text(f'ALTER TABLE "user" ADD COLUMN IF NOT EXISTS {col} {type_}'))
|
||||
session.commit()
|
||||
print(f"Added {col}")
|
||||
except Exception as e:
|
||||
print(f"Error adding {col}: {e}")
|
||||
session.rollback()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
migrate()
|
||||
Reference in New Issue
Block a user