📁 Showcase
FitnessSheet

FitnessSheet

Backend

1. Variables

// function to convert time to millis
ensure var VarFunctionCalcTimeMillis kind: function 
  modules: ["MyFitnessPal"]
  deploy: fixedOnDeploy
  value: "function(dateString : text) : number	
  {
    // Create a Date object with today's date and parsed time
    const date = new Date(dateString);

    // Get milliseconds since the epoch
    const milliseconds = date.getTime();
    
    return milliseconds;	
  }"

// types of activity
ensure var VarSetOfTextActivityType kind: setOfText 
  modules: ["MyFitnessPal"]
  deploy: fixedOnDeploy
  value: "<root>
      <node key='keyFood'>Food</node>
      <node key='keyWater'>Water</node>
      <node key='keySleep'>Sleep</node>
      <node key='keyExercise'>Exercise</node>
    </root>"

// types of exercise
ensure var VarSetOfTextExerciseType kind: setOfText 
  modules: ["MyFitnessPal"]
  deploy: fixedOnDeploy
  value: "<root>
      <node key='keyWalking'>Walking</node>
      <node key='keyRunning'>Running</node>
      <node key='keyGym'>Gym</node>
      <node key='keyCycling'>Cycling</node>
      <node key='keySwimming'>Swimming</node>
      <node key='keyHiking'>Hiking</node>
    </root>"

// function variable to calculate calorie burn
ensure var VarFunctionCalcCalorieBurn kind: function 
  modules: ["MyFitnessPal"]
  deploy: fixedOnDeploy
  value: "function(type : text, duration : number) : number
  {

  let calories = 0;

  switch (type) {
    case 'Walking':
      calories = (duration/30) * 85;
      break;
    case 'Running':
      calories = (duration/30) * 300;
      break;
    case 'Gym':
      calories = (duration/30) * 150;
      break;
    case 'Cycling':
      calories = (duration/30) * 330;
      break;
    case 'Swimming':
      calories = (duration/30) * 215;
      break;
    case 'Hiking':
      calories = (duration/30) * 250;
      break;
    default:
      calories = null;
  }

  return calories;
  }"

// function variable to calculate calorie gain
ensure var VarFunctionCalcCalorieGain kind: function 
  modules: ["MyFitnessPal"]
  deploy: fixedOnDeploy
  value: "function(size : number) : number
  {
      if (size >= 10 && size < 100)
      {
        return Math.floor(Math.random() * (100 - 10 + 1)) + 10;
      }
      else if (size >= 100 && size < 200)
      {
            return Math.floor(Math.random() * (200 - 100 + 1)) + 20;
      }
      else if (size >= 200 && size < 400)
      {
        return Math.floor(Math.random() * (400 - 200 + 1)) + 40;
      }
      else
      {
        return Math.floor(Math.random() * (800 - 400 + 1)) + 80;
      }
  }"

2. FitnessSheet

// fields ending with "*" suffix are required
ensure spreadsheet: FitnessSheet
withFields: [
    "Date",
    "Time*",
    "Activity*"
  ]
ofTypes: [date, time, pickText]
modules: ["MyFitnessPal"]
readRoleSet: [Member]
insertRoleSet: [Member]
updateRoleSet: [Member]
removeRoleSet: [Member]


ensure form EntityFitness
  modules: ["MyFitnessPal"]

ensure section: Details
ensure field Date defaultValue: "now"
ensure field Time defaultValue.value: now
ensure field Activity sourceVar: VarSetOfTextActivityType

ensure section: Water 
ensure field Intake kind: number
  helperText: "Water intake in ml"
  suffix: "ml"

ensure section: Food 
ensure field EnterManually kind: bool
  showAsCheckbox: true
  position: start
  labelPlacement: end
ensure field FoodImage kind: image
ensure field RefFood kind: ref
  spreadsheet: FoodItemMaster
  layoutSpreadsheet: List
  permissionMatrix: {
      'defaultPermission': 'hide'
    }
ensure field FoodName kind: text
ensure field AvgServingSize kind: number
  permissionMatrix: {
      'defaultPermission': 'invisible'
    }
  min: 0
