Compare commits

...
14 Commits
22 changed files with 258 additions and 154 deletions
+16
View File
@@ -0,0 +1,16 @@
for stase management:
1. Klick auf Übung macht neuen Eintrag in der UserState mit dem Excercise Namen + benötigten Feldern in currentEdit.
2. Wenn CurrentEdit gesetzt zeig die Set Optionen an.
3. Speichere die Sets in User.Chest
4. Cleare den CurrentEdit
5. Display oben was Eingetragen wurde in User.Chest
In this rewritten example, we still use reactive to create the reactive inputValues object and ref to create the currentButton reference.
The setCurrentButton function sets the value of currentButton to the ID of the button that was clicked.
The saveInputValue function saves the input value for the current button in inputValues[currentButton.value].value.
The rest of the code remains largely the same, with the buttons array being rendered using v-for, and the input field and value display being updated based on the currently selected button.
With the Composition API, the reactive state and functions are defined within the setup function, providing a cleaner and more organized way to handle component logic.
+11
View File
@@ -0,0 +1,11 @@
Your selected colors:
Primary: #daeafb (RGB: 218, 234, 251)
Secondary: #000000 (RGB: 0, 0, 0)
Primary Button: #5b9a66 (RGB: 91, 154, 102)
Secondary Button: #120320 (RGB: 18, 3, 32)
Accent: #b574f1 (RGB: 181, 116, 241)
Realtime Colors link for selected colors: https://realtimecolors.com/?colors=daeafb-000000-5b9a66-120320-b574f1
Thanks for using RealtimeColors.com!
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

