0% found this document useful (0 votes)
2 views39 pages

Fitness App Main Menu Interface

The document is a Delphi unit for a fitness application main menu, defining a form class with various UI components and event handlers. It includes methods for creating dynamic user interfaces, handling user interactions, and managing data related to workouts, meals, and user profiles. The form features navigation buttons, summary cards, and quick action buttons to enhance user experience.

Uploaded by

gustaveisenberg2
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views39 pages

Fitness App Main Menu Interface

The document is a Delphi unit for a fitness application main menu, defining a form class with various UI components and event handlers. It includes methods for creating dynamic user interfaces, handling user interactions, and managing data related to workouts, meals, and user profiles. The form features navigation buttons, summary cards, and quick action buttons to enhance user experience.

Uploaded by

gustaveisenberg2
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

unit frmMainMenu_u;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, DateUtils, ExtCtrls, dmFitness_u, Grids, DBGrids,
Math,DB,
//forms
frmWorkouts_u,
frmUserProfile_u,
frmSports_u,
frmProgress_u,
frmNutrition_u;

type
TfrmMainMenu = class(TForm)
procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormResize(Sender: TObject);
private
lblTitle, lblWelcome : TLabel;

arrNavButtons : array of TButton;

arrPnlCards : array of TPanel;


arrCardPaintBoxes : array of TPaintBox;
arrLblCardValue : array of TLabel;
arrCardTarget : array of Integer; //animated goal perc 0..100
arrCardCurrent : array of Integer;//animated current perc

TimerFade : TTimer;
TimerSlide : TTimer;
TimerRing : TTimer;

iAnimStep : integer;
iCurrUserID : integer;

pnlCenter : TPanel;
pnlRight : TPanel;
pnlLeft : TPanel;
bFlag : boolean;
//shortcut buttons
btnQuickWorkout : TButton;
btnQuickMeal : TButton;
btnQuickWeighIn : TButton;

lblCalToday : TLabel;
lblWorkoutsWeek : TLabel;
lblSportsMonth : TLabel;

memRecent : TMemo;

procedure FormClose(Sender : TObject; var Action: TCloseAction);


procedure OnNavButtonClick(Sender : TObject);
procedure OnNavButtonMouseEnter(Sender : TObject);
procedure OnNavButtonMouseLeave(Sender : TObject);
procedure OnPaintBoxPaint(Sender : TObject);
procedure TimerFadeTick(Sender : TObject);
procedure TimerSlideTick(Sender : TObject);
procedure TimerRingTick(Sender : TObject);

//Helping procedure/Functions
procedure CreateDynamicUI;
procedure StartEntryAnim;
procedure SetupCardTargets; //read DB set CardTarget

function CountWorkoutLast7Days (UserID : Integer): Integer;


function CaloriesToday (UserID: Integer): Integer;
function SportThsMonth (UserID: Integer) : Integer;

procedure CreateCenterPanel;

procedure CreateQuickActions;
procedure CreateSnapshotLabels;
procedure CreateRecentActivity;
procedure RefreshDashboard;
procedure PositionCenterControls;
procedure QuickActionClick(Sender: TObject);

procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);


{ Private declarations }
public

constructor Create(AOwner : TComponent); override;


procedure SetCurrentUser(UserID: Integer);
{ Public declarations }
end;

var
frmMainMenu: TfrmMainMenu;

const
arrNavCaptions : array [0..5] of string = (
'Workouts',
'Nutrition',
'Sports',
'Progress',
'Profile',
'Log out'
);

implementation

{$R *.dfm}

{-------------- Helper: DB aclculations --------------}

function [Link](UserID: Integer): Integer;


var
iPosMealSaved, iPosMealSavedItems, iPosFoodsSaved : integer;
iMealID : integer;
dtToday : TDateTime;
rQuantity : Double;
rFoodCalories : Double;
begin
Result := 0;

if NOT Assigned(dmFitness) then


begin
Exit;
end;

dtToday := Date;

//Each meal for user today, calc sum calories


with dmFitness do
begin
[Link];
[Link];

try
[Link];

while NOT [Link] do


begin

if (tblMeals['UserID'] = UserID) AND


(Trunc(tblMeals['MealDate']) = Trunc(dtToday)) then
begin
iMealID := tblMeals['MealID'];