ensure field Unit kind: pickText
  permissionMatrix: {
      'defaultPermission': 'invisible'
    }
  sourceVar: VarSetOfTextFoodItemUnit
ensure field Calories kind: number
  permissionMatrix: {
      'defaultPermission': 'invisible'
    }
  suffix: " cal"
  min: 0
ensure field Protein kind: decimal
  permissionMatrix: {
      'defaultPermission': 'invisible'
    }
  min: 0.0
  numberOfDigitsAfterPeriod: 2
ensure field Carbohydrate kind: decimal
  permissionMatrix: {
      'defaultPermission': 'invisible'
    }
  min: 0.0
  numberOfDigitsAfterPeriod: 2
ensure field Fat kind: decimal
  permissionMatrix: {
      'defaultPermission': 'invisible'
    }
  min: 0.0
  numberOfDigitsAfterPeriod: 2
ensure field ServingSize kind: number
ensure field TotalCalories kind: number
  disabled: true
ensure field TotalProtein kind: decimal
  disabled: true
  numberOfDigitsAfterPeriod: 2
ensure field TotalCarbs kind: decimal
  disabled: true
  numberOfDigitsAfterPeriod: 2
ensure field TotalFat kind: decimal
  disabled: true
  numberOfDigitsAfterPeriod: 2

ensure section: Sleep 
ensure field BedTime kind: label 
ensure field From kind: dateTime 
ensure field WakeUpTime kind: label 
ensure field To kind: dateTime 
ensure field TotalHours kind: number 

ensure section: Exercise
ensure field ExerciseType kind: pickText sourceVar: VarSetOfTextExerciseType
ensure field Duration kind: number
  helperText: "Exercise duration in minutes"
  suffix: " min"
ensure field BurnedCalories kind: number

3. Fitness formula

// formula to calculate total calories gain
ensure formula TotalCalories
  assignToField: Food.TotalCalories
  formula: "let avgServing = ${f:AvgServingSize};

  if(avgServing === undefined || avgServing === null)
  {
    ${var:VarFunctionCalcCalorieGain}(${f:ServingSize})
  }
  else
  {
    ((${f:ServingSize})/${f:AvgServingSize})*(${f:Calories})
  }"

// formula, TotalProtien
ensure formula TotalProtien
  assignToField: Food.TotalProtein
  formula: "let avgServing = ${f:AvgServingSize};

  if(avgServing === undefined || avgServing === null)
  {
    ${f:TotalCalories}/4;
  }
  else
  {
      ((${f:ServingSize})/${f:AvgServingSize})*(${f:Protein})
  }"

// formula to calculate total fat
ensure formula TotalFat
  assignToField: Food.TotalFat
  formula: "let avgServing = ${f:AvgServingSize};

  if(avgServing === undefined || avgServing === null)
  {
    ${f:TotalCalories}/9;
  }
  else
  {
      ((${f:ServingSize})/${f:AvgServingSize})*(${f:Fat})
  }"

// formula to calculate total carbs
ensure formula TotalCarbs
  assignToField: Food.TotalCarbs
  formula: "let avgServing = ${f:AvgServingSize};

  if(avgServing === undefined || avgServing === null)
  {
    ${f:TotalCalories}/4;
  }
  else
  {
      ((${f:ServingSize})/${f:AvgServingSize})*(${f:Carbohydrate})
  }"

// formula to calculate total sleep hours
ensure formula TotalHours
  assignToField: Sleep.TotalHours
  formula: "if(${f:From}==null || ${f:To}==null)
  {
      null;
  }
  else
  {
      let fromDate = new Date(${f:From});
      let toDate = new Date(${f:To});


      let start = ${var:VarFunctionCalcTimeMillis}(fromDate);
      let end = ${var:VarFunctionCalcTimeMillis}(toDate);

      let ans = (end - start)/3600000;

      ans
  }"

// formula to calculate total calories burned
ensure formula BurntCalories
  assignToField: Exercise.BurnedCalories
  formula: "let ans = ${var:VarFunctionCalcCalorieBurn}(${f:ExerciseType.value}, ${f:Duration});
