From d2cfa5ae170ac188cd2c261c25f3b458ddbc3e27 Mon Sep 17 00:00:00 2001 From: t0xa Date: Thu, 4 Sep 2025 23:18:20 +0300 Subject: [PATCH] Add template for rendering trainings --- app/api/v1/web.py | 19 ++++++++++++--- app/core/templates/__init__.py | 0 app/core/templates/templates.py | 30 +++++++++++++++++++++++ app/templates/base.html | 2 +- app/templates/trainings.html | 43 +++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 app/core/templates/__init__.py create mode 100644 app/core/templates/templates.py create mode 100644 app/templates/trainings.html diff --git a/app/api/v1/web.py b/app/api/v1/web.py index 0ef8498..a7636fc 100644 --- a/app/api/v1/web.py +++ b/app/api/v1/web.py @@ -2,14 +2,27 @@ from fastapi import APIRouter, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates +from app.core.parsers.obsidian import parse_training_data +from app.core.templates.templates import BaseTemplateResponse + web_router = APIRouter() templates = Jinja2Templates(directory="app/templates") +template_renderer = BaseTemplateResponse(templates) @web_router.get("/", response_class=HTMLResponse) async def home(request: Request): """Home page""" - return templates.TemplateResponse( - "index.html", - {"request": request, "title": "Fitness Parser"} + + return template_renderer.render( + request, + "index.html", + ) + + +@web_router.get("/obsidian/list/", response_class=HTMLResponse) +async def obsidian_list(request: Request): + data = parse_training_data() + return template_renderer.render( + request=request, template_name="trainings.html", context={"trainings": data} ) diff --git a/app/core/templates/__init__.py b/app/core/templates/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/core/templates/templates.py b/app/core/templates/templates.py new file mode 100644 index 0000000..80b668d --- /dev/null +++ b/app/core/templates/templates.py @@ -0,0 +1,30 @@ +from typing import Optional +from fastapi import Request +from fastapi.templating import Jinja2Templates + + +class BaseTemplateResponse: + """Базовый метод для рендеринга Jinja2 темплейтов. + + Нужен в первую очередь для того, чтобы подставлять какие-то дефолтные значения (которые есть + на всех страницах) в переменные темплейтов + + Attributes: + templates: Формат темплейтов, используемых в проекте + """ + def __init__(self, templates: Jinja2Templates): + self.templates = templates + + def render( + self, request: Request, template_name: str, context: Optional[dict] = None + ): + base_context = { + "request": request, + "title": "Fitness stats", + "app_name": "Fitness parser" + } + + if context: + base_context.update(context) + + return self.templates.TemplateResponse(template_name, base_context) diff --git a/app/templates/base.html b/app/templates/base.html index b41ed03..503835c 100644 --- a/app/templates/base.html +++ b/app/templates/base.html @@ -14,7 +14,7 @@ diff --git a/app/templates/trainings.html b/app/templates/trainings.html new file mode 100644 index 0000000..aab5774 --- /dev/null +++ b/app/templates/trainings.html @@ -0,0 +1,43 @@ +{% extends "base.html" %} + +{% block content %} +

Training Sessions

+ +{% if trainings %} +

Total trainings: {{ trainings|length }}

+ + {% for training in trainings %} +
+

Date: {{ training.date }}

+ + {% if training.exercises %} +

Exercises: {{ training.exercises|length }}

+ + {% for exercise in training.exercises %} +
+

{{ exercise.name }}

+ {% if exercise.splitted_weight %} + (Split Weight) + {% endif %} + +
    + {% for approach in exercise.approaches %} +
  • {{ approach.weight }}kg x {{ approach.reps }} reps
  • + {% endfor %} +
+
+ {% endfor %} + + {% else %} +

No exercises recorded

+ {% endif %} +
+ +
+ {% endfor %} + +{% else %} +

No training data available

+{% endif %} + +{% endblock %} \ No newline at end of file