with dmFitness do
begin
[Link];

while NOT [Link] do


begin

if tblMealItems['MealID'] = iMealID then


begin
rQuantity := tblMealItems['Quantity'];

//Find food row


with dmFitness do
begin
if [Link]('FoodID',tblFoods['FoodID'],[]) then
begin
rFoodCalories := tblFoods['Calories'];
Result := Result + Round(rFoodCalories* rQuantity)

end;//end if
end;//end with foods
end;// end if

[Link];
end;
end;
end;
[Link];
end;
finally
[Link]
end;
end;
end;

function TfrmMainMenu.CountWorkoutLast7Days(UserID : integer): integer;


var
iSavedPos : integer;
SevenDayDate : TDateTime;
begin
Result := 0;
with dmFitness do
begin
if NOT [Link] then
[Link];
if NOT Assigned(dmFitness) then
Exit;

SevenDayDate := Date - 7;

with dmFitness do
begin
[Link];

try
iSavedPos := [Link];
[Link];

while NOT [Link] do


begin

if (tblWorkouts['UserID'] = UserID) AND (tblWorkouts['WorkoutDate']


>= SevenDayDate)then
Inc(Result);
[Link];
end;//end with

//Restore pos if possible


if [Link] > 0 then
[Link];

finally
[Link];

end;//end try

end;//end with
end;
end;

constructor [Link](AOwner: TComponent);


begin
inherited Create(AOwner);

//Call SetCurrentUser after login


iCurrUserID := -1;

//form Properties for fade anim


with Self do
begin
BorderStyle := bsSizeable;
Position := poScreenCenter;
Caption := 'Fitness App - Dashboard';
end;

//When closed
OnClose := FormClose;

end;

procedure [Link];
begin
// center panel
if Assigned(pnlCenter) AND Assigned(pnlRight) AND Assigned(pnlLeft) then
Exit;

if NOT Assigned(pnlLeft) then


begin
pnlLeft := [Link](Self);
[Link] := Self;
[Link] := bvNone;
[Link] := '';
[Link] := clBtnFace;
[Link] := True;
end;

if NOT Assigned(pnlRight) then


begin
pnlRight := [Link](Self);
[Link] := Self;
[Link] := bvNone;
[Link] := '';
[Link] := clBtnFace;
[Link] := True; // reduce flicker
end;

if NOT Assigned(pnlCenter) then


begin
pnlCenter := [Link](Self);
[Link] := Self;
[Link] := alNone;
[Link] := bvNone;
[Link] := '';
[Link] := clWhite;
[Link] := bsNone;
end;

[Link] := alNone
;
[Link] := 180;
[Link] := alNone;
[Link] := 280;

CreateQuickActions;
CreateSnapshotLabels;
CreateRecentActivity;

[Link] := 100;
[Link] := True;
[Link] := FormKeyDown;

end;

procedure [Link];
var
i : integer;
btn : TButton;
pnlCard : TPanel;
paintbx : TPaintBox;
lblval : TLabel;
iContainerTop : integer;
begin
//Title label
lblTitle := [Link](Self);
with lblTitle do
begin
Parent := Self;
Caption := 'Framesby Fitness Program';
[Link] := 24;
[Link] := [fsBold];
Left := -800;
Top := 20;
AutoSize := True;
end;

//Welcome Label
lblWelcome := [Link](Self);
with lblWelcome do
begin
Parent := Self;
Caption := 'Welcome!';
[Link] := 14;
Left := [Link] + 200;
Top := 60;
AutoSize := True;
end;

//Navigation buttons
//arrNavCaptions := ['Workouts','Nutrition','Sports','Progress','Profile','Log out'];
SetLength(arrNavButtons,length(arrNavCaptions));

for i := 0 to High(arrNavButtons) do
begin
btn := [Link](Self);

with btn do
begin
Parent := pnlLeft;;
Caption := arrNavCaptions[i];
Width := 140;
Height := 42;
Left := 20;
Top := 20 + (i * 10);// off screen bottom start
Tag := i;
Hint := 'Open ' + arrNavCaptions[i];
ShowHint := True;
OnClick := OnNavButtonClick;
OnMouseEnter := OnNavButtonMouseEnter;
OnMouseLeave := OnNavButtonMouseLeave;