-2
View File
File diff suppressed because one or more lines are too long
+2
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="./logo.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Gym Tracker</title><script type="module" crossorigin src="./assets/index-3d69e972.js"></script></head><body><div id="app"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="./logo.ico"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Gym Tracker</title><script type="module" crossorigin src="./assets/index-4ea6f92e.js"></script></head><body><div id="app"></div></body></html>
+1 -1
View File
@@ -4,7 +4,7 @@ import { NavigationModel } from "./components/Index.js";
</script>
<template>
<div class="app-containe">
<div class="app-container bg-background">
<NavigationModel />
<div class="container px-3 mx-auto">
<router-view class="mt-4" />
View File
+25 -28
View File
@@ -1,57 +1,57 @@
<template>
<input class="search " type="text" v-model="input" placeholder="Search..." />
<input class="search
text-black py-2 px-2 rounded mt-5"
v-model="input"
type="text"
placeholder="Search..." />
<div class="flex">
<div class="exerciseList">
<ul class="exerciseItem" v-for="exercise in filterExercises()" :key="exercise.name">
<Button @click="exerciseClick(exercise)" class="btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4" >{{ exercise.name }}</Button>
<button @click="exerciseClick(exercise); initSetInput()" class="btn bg-secondary-button hover:bg-accent text-white font-bold py-2 px-2 rounded" >{{ exercise.name }}</button>
</ul>
</div>
<div v-show="isClicked" class="show">
<label> {{ exerciseName }}</label>
<WeightsInput/>
<div v-if="selectedExercise">
<WeightsInput :selectedExercise="selectedExercise"></WeightsInput>
</div>
</div>
</template>
<script setup>
import { usePostStore } from '@/stores/store.js';
import { useExerciseStore } from '@/stores/storeExercise.js';
import { onMounted, ref } from 'vue';
import WeightsInput from "@/views/weight/WeightsInput.vue";
import { useWeightInputStore } from '@/stores/storeInput';
const muscle = defineProps({
muscle: String,
warmUpSets: Array,
workingSets: Array,
warmUpReps: Array,
workingReps: Array,
})
let isClicked = false
const json = usePostStore()
const json = useExerciseStore()
const weightInput = useWeightInputStore()
const exercises = ref([])
let exerciseName = ""
const selectedExercise = ref(null)
onMounted(async () => {
await json.fetchMuscleExercise()
switch (muscle.muscle) {
case "Legs":
exercises.value = json.postList.muscle[0].exercises
exercises.value = json.exerciseList.muscle[0].exercises
break;
case "Back":
exercises.value = json.postList.muscle[1].exercises
exercises.value = json.exerciseList.muscle[1].exercises
break;
case "Chest":
exercises.value = json.postList.muscle[2].exercises
exercises.value = json.exerciseList.muscle[2].exercises
break;
case "Shoulder":
exercises.value = json.postList.muscle[3].exercises
exercises.value = json.exerciseList.muscle[3].exercises
break;
case "Biceps":
exercises.value = json.postList.muscle[4].exercises
exercises.value = json.exerciseList.muscle[4].exercises
break;
case "Triceps":
exercises.value = json.postList.muscle[5].exercises
exercises.value = json.exerciseList.muscle[5].exercises
break;
}
}
@@ -65,16 +65,13 @@
});
};
const showWeightInput = (isClicked) => {
isClicked.value = true
}
const exerciseClick = (exercise) => {
isClicked = true
exerciseName = exercise.name
console.log(isClicked)
}
const exerciseClick = (exercise) => {
selectedExercise.value = exercise;
};
const initSetInput = () => {
weightInput.initSetsInputs(selectedExercise.value);
};
</script>
+7 -3
View File
@@ -25,7 +25,7 @@
width: 100%;
height: 4rem;
justify-content: start;
background: rgb(36, 165, 75);
background: #0a0e06;
}
.navbar-nav{
display: flex;
@@ -36,12 +36,16 @@
.nav-item{
margin-left: 1rem;
margin-right: 1rem;
color: white;
color: #e7f1df;
text-decoration: none;
font-size: 1.2rem;
}
.nav-item:hover{
color: orangered;
// color: rgb(91, 154, 102);
color: #699f65
}
.logo{
display: flex;
}
-22
View File
@@ -1,22 +0,0 @@
import {defineStore} from 'pinia'
import muscleExercise from '../assets/muscleExercise';
import { ref } from 'vue'
export const usePostStore = defineStore('json', () => {
const postList = ref([])
const error = ref([])
async function fetchMuscleExercise() {
postList.value = muscleExercise
error.value = []
}
return {
postList,
error,
fetchMuscleExercise
}
}
)
export default usePostStore
+17
View File
@@ -0,0 +1,17 @@
import {defineStore} from 'pinia'
import muscleExercise from '../assets/muscleExercise';
import { ref } from 'vue'
export const useExerciseStore = defineStore('json', () => {
const exerciseList = ref([])
async function fetchMuscleExercise() {
exerciseList.value = muscleExercise
}
return {
exerciseList,
fetchMuscleExercise
}
}
)
+94
View File
@@ -0,0 +1,94 @@
import { defineStore } from 'pinia'
// import { reactive } from 'vue'
import { useLocalStorage } from '@vueuse/core'
export const useWeightInputStore = defineStore('weightInput', () => {
// localStorage https://vueuse.org/core/useLocalStorage/
const exercises = useLocalStorage('exercises', {});
function addWorkingSet(selectedExercise) {
if (!exercises.value[selectedExercise]) {
return;
}
exercises.value[selectedExercise].workingSet.push({
workingSetReps: [],
workingSetWeight: [],
});
console.log('Added working set:', exercises.value[selectedExercise]);
}
function addWarmUpSet(selectedExercise) {
if (!exercises.value[selectedExercise]) {
return;
}
exercises.value[selectedExercise].warmUpSet.push({
warmSetReps: [],
warmSetWeight: [],
});
}
function removeWorkingSet(selectedExercise) {
if(!exercises.value[selectedExercise]) {
return
}
exercises.value[selectedExercise].workingSet.pop({
workingSetReps: [],
workingSetsWeight: [],
})
}
function removeWarmUpSet(selectedExercise) {
if(!exercises.value[selectedExercise]) {
return;
}
exercises.value[selectedExercise].warmUpSet.pop({
warmUpSetReps: [],
warmUpSetsWeight: [],
})
}
function getWorkingSetCount(selectedExercise) {
if (exercises.value[selectedExercise]) {
return exercises.value[selectedExercise].workingSet.length;
}
return 1;
}
function getWarmUpSetCount(selectedExercise) {
if (exercises.value[selectedExercise]) {
return exercises.value[selectedExercise].warmUpSet.length;
}
return 1;
}
function initSetsInputs(selectedExercise) {
if(!exercises.value[selectedExercise]) {
exercises.value[selectedExercise] = {
workingSet: [],
warmUpSet: [],
};
exercises.value[selectedExercise].workingSet.push({
workingSetReps: [],
workingSetWeight: [],
});
exercises.value[selectedExercise].warmUpSet.push({
warmSetReps: [],
warmSetWeight: [],
});
}
console.log('Init sets inputs:', exercises.value[selectedExercise], selectedExercise);
}
return {
exercises,
addWorkingSet,
removeWorkingSet,
addWarmUpSet,
removeWarmUpSet,
getWorkingSetCount,
getWarmUpSetCount,
initSetsInputs }
}
)
-22
View File
@@ -1,22 +0,0 @@
import {defineStore} from 'pinia'
import {useStorage} from '@vueuse/core'
//see https://stephanlangeveld.medium.com/simple-local-storage-implementation-using-vue-3-vueuse-and-pinia-with-zero-extra-lines-of-code-cb9ed2cce42a
export const useWeightStore = defineStore({
id: 'weight',
state: () => ({
weight: [],
reps: []
}),
getters: {
getAllWeights() {
return this.weight.value
},
},
actions: {
addWeight(weight, reps) {
this.weight.push(weight);
this.reps.push(reps);
},
}
})
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="text-3xl font-bold underline text-blue-500">
<div class="text-white">
<h1>Back</h1>
<ExerciseList muscle="Back"/>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="biceps">
<div class="biceps text-text">
<h1>Biceps</h1>
<ExerciseList muscle="Biceps"/>
</div>
+1 -4
View File
@@ -1,12 +1,9 @@
<template>
<div class="flex">
<div class="text-white">
<div class="w-1/2">
<h1>Chest</h1>
<ExerciseList muscle="Chest"/>
</div>
<div>
<weightsInput/>
</div>
</div>
</template>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="legs">
<div class="legs text-white">
<h1>Legs</h1>
<ExerciseList muscle="Legs"/>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="shoulder">
<div class="shoulder text-white">
<h1>Shoulder</h1>
<ExerciseList muscle="Shoulder"/>
</div>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="triceps">
<div class="triceps text-white ">
<h1>Triceps</h1>
<ExerciseList muscle="Triceps"/>
</div>
+67 -65
View File
@@ -1,87 +1,89 @@
<template>
//TODO make view resposive on button click add
<div class="w-2/3 mx-auto">
<div class="warmup-sets mt-12 w-2/3">
<div class="mt-2">
<label>Warm-Up Sets</label>
<button @click="warmUpAddSet()" class="add-btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded ml-5">Add</button>
<div v-for="warmupset in warmUpInput.warmUpSets" class="item" :key="warmupset">
{{ warmupset }}
<input name="warmupweight" class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-sky-500 block rounded-md sm:text-sm focus:ring-1" placeholder="Weight in Kg" />
</div>
</div>
<button @click="weightInput.addWarmUpSet(selectedExercise)"
class="bg-accent hover:bg-primary-button text-white font-bold py-2 px-2 rounded ml-5">
Add
</button>
<!-- https://www.designcise.com/web/tutorial/how-to-conditionally-disable-a-button-in-vue-js -->
<button :disabled="weightInput.getWarmUpSetCount(selectedExercise) <= 1"
@click="weightInput.removeWarmUpSet(selectedExercise)"
class="bg-accent hover:bg-primary-button text-white font-bold py-2 px-2 rounded ml-5 disabled:opacity-25">
Remove
</button>
<div v-for="(warmUpSet, warmUpSetCount) in weightInput.exercises[selectedExercise].warmUpSet" :key="warmUpSetCount"
class="flex ml-2">
<label>Set {{ warmUpSetCount + 1 }}</label>
<div class="ml-3">
<input
v-model="warmUpSet.warmUpWeight"
type="number"
class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none block rounded-md sm:text-sm "
placeholder="Weight (kg)"
onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
</div>
<div class="ml-3">
<input
v-model="warmUpSet.warmUpReps"
type="number"
class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none block rounded-md sm:text-sm "
placeholder="Reps"
onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
</div>
</div>
<div class="working-set mt-5">
<label>Working Sets</label>
<button @click="workingAddSet()" class="add-btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded ml-7">Add</button>
<button @click="weightInput.addWorkingSet(selectedExercise.selectedExercise)"
class="bg-accent hover:bg-primary-button text-white font-bold py-2 px-2 rounded ml-7">
Add
</button>
<button :disabled="weightInput.getWorkingSetCount(selectedExercise) <= 1"
@click="weightInput.removeWorkingSet(selectedExercise)"
class="bg-accent hover:bg-primary-button text-white font-bold py-2 px-2 rounded ml-5 disabled:opacity-25">
Remove
</button>
<div>
<div v-for="(workingset, index) in workingInput.workingSets" class="item flex justify-smart mt-3" :key="index">
{{ workingset }}
<div v-for="(workingset, workingSetCount) in weightInput.exercises[selectedExercise].workingSet" :key="workingSetCount" class="item flex justify-smart mt-1">
<label class=""> {{ workingSetCount + 1 }}. Set</label>
<div class="ml-3">
<input v-model="workingInput.workingSets" class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-sky-500 block rounded-md sm:text-sm focus:ring-1" placeholder="Weight in Kg"/>
<input
v-model="workingset.workingSetWeight"
type="number"
class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none block rounded-md sm:text-sm "
placeholder="Weight (Kg)"
onkeypress='return event.charCode >= 48 && event.charCode <= 57'/>
</div>
<label>Reps</label>
<div class="ml-3">
<input v-model="workingInput.workingReps" class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none focus:border-sky-500 focus:ring-sky-500 block rounded-md sm:text-sm focus:ring-1" placeholder="Reps">
<input
v-model="workingset.workingSetReps"
type="number"
class="mt-1 px-3 py-2 bg-black border shadow-sm border-slate-300 placeholder-slate-400 focus:outline-none block rounded-md sm:text-sm "
placeholder="Reps"
onkeypress='return event.charCode >= 48 && event.charCode <= 57'> <!-- https://stackoverflow.com/questions/66172698/textbox-which-accepts-only-numbers-in-vue-js -->
</div>
</div>
</div>
</div>
<button @click="addWeight()" class="add-btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded mt-5">Save</button>
</div>
</div>
</template>
<script setup>
import { useWeightStore } from '@/stores/storeWeight';
import { useWeightInputStore } from '@/stores/storeInput';
import { ref } from 'vue';
let warmUpSetCount = 0;
let workingSetCount = 0;
const selectedExercise = defineProps({
selectedExercise: String
});
const weight = useWeightStore();
const weightInput = useWeightInputStore();
weightInput.selectedExercise = ref(selectedExercise.selectedExercise);
let warmUpInput = {
warmUpSets: [],
warmUpReps: []
}
let workingInput = {
workingSets: [],
workingReps: []
}
const warmUpAddSet = () => {
const newWarmUpSet = {
id: warmUpSetCount++,
content: warmUpSetCount + ". Set"
};
warmUpInput.warmUpSets.push(newWarmUpSet.content);
console.log(warmUpInput.warmUpSets);
};
const workingAddSet = () => {
const newWorkingSet = {
id: workingSetCount++,
content: workingSetCount + ". Set"
};
workingInput.workingSets.push(newWorkingSet.content);
console.log(workingInput);
};
const addWeight = () => {
//TODO: Add warmup sets and reps to store
weight.addWeight(workingSetInput.value, workingRepsSets.value);
workingSetInput.value = "";
workingRepsSets.value = "";
}
console.log(addWeight);
</script>
<style>
</style>
export default weightsInput;
</script>
+11 -1
View File
@@ -5,7 +5,17 @@ export default {
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
extend: {
colors: {
'primary-button':'#5b9a66',
// 'secondary-button':'#0d1406',
'secondary-button':'#699f65',
'background':'#131d0c',
'text': '#e7f1df',
'accent': '#361f47',
'accent2': '#63992e',
}
},
},
plugins: [],
}