Compare commits

..

No commits in common. "71ce91cd353042021acc3ccb03f9aa9ad01457e4" and "831f7c4ad10e54758724358f2fa778eed070d1c2" have entirely different histories.

22 changed files with 154 additions and 258 deletions

16
TODOS
View File

@ -1,16 +0,0 @@
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.

View File

@ -1,11 +0,0 @@
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.

Before

Width:  |  Height:  |  Size: 1.8 KiB

2
dist/assets/index-3d69e972.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/index.html vendored
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-4ea6f92e.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-3d69e972.js"></script></head><body><div id="app"></div></body></html>

View File

@ -4,7 +4,7 @@ import { NavigationModel } from "./components/Index.js";
</script>
<template>
<div class="app-container bg-background">
<div class="app-containe">
<NavigationModel />
<div class="container px-3 mx-auto">
<router-view class="mt-4" />

View File

@ -1,57 +1,57 @@
<template>
<input class="search
text-black py-2 px-2 rounded mt-5"
v-model="input"
type="text"
placeholder="Search..." />
<input class="search " type="text" v-model="input" placeholder="Search..." />
<div class="flex">
<div class="exerciseList">
<ul class="exerciseItem" v-for="exercise in filterExercises()" :key="exercise.name">
<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>
<Button @click="exerciseClick(exercise)" class="btn bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4" >{{ exercise.name }}</Button>
</ul>
</div>
<div v-if="selectedExercise">
<WeightsInput :selectedExercise="selectedExercise"></WeightsInput>
<div v-show="isClicked" class="show">
<label> {{ exerciseName }}</label>
<WeightsInput/>
</div>
</div>
</template>
<script setup>
import { useExerciseStore } from '@/stores/storeExercise.js';
import { usePostStore } from '@/stores/store.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,
})
const json = useExerciseStore()
const weightInput = useWeightInputStore()
let isClicked = false
const json = usePostStore()
const exercises = ref([])
const selectedExercise = ref(null)
let exerciseName = ""
onMounted(async () => {
await json.fetchMuscleExercise()
switch (muscle.muscle) {
case "Legs":
exercises.value = json.exerciseList.muscle[0].exercises
exercises.value = json.postList.muscle[0].exercises
break;
case "Back":
exercises.value = json.exerciseList.muscle[1].exercises
exercises.value = json.postList.muscle[1].exercises
break;
case "Chest":
exercises.value = json.exerciseList.muscle[2].exercises
exercises.value = json.postList.muscle[2].exercises
break;
case "Shoulder":
exercises.value = json.exerciseList.muscle[3].exercises
exercises.value = json.postList.muscle[3].exercises
break;
case "Biceps":
exercises.value = json.exerciseList.muscle[4].exercises
exercises.value = json.postList.muscle[4].exercises
break;
case "Triceps":
exercises.value = json.exerciseList.muscle[5].exercises
exercises.value = json.postList.muscle[5].exercises
break;
}
}
@ -65,13 +65,16 @@
});
};
const exerciseClick = (exercise) => {
selectedExercise.value = exercise;
};
const showWeightInput = (isClicked) => {
isClicked.value = true
}
const exerciseClick = (exercise) => {
isClicked = true
exerciseName = exercise.name
console.log(isClicked)
}
const initSetInput = () => {
weightInput.initSetsInputs(selectedExercise.value);
};
</script>

View File

@ -25,7 +25,7 @@
width: 100%;
height: 4rem;
justify-content: start;
background: #0a0e06;
background: rgb(36, 165, 75);
}
.navbar-nav{
display: flex;
@ -36,16 +36,12 @@
.nav-item{
margin-left: 1rem;
margin-right: 1rem;
color: #e7f1df;
color: white;
text-decoration: none;
font-size: 1.2rem;
}
.nav-item:hover{
// color: rgb(91, 154, 102);
color: #699f65
color: orangered;
}
.logo{
display: flex;
}

22
src/stores/store.js Normal file
View File

@ -0,0 +1,22 @@
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

View File

@ -1,17 +0,0 @@
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
}
}
)

View File

@ -1,94 +0,0 @@
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
src/stores/storeWeight.js Normal file
View File

@ -0,0 +1,22 @@
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);
},
}
})

View File

@ -1,5 +1,5 @@
<template>
<div class="text-white">
<div class="text-3xl font-bold underline text-blue-500">
<h1>Back</h1>
<ExerciseList muscle="Back"/>
</div>

View File

@ -1,5 +1,5 @@
<template>
<div class="biceps text-text">
<div class="biceps">
<h1>Biceps</h1>
<ExerciseList muscle="Biceps"/>
</div>

View File

@ -1,9 +1,12 @@
<template>
<div class="text-white">
<div class="flex">
<div class="w-1/2">
<h1>Chest</h1>
<ExerciseList muscle="Chest"/>
</div>
<div>
<weightsInput/>
</div>
</div>
</template>

View File

@ -1,5 +1,5 @@
<template>
<div class="legs text-white">
<div class="legs">
<h1>Legs</h1>
<ExerciseList muscle="Legs"/>
</div>

View File

@ -1,5 +1,5 @@
<template>
<div class="shoulder text-white">
<div class="shoulder">
<h1>Shoulder</h1>
<ExerciseList muscle="Shoulder"/>
</div>

View File

@ -1,5 +1,5 @@
<template>
<div class="triceps text-white ">
<div class="triceps">
<h1>Triceps</h1>
<ExerciseList muscle="Triceps"/>
</div>

View File

@ -1,89 +1,87 @@
<template>
//TODO make view resposive on button click add
<div class="w-2/3 mx-auto">
<div class="mt-2">
<div class="warmup-sets mt-12 w-2/3">
<label>Warm-Up Sets</label>
<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>
<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>
<div class="working-set mt-5">
<label>Working Sets</label>
<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>
<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>
<div>
<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 v-for="(workingset, index) in workingInput.workingSets" class="item flex justify-smart mt-3" :key="index">
{{ workingset }}
<div class="ml-3">
<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'/>
<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"/>
</div>
<label>Reps</label>
<div class="ml-3">
<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 -->
<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">
</div>
</div>
</div>
</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>
</template>
<script setup>
import { useWeightInputStore } from '@/stores/storeInput';
import { ref } from 'vue';
import { useWeightStore } from '@/stores/storeWeight';
const selectedExercise = defineProps({
selectedExercise: String
});
let warmUpSetCount = 0;
let workingSetCount = 0;
const weightInput = useWeightInputStore();
weightInput.selectedExercise = ref(selectedExercise.selectedExercise);
const weight = useWeightStore();
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;

View File

@ -5,17 +5,7 @@ export default {
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
'primary-button':'#5b9a66',
// 'secondary-button':'#0d1406',
'secondary-button':'#699f65',
'background':'#131d0c',
'text': '#e7f1df',
'accent': '#361f47',
'accent2': '#63992e',
}
},
extend: {},
},
plugins: [],
}