SetLength(arrNavButtons,length(arrNavButtons));//prevent stable
issues;
arrNavButtons[i] := btn;
end;
end;

//summary cards on top right area


SetLength(arrPnlCards,3);
SetLength(arrCardPaintBoxes,3);
SetLength(arrCardTarget,3);
SetLength(arrCardCurrent,3);
SetLength(arrLblCardValue,3);

iContainerTop := 120;
for i := 0 to 2 do
begin

pnlCard := [Link](Self);
with pnlCard do
begin
Parent := pnlRight;
Width := 240;
Height := 120;
BevelInner := bvNone;
BevelOuter := bvRaised;
Caption := '';
end;//end with pnlcard

//Rings(paintbox)
paintbx := [Link](Self);
with paintbx do
begin
Parent := pnlCard;
Align := alLeft;
Width := 120;
Height := [Link];
OnPaint := OnPaintBoxPaint;
Tag := i;//index
end;

//Numeric value label to the right


lblval := [Link](Self);
with lblval do
begin
Parent := pnlCard;
Left := [Link] + 16;
Top := 24;
Caption := '...';
[Link] := 12;
end;

//store
arrPnlCards[i] := pnlCard;
arrCardPaintBoxes[i] := paintbx;
arrLblCardValue[i] := lblval;
arrCardTarget[i] := 0;
arrCardCurrent[i] := 0;
end;

//Set TabOrder for accessibility


for i := 0 to High(arrNavButtons) do
arrNavButtons[i].TabOrder := i;

//show hints
[Link] := True;
end;

procedure [Link];
const
btnHeight = 38;
btnWidth = 140;
var
iLeftX, iTopY, iGap : integer;
begin
//Create buttons
btnQuickWorkout := [Link](Self);
btnQuickMeal := [Link](Self);
btnQuickWeighIn := [Link](Self);

with btnQuickWorkout do
begin
Parent := pnlCenter;
Caption := 'Log & workout';
[Link] := bvNone;
[Link] := '';
Width := btnWidth;
Height := btnHeight;
Hint := 'Ctrl+W';
ShowHint := True;
OnClick := QuickActionClick;
end;

with btnQuickMeal do
begin
Parent := pnlCenter;
Caption := 'Log & meal';
[Link] := bvNone;
[Link] := '';
Width := btnWidth;
Height := btnHeight;
Hint := 'Ctrl+N';
ShowHint := True;
OnClick := QuickActionClick;
end;

with btnQuickWeighIn do
begin
Parent := pnlCenter;
Caption := 'Quick Weigh-in';
Width := btnWidth;
Height := btnHeight;
Hint := 'Ctrl+G';
ShowHint := True;
OnClick := QuickActionClick;
end;

iGap := 20;
iLeftX := ([Link] DIV 2) - ([Link] DIV 2);
iTopY := 40;

[Link](iLeftX, iTopY, [Link],


[Link]);
[Link](iLeftX, iTopY + [Link] + iGap,
[Link], [Link]);
[Link](iLeftX, iTopY + ([Link] + iGap) *
2,
[Link], [Link]);
end;

procedure [Link];
begin
memRecent := [Link](Self);
with memRecent do
begin
Parent := pnlCenter;
ReadOnly := True;
ScrollBars := ssVertical;
WordWrap := False;
[Link] := 'Segoe UI';
[Link]('Recent activity will show here...');
end;
end;

procedure [Link];
var
lbl : TLabel;
begin
//Calories today
lblCalToday := [Link](Self);
with lblCalToday do
begin
Parent := pnlCenter;
[Link] := 12;
Caption := 'Calories today: 0 kcal';
end;

//Workouts this week


lblWorkoutsWeek := [Link](Self);
with lblWorkoutsWeek do
begin
Parent := pnlCenter;
[Link] := 12;
Caption := 'Workouts (7d): 0';
end;

//Sport sessions this month


lblSportsMonth := [Link](Self);
with lblSportsMonth do
begin
Parent := pnlCenter;
[Link] := 12;
Caption := 'Sports sessions (month): 0';
end;
end;

procedure [Link](Sender: TObject; var Action: TCloseAction);


begin
//Stop timers
[Link] := False;
[Link] := False;
[Link] := False;
end;

procedure [Link](Sender: TObject);