ans;"

4. Visibility rules

ensure visibilityRule FoodVisibilityRule
  condition: "<root>
      <stmt>Details.Activity == ${d:Activity.keyFood}</stmt>
    </root>"
ensure actionMapIfTrue MakeFoodVisible
  comp: Food
  visibilityAction: visible
  visibilityActionOn: component
ensure actionMapIfFalse MakeFoodHidden
   comp: Food
   visibilityAction: hidden
   visibilityActionOn: component

// visibilityRule, WaterVisibilityRule
ensure visibilityRule WaterVisibilityRule
  condition: "<root>
      <stmt>Details.Activity == ${d:Activity.keyWater}</stmt>
    </root>"
ensure actionMapIfTrue MakeWaterVisible
  comp: Water
  visibilityAction: visible
  visibilityActionOn: component
ensure actionMapIfFalse MakeWaterHidden
  comp: Water
  visibilityAction: hidden
  visibilityActionOn: component

// visibilityRule, ExerciseVisibilityRule
ensure visibilityRule ExerciseVisibilityRule
  condition: "<root>
      <stmt>Details.Activity == ${d:Activity.keyExercise}</stmt>
    </root>"
ensure actionMapIfTrue MakeExerciseVisible
  comp: Exercise
  visibilityAction: visible
  visibilityActionOn: component
ensure actionMapIfFalse MakeExerciseHidden
  comp: Exercise
  visibilityAction: hidden
  visibilityActionOn: component

// visibilityRule, SleepVisibilityRule
ensure visibilityRule SleepVisibilityRule
  condition: "<root>
      <stmt>Details.Activity == ${d:Activity.keySleep}</stmt>
    </root>"

ensure actionMapIfTrue MakeSleepVisible
  comp: Sleep
  visibilityAction: visible
  visibilityActionOn: component
ensure actionMapIfFalse MakeSleepHidden
  comp: Sleep
  visibilityAction: hidden
  visibilityActionOn: component

// visibilityRule, FoodManullyVisibilityRule
ensure visibilityRule FoodManullyVisibilityRule
  condition: "<root>
      <stmt>Food.EnterManually == ${d:EnterManually.true}</stmt>
    </root>"
ensure actionMapIfTrue MakeRefFoodVisible
  comp: Food.RefFood
  visibilityAction: visible
  visibilityActionOn: field

ensure actionMapIfTrue MakeFoodNameVisible
  comp: Food.FoodName
  visibilityAction: visible
  visibilityActionOn: field
ensure actionMapIfTrue FoodImageHidden
  comp: Food.FoodImage
  visibilityAction: hidden
  visibilityActionOn: field
ensure actionMapIfFalse MakeRefFoodHidden
  comp: Food.RefFood
  visibilityAction: hidden
  visibilityActionOn: field
ensure actionMapIfFalse MakeFoodNameHidden
  comp: Food.FoodName
  visibilityAction: hidden
  visibilityActionOn: field
ensure actionMapIfFalse MakeFoodImageHidden
  comp: Food.FoodImage
  visibilityAction: visible
  visibilityActionOn: field

5. FitnessSheet layout

ensure spreadsheet FitnessSheet

ensure layoutSpreadsheet List kind: list
  firstLine.first.lineFields: [Details.Date]
  firstLine.middle.lineFields: [Details.Time]
  firstLine.caption.lineFields: [Details.Activity]

// layoutSpreadsheet, table, WaterTable
ensure layoutSpreadsheet WaterTable kind: table
  columnSizeSet: ["Flex"]
  showComps: [Date, Time, Activity, Intake]

// layoutSpreadsheet, table, FoodTable
ensure layoutSpreadsheet FoodTable kind: table
  columnSizeSet: ["Flex"]
  showComps: [
    Date, 
    Time, 
    Activity, 
    FoodName, 
    ServingSize, 
    TotalCalories, 
    TotalProtein, 
    TotalCarbs, 
    TotalFat
  ]

