Changeset b3d5fed


Ignore:
Timestamp:
05/05/26 18:06:26 (2 months ago)
Author:
Andrej <asumanovski@…>
Branches:
master
Children:
a8381b1
Parents:
e9a0543
Message:

training graph developed

Location:
frontend
Files:
3 added
4 edited

Legend:

Unmodified
Added
Removed
  • frontend/package-lock.json

    re9a0543 rb3d5fed  
    1515        "@relume_io/relume-ui": "^1.3.1",
    1616        "@tailwindcss/vite": "^4.1.18",
     17        "apexcharts": "^5.10.6",
    1718        "axios": "^1.13.4",
    1819        "daisyui": "^5.5.18",
    1920        "react": "^19.2.0",
     21        "react-apexcharts": "^2.1.0",
    2022        "react-dom": "^19.2.0",
    2123        "react-icons": "^5.5.0",
     
    57245726        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
    57255727      }
     5728    },
     5729    "node_modules/apexcharts": {
     5730      "version": "5.10.6",
     5731      "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-5.10.6.tgz",
     5732      "integrity": "sha512-FJQGbso3iRuOwUYnj0yUhkWeKeJE6aboVol+ae09lsc+lbLMWZqSRbrAWVa/qishLiaeG2icxdvmVkm+9n6kOQ==",
     5733      "license": "SEE LICENSE IN LICENSE"
    57265734    },
    57275735    "node_modules/argparse": {
     
    69116919      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
    69126920      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
    6913       "dev": true,
    69146921      "license": "MIT"
    69156922    },
     
    72807287      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
    72817288      "license": "MIT"
     7289    },
     7290    "node_modules/loose-envify": {
     7291      "version": "1.4.0",
     7292      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
     7293      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
     7294      "license": "MIT",
     7295      "dependencies": {
     7296        "js-tokens": "^3.0.0 || ^4.0.0"
     7297      },
     7298      "bin": {
     7299        "loose-envify": "cli.js"
     7300      }
    72827301    },
    72837302    "node_modules/lru-cache": {
     
    93539372      "license": "ISC"
    93549373    },
     9374    "node_modules/object-assign": {
     9375      "version": "4.1.1",
     9376      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
     9377      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
     9378      "license": "MIT",
     9379      "engines": {
     9380        "node": ">=0.10.0"
     9381      }
     9382    },
    93559383    "node_modules/optionator": {
    93569384      "version": "0.9.4",
     
    95159543      }
    95169544    },
     9545    "node_modules/prop-types": {
     9546      "version": "15.8.1",
     9547      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
     9548      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
     9549      "license": "MIT",
     9550      "dependencies": {
     9551        "loose-envify": "^1.4.0",
     9552        "object-assign": "^4.1.1",
     9553        "react-is": "^16.13.1"
     9554      }
     9555    },
     9556    "node_modules/prop-types/node_modules/react-is": {
     9557      "version": "16.13.1",
     9558      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
     9559      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
     9560      "license": "MIT"
     9561    },
    95179562    "node_modules/proxy-from-env": {
    95189563      "version": "1.1.0",
     
    95389583      "engines": {
    95399584        "node": ">=0.10.0"
     9585      }
     9586    },
     9587    "node_modules/react-apexcharts": {
     9588      "version": "2.1.0",
     9589      "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-2.1.0.tgz",
     9590      "integrity": "sha512-xrmeTKRKHh3cvvLc8SasqFjlOgIqGpyHc81qjnRtcjUM0Fu7qEjgVRWGPokGFjqhwRZVgEym8zmuEyYr5LMYIg==",
     9591      "license": "SEE LICENSE IN LICENSE",
     9592      "dependencies": {
     9593        "prop-types": "^15.8.1"
     9594      },
     9595      "peerDependencies": {
     9596        "apexcharts": ">=5.10.1",
     9597        "react": ">=16.8.0"
    95409598      }
    95419599    },
  • frontend/package.json

    re9a0543 rb3d5fed  
    1717    "@relume_io/relume-ui": "^1.3.1",
    1818    "@tailwindcss/vite": "^4.1.18",
     19    "apexcharts": "^5.10.6",
    1920    "axios": "^1.13.4",
    2021    "daisyui": "^5.5.18",
    2122    "react": "^19.2.0",
     23    "react-apexcharts": "^2.1.0",
    2224    "react-dom": "^19.2.0",
    2325    "react-icons": "^5.5.0",
  • frontend/src/pages/Dashboard/pages/Training/TrainingTracking.jsx

    re9a0543 rb3d5fed  
    22import { useNavigate } from "react-router-dom";
    33import api from "../../../../api/axios";
    4 import graphPlaceholder from "../../../../assets/graph-placeholder.svg";
    54
    65import TrainingTrackingHeader from "./components/TrainingTrackingHeader.jsx";
     
    103102        onAddSession={() => navigate("/dashboard/training/sessions/new")}
    104103      />
    105       <TrainingProgressCard graphSrc={graphPlaceholder} />
     104      <TrainingProgressCard sessions={sessions} />
    106105      <TrainingSessionsTable
    107106        columns={columns}
  • frontend/src/pages/Dashboard/pages/Training/components/TrainingProgressCard.jsx

    re9a0543 rb3d5fed  
    1 import React from "react";
     1import React, { useMemo, useState } from "react";
    22
    3 const TrainingProgressCard = ({ graphSrc }) => {
     3import TimeRangeToggle from "../../../../../components/graphs/TimeRangeToggle.jsx";
     4import PercentChangeAreaChart from "../../../../../components/graphs/PercentChangeAreaChart.jsx";
     5import { percentChangeSeries, sumByTimeBucket } from "../../../../../utils/timeSeries.js";
     6
     7const TrainingProgressCard = ({ sessions }) => {
     8  const [range, setRange] = useState("weekly");
     9
     10  const points = useMemo(() => {
     11    const buckets = sumByTimeBucket(
     12      sessions,
     13      range,
     14      (s) => s.date,
     15      (s) => s.calories
     16    );
     17    return percentChangeSeries(buckets);
     18  }, [range, sessions]);
     19
     20  const latest = points?.length ? points[points.length - 1] : null;
     21  const latestPct = latest ? Number(latest.value ?? 0) : 0;
     22  const latestBase = latest ? Number(latest.base ?? 0) : 0;
     23
    424  return (
    525    <div className="card bg-base-200 border border-base-300">
     
    727        <div className="flex items-center justify-between gap-4">
    828          <h2 className="card-title">Progress</h2>
    9           <span className="badge badge-ghost">Graph placeholder</span>
     29          <div className="flex items-center gap-3">
     30            <span className="badge badge-ghost">
     31              {latestPct >= 0 ? "+" : ""}
     32              {latestPct.toFixed(1)}% (last)
     33            </span>
     34            <TimeRangeToggle value={range} onChange={setRange} />
     35          </div>
    1036        </div>
    11         <div className="mt-4 w-full overflow-hidden rounded-xl border border-base-300 bg-base-100">
    12           <img
    13             src={graphSrc}
    14             alt="Training progress graph placeholder"
    15             className="block h-65 w-full object-cover"
    16           />
     37
     38        <div className="mt-4 w-full overflow-hidden rounded-xl border border-base-300 bg-base-100 p-2">
     39          {points.length < 2 ? (
     40            <div className="flex h-65 items-center justify-center text-sm opacity-70">
     41              Add at least 2 sessions to see % change.
     42            </div>
     43          ) : (
     44            <PercentChangeAreaChart
     45              points={points}
     46              granularity={range}
     47              height={260}
     48            />
     49          )}
     50        </div>
     51
     52        <div className="mt-2 text-xs opacity-70">
     53          Showing percentage change in calories burned per {range} bucket. Latest bucket total: {Math.round(latestBase)}.
    1754        </div>
    1855      </div>
Note: See TracChangeset for help on using the changeset viewer.