begin
bFlag := False;
if NOT Assigned(dmFitness) then
dmFitness := [Link](Self);

//open all tables to ensure working


with dmFitness do
begin
if NOT [Link] then [Link];
if NOT [Link] then [Link];
if NOT [Link] then [Link];
if NOT [Link] then [Link];
if NOT [Link] then [Link];
if NOT [Link] then [Link];
if NOT [Link] then [Link];
if NOT [Link] then [Link];
end;

end;

procedure [Link](Sender: TObject; var Key: Word;


Shift: TShiftState);
begin
//shortcut keys
if (ssCtrl IN Shift ) then
begin
case Key of
Ord('W'): [Link]; // Ctrl+W
Ord('N'): [Link]; // Ctrl+N
Ord('G'): [Link]; // Ctrl+G
Ord('P'): if Assigned(frmProfile) then
[Link]; // ctrl+P
end;
end;
end;

procedure [Link](Sender: TObject);


var
i : integer;
begin
if bFlag then
Exit;
bFlag := True;

try
PositionCenterControls;
finally
bFlag := False;
end;

for i := 0 to High(arrCardPaintBoxes) do
if Assigned(arrCardPaintBoxes[i]) then
arrCardPaintBoxes[i].Invalidate;
end;

procedure [Link](Sender: TObject);


begin
if NOT bFlag then
begin
//Timers
TimerFade := [Link](Self);
[Link] := 20;
[Link] := TimerFadeTick;

TimerSlide := [Link](Self);
[Link] := 18;
[Link] := TimerSlideTick;

TimerRing := [Link](Self);
[Link] := 20;
[Link] := TimerRingTick;

//start of fade
with dmFitness do
begin
if NOT [Link] then
[Link];
[Link];
[Link] := 'Welcome, ' + tblUsers['FullName'];
end;

bFlag := True;
CreateCenterPanel;
CreateDynamicUI;
PositionCenterControls;
RefreshDashboard;

StartEntryAnim;
end;
end;

procedure [Link](Sender: TObject);


var
iIndex : integer;
begin
iIndex := (Sender as TButton).Tag;
case iIndex of
0 : ShowMessage('Open Workouts form (implement)');
1 : ShowMessage('Open Nutrition / Meals form (implement)');
2 : ShowMessage('Open Sports Sessions form (implement)');
3 : ShowMessage('Open Progress form (implement)');
4 : ShowMessage('Open Profile form (implement)');
5 : Close; // logout/exit

end;
end;

procedure [Link](Sender: TObject);


var
B : TButton;
begin
//(Sender as TButton).[Link] := [];
//(Sender as TButton).Color := clBtnFace;

if NOT (Sender is TButton) then


Exit;

B := TButton(Sender);
[Link] := [Link] + [fsBold];
[Link] := RGB(0, 102, 204);
[Link] := [Link] + 6;
end;

procedure [Link](Sender: TObject);


var
B : TButton;
begin
//(Sender as TButton).[Link] := [fsBold];
//(Sender as TButton).Color := RGB(230,245,255);

if NOT (Sender is TButton) then Exit;

B := TButton(Sender);
[Link] := [Link] - [fsBold];
[Link] := clBtnText;
[Link] := [Link] - 6;
end;

procedure [Link](Sender: TObject);


var
PB : TPaintBox;
iIndex : integer;
R, rect : TRect;
iCx, iCy, ir, iPenWidth: integer;
rStartAngle, rEndAngle : Double;
iXStart, iYStart, iXEnd, iYEnd : integer;
BackupPen : TPen;
BackupBrush : TBrush;
iProgress : integer;
lblTxt : string;
iFSize : integer;
begin
PB := Sender AS TPaintBox;
iIndex := [Link];
R := [Link];

//center and raduis based on pb size


iCx := ([Link] - [Link]) DIV 2;
iCy := ([Link] - [Link]) DIV 2;
ir := Min(iCx,iCy) - 10;
iPenWidth := Max(6, Round(ir * 0.14));
if iPenWidth > Round(ir /2) then
iPenWidth := Round(ir / 2);

//Current anim percent


iProgress := 0;
if (iIndex >= 0) AND (iIndex <= High(arrCardCurrent)) then
iProgress := arrCardCurrent[iIndex];

//clear
[Link] := [Link];;
[Link](R);