// layoutSpreadsheet, table, SleepTable
ensure layoutSpreadsheet SleepTable kind: table
  columnSizeSet: ["Flex"]
  showComps: [Date, Time, Activity, From, To, TotalHours]

// layoutSpreadsheet, table, ExerciseTable
ensure layoutSpreadsheet ExerciseTable kind: table
  columnSizeSet: ["Flex"]
  showComps: [Date, Time, Activity, ExerciseType, Duration, BurnedCalories]

Frontend

1. AddFitnessActivity

ensure action AddFitnessActivity kind: rowInsert
  modules: ["MyFitnessPal"]
  icon: "AddCircleOutlineRounded"
  spreadsheet: FitnessSheet
  sendMessageToInbox: true

2. AddWaterActivity

ensure action AddWaterActivity kind: rowInsert 
  icon: "AddCircleOutlineRounded" 
  modules: ["MyFitnessPal"]
  defaultValueMap: {
      'Details.Activity': {
        'value': 'Water',
        'optionId': 'keyWater'
      }
    } 
  spreadsheet: FitnessSheet 
  sendMessageToInbox: true

3. AddSleepActivity

ensure action AddSleepActivity kind: rowInsert 
  icon: "AddCircleOutlineRounded" 
  modules: ["MyFitnessPal"]
  defaultValueMap: {
      'Details.Activity': {
        'value': 'Sleep',
        'optionId': 'keySleep'
      }
    } 
  spreadsheet: FitnessSheet 
  sendMessageToInbox: true

4. AddExerciseActivity

ensure action AddExerciseActivity kind: rowInsert 
  icon: "AddCircleOutlineRounded"
  modules: ["MyFitnessPal"]
  defaultValueMap: {
    'Details.Activity': {
      'value': 'Exercise',
      'optionId': 'keyExercise'
    }
  }  
  spreadsheet: FitnessSheet 
  sendMessageToInbox: true

5. AddFoodActivity

ensure action AddFoodActivity kind: rowInsert 
  icon: "AddCircleOutlineRounded"
  modules: ["MyFitnessPal"]
  defaultValueMap: {
    'Details.Activity': {
      'value': 'Food',
      'optionId': 'keyFood'
    }
  }  
  spreadsheet: FitnessSheet 
  sendMessageToInbox: true

6. Prompts

//** prompt, PromptAddExerciseActivity
ensure prompt PromptAddExerciseActivity 
  modules: ["MyFitnessPal"] 
  action: AddExerciseActivity 
  promptText: "exercise ${f:ExerciseType}${sep}${f:Duration}" 
  permissionRoles: [Member]

//** prompt, PromptAddFoodActivity
ensure prompt PromptAddFoodActivity 
  modules: ["MyFitnessPal"] 
  action: AddFoodActivity 
  promptText: "food ${f:EnterManually}${sep}${f:RefFood}${sep}${f:ServingSize}" 
  permissionRoles: [Member]

//** prompt, PromptAddSleepActivity
ensure prompt PromptAddSleepActivity 
  modules: ["MyFitnessPal"] 
  action: AddSleepActivity 
  promptText: "sleep ${f:From}${sep}${f:To}" 
  permissionRoles: [Member]

//** prompt, PromptAddWaterActivity
ensure prompt PromptAddWaterActivity 
  modules: ["MyFitnessPal"] 
  action: AddWaterActivity 
  promptText: "water ${f:Intake}" 
  permissionRoles: [Member]

7. Group actions

ensure group MyFitnessPal
  actionPermission: {
      'AddFitnessActivity': {
        'menuGroup': '1',
        'roles': [
          'Member'
        ]
      },
     'AddFoodActivity': {
        'menuGroup': '1',
        'roles': [
          'Member'
        ]
      },
      'AddWaterActivity': {
        'menuGroup': '1',
        'roles': [
          'Member'
        ]
      },
      'AddSleepActivity': {
        'menuGroup': '1',
        'roles': [
          'Member'
        ]
      },
      'AddExerciseActivity': {
        'menuGroup': '1',
        'roles': [
          'Member'
        ]
      }
    }