//Background Ring;
BackupPen := [Link];
BackupBrush := [Link];

try
[Link]([Link]);
[Link]([Link]);

[Link] := iPenWidth;
[Link] := RGB(230,230,230);
[Link] := bsClear;

//Draw full circle


[Link](iCx - ir, iCy - ir, iCx + ir, iCy + ir);

//Draw progress arc at - 90 degrees


rStartAngle := -90;
rEndAngle := rStartAngle + (iProgress/100) * 360;
//Give arc endpoints
iXStart := Round(iCx + ir * Cos(DegToRad(rStartAngle)));
iYStart := Round(iCy + ir * Sin(DegToRad(rStartAngle)));
iXEnd := Round(iCx + ir * Cos(DegToRad(rEndAngle)));
iYEnd := Round(iCy + ir * Sin(DegToRad(rEndAngle)));

[Link] := RGB(60,160,220);
[Link] := iPenWidth;

//Arc draws outline por of circle


[Link](iCx - ir, iCy - ir, iCx + ir, iCy + ir,iXStart, iYStart,iXEnd,iYEnd);

//Center for text


iFSize := Max(8, Round(ir * 0.28));
[Link] := iFSize;
[Link] := [fsBold];
lblTxt := IntToStr(iProgress) + '%';
[Link](iCx - [Link](lblTxt) DIV 2,
iCy - [Link](lblTxt) DIV 2, lblTxt);

finally
[Link](BackupPen);
[Link](BackupBrush);
[Link];
[Link];
end;
end;

procedure [Link];
var
iLeftWidth, iRightWidth, iGap, iTopMargin, iCenterLeft, iCenterWidth: Integer;
ibtnTop, ibtnLeft, ibtnGap: Integer;
i, iYPos, iCardWidth : integer;
pnlCard : TPanel;
pb : TPaintBox;
const
iCardHeight = 120;
iCardGap = 12;
begin

if bFlag then
Exit;
bFlag := True;

try
if (pnlCenter = nil) OR (pnlRight = nil) then
begin
Exit;
end;

if NOT Assigned(pnlCenter) OR NOT Assigned(pnlRight) then


Exit;

iGap := 20;
iTopMargin := 100;

//set left and right columm widths to match nav layout


iLeftWidth := Max(160, Round(ClientWidth * 0.17)); // left nav
iRightWidth := Max(260, Round(ClientWidth * 0.28)); // right rings

iCenterLeft := iLeftWidth + iGap;


iCenterWidth := ClientWidth - iLeftWidth - iRightWidth - (iGap * 3);
if iCenterWidth < 300 then
iCenterWidth := 300;

// temporarily disable align to prevent resize


[Link] := alNone;
[Link] := alNone;

//Centre panel postition


[Link](iCenterLeft, iTopMargin, iCenterWidth, ClientHeight -
iTopMargin - 40);

//right panel position


[Link](iCenterLeft + iCenterWidth + iGap, iTopMargin, iRightWidth,
ClientHeight - iTopMargin - 40);

//layout of cards inside pnlright


iCardWidth := [Link] - 20;
iYPos := 8;
for i := 0 to High(arrPnlCards) do
begin

if NOT Assigned(pnlCard) then


Continue;

with pnlCard do
begin
Parent := pnlRight;
Width := iCardWidth;
Height := iCardHeight;
Left := 10;
Top := iYPos;
end;
//Resize the paintbox inside pnl
pb := arrCardPaintBoxes[i];
if Assigned(pb) then
begin
[Link] := pnlCard;
[Link] := Round([Link] * 0.45) ;
[Link] := [Link] - 10;
[Link] := 6;
[Link] := ([Link] - [Link]) DIV 2;
end;

//position value labels next pb


if Assigned(arrLblCardValue[i]) then
begin
arrLblCardValue[i].Parent := pnlCard;
arrLblCardValue[i].Left := [Link] + [Link] + 12;
arrLblCardValue[i].Top := ([Link] -
arrLblCardValue[i].Height) DIV 2;
end;

Inc(iYPos, iCardHeight + iCardGap);


end;

//Invalidate pb to redraw new size


for i := 0 to High(arrCardPaintBoxes) do
if Assigned(arrCardPaintBoxes[i]) then
arrCardPaintBoxes[i].Invalidate;

//quick actions btns top of pnlcenter


ibtnGap := 14;
ibtnLeft := ([Link] - ([Link] * 3 + ibtnGap *
2)) div 2;
ibtnTop := 12;
[Link] := ibtnLeft;
[Link] := ibtnTop;

[Link] := [Link] + [Link] +


ibtnGap;
[Link] := ibtnTop;

[Link] := [Link] + [Link] + ibtnGap;


[Link] := ibtnTop;

//Labels under quick actions


[Link] := 12;
[Link] := ibtnTop + [Link] + 12;

[Link] := 12;
[Link] := [Link] + 22;

[Link] := 12;
[Link] := [Link] + 22;

//Recent activity memo


[Link] := 12;
[Link] := [Link] + 28;
[Link] := [Link] - 24;
[Link] := [Link] - [Link] - 12;
finally
bFlag := False;
end;
end;

procedure [Link](Sender: TObject);


begin
if Sender = btnQuickWorkout then
begin
//open workouts form
if NOT Assigned(frmWorkouts) then
frmWorkouts := [Link](Application);
[Link];
end
else
if Sender = btnQuickMeal then
begin
if NOT Assigned(frmNutrition) then
frmNutrition := [Link](Application);
[Link];
end
else
if Sender = btnQuickWeighIn then
begin
if NOT Assigned(frmProgress) then
frmProgress := [Link](Application);
[Link];
end;

RefreshDashboard;

end;

procedure [Link];
var
iWkCount, iCalToday, iSportCount: Integer;
iSavedPos: Integer;
sLine: string;
iMaxLines: Integer;
begin
if NOT Assigned(dmFitness) then
Exit;
//safety check
with dmFitness do
begin
if NOT [Link] then
[Link];
if NOT [Link] then
[Link];
if NOT [Link] then
[Link];
if NOT [Link] then
[Link];
if NOT [Link] then
[Link];
if NOT [Link] then
[Link];

//get numeric
iWkCount := 0;
[Link];
try
[Link];

while NOT [Link] do


begin
if ([Link]('UserID').AsInteger = iCurrUserID) AND
([Link]('WorkoutDate').AsDateTime >= Date - 7)
then
Inc(iWkCount);
[Link];
end;
finally
[Link];
end;

//calories today
iCalToday := 0;
[Link];

try
[Link];

while NOT [Link] do


begin
if ([Link]('UserID').AsInteger = iCurrUserID) AND
(Trunc([Link]('MealDate').AsDateTime) =
Trunc(Date))then
begin
[Link];

while NOT [Link] do


begin

if [Link]('MealID').AsInteger =
[Link]('MealID').AsInteger then
begin

//Find calories
if [Link]('FoodID',
[Link]('FoodID').AsInteger,[]) then
begin
iCalToday := iCalToday +
Round([Link]('Calories').AsFloat*
[Link]('Quantity').AsFloat);

end;
end;
[Link];
end;
end;
[Link];
end;
finally
[Link];
end;

//sport this month


iSportCount := 0;
[Link];
try
[Link];
while NOT [Link] do
begin
if ([Link]('UserID').AsInteger = iCurrUserID) AND
(MonthOf([Link]('SessionDate').AsDateTime) =
MonthOf(Date)) then
begin
Inc(iSportCount);
end;
[Link];
end;
finally
[Link];
end;

//add recent activity in memo(last 8 workouts + meals)


[Link];
try
[Link];
iMaxLines := 8;

//Decending date - recent workouts


[Link];
try
[Link];

while NOT [Link] do


begin
if [Link]('UserID').AsInteger = iCurrUserID then
begin
sLine := Format('%s | %s | %s',

[DateToStr([Link]('WorkoutDate').AsDateTime),
[Link]('WorkoutType').AsString,
[Link]('Notes').AsString]);
[Link](sLine);

if [Link] >= iMaxLines then


Break;
end;
[Link];
end;
finally
[Link];
end;
finally
[Link];
end;
end;//end with
end;

procedure [Link](UserID: Integer);


begin
iCurrUserID := UserID;

//Update welcome label


if Assigned(dmFitness) then
begin
if [Link]('UserID',UserID,[]) then
[Link] := 'Welcome, ' +
[Link]('FullName').AsString;
end;
end;

procedure [Link];
var
iCountWorkouts, iCalToday, iSportSesCount : integer;
// convert raw numbers to simple % goals for demo:
// - workouts: 0..7 => % of 4 workouts/week target
// - calories: compute percent of 2500 kcal daily goal
// - sports: count in month vs 8 sessions target
begin
if iCurrUserID < 0 then
begin
//Try use first user in table
if Assigned(dmFitness) AND ([Link] > 0)then
[Link];
if Assigned(dmFitness) AND (NOT [Link])then
iCurrUserID := [Link]('UserID').AsInteger;
end;

if NOT [Link] then


[Link];

//assign valuse
iCountWorkouts := CountWorkoutLast7Days(iCurrUserID);
iCalToday := CaloriesToday(iCurrUserID);
iSportSesCount := SportThsMonth(iCurrUserID);

arrCardTarget[0] := Min(100, Round((iCountWorkouts/4)*100)); //Target 4


workouts per week
arrCardTarget[1] := Min(100, Round((iCalToday/2500)*100)); //Daily cal goal;
arrCardTarget[2] := Min(100, Round((iSportSesCount/8)*100)); //Monthly target
= 8 ses;

arrLblCardValue[0].Caption := IntToStr(iCountWorkouts) + ' wk';


arrLblCardValue[1].Caption := IntToStr(iCalToday) + ' kcal';
arrLblCardValue[2].Caption := IntToStr(iSportSesCount) + ' mo';
end;

function [Link](UserID: Integer): Integer;


var
dtStartOfMonth : TDateTime;
begin
Result := 0;

if NOT Assigned(dmFitness) then


Exit;

//Count sessions for the current month


dtStartOfMonth := EncodeDate(YearOf(Date), MonthOf(Date),1);

with dmFitness do
begin
[Link];
[Link];
try
[Link];

while NOT [Link] do


begin

if (tblSportSessions['UserID'] = UserID) AND


(tblSportSessions['SessionDate'] >= dtStartOfMonth) then
begin
Inc(Result);
end;

[Link];
end;// end with eof

finally
[Link];
end;// end try
end; //end with dm
end;

procedure [Link];
begin
//Initial state
[Link] := True;
[Link] := 0;
iAnimStep := 0;
[Link] := True;

end;

procedure [Link](Sender: TObject);


begin
if [Link] < 255 then
[Link] := Min(255, [Link] + 20)
else
begin
[Link] := False;
//start animation for title/welcome/Nav
[Link] := True;
end;
end;

procedure [Link](Sender: TObject);


var
i : integer;
bsChanged : boolean;
begin
bsChanged := False;

for i := 0 to High(arrCardCurrent) do
begin

if arrCardCurrent[i] < arrCardTarget[i] then


begin
Inc(arrCardCurrent[i],Max(1, Round((arrCardTarget[i] -
arrCardCurrent[i])/8)));

if arrCardCurrent[i] > arrCardTarget[i] then


arrCardCurrent[i] := arrCardTarget[i];

bsChanged := True;

//Update display
arrLblCardValue[i].Caption := IntToStr(Round(arrCardCurrent[i])) + '%';
arrCardPaintBoxes[i].Invalidate;
end;
end;

//if anim finished


if NOT bsChanged then
[Link] := False
end;

procedure [Link](Sender: TObject);


var
i : integer;
iTargetDrop : integer;
bsFinished : boolean;

begin

//slide from left to x = 30 (Title label)


if [Link] < 30 then
[Link] := [Link] + 22;

//Slide from right to x = 320 (welcome lbl)


if [Link] > ([Link] DIV 3) then
[Link] := [Link] - 20;

//Slide navigation buttons into position


//top starts at 150 + i*
bsFinished := True;

for i := 0 to High(arrNavButtons) do
begin
iTargetDrop := 150 + i * 58;

if arrNavButtons[i].Top > iTargetDrop then


begin
arrNavButtons[i].Top := arrNavButtons[i].Top - 18;
bsFinished := False;
end;
end;

//When slide done - stop and start ring animation after DB targets
if bsFinished AND ([Link] >= 30) AND ([Link] <=
([Link] DIV 3)) then
begin
[Link] := False;
SetupCardTargets;

//start ring anim and counters


[Link] := True;
end;
end;

end.

You might also like