Compare commits

..

14 Commits

Author SHA1 Message Date
roberts 71ce91cd35 resolved remove button issue 2023-06-03 18:25:46 +02:00
roberts f6f3ad8fa9 weightinput is now being displayed and the state is safed. TODO safe state for each exercise. 2023-06-02 18:10:43 +02:00
roberts 39e7f9daa7 reworkd the storeInput 2023-06-01 17:01:02 +02:00
roberts e9a696dcaa wip 2023-05-26 17:48:07 +02:00
roberts 054da6633e wip state management 2023-05-23 18:19:57 +02:00
roberts e68d999681 wip state management for the input 2023-05-21 18:20:17 +02:00
roberts 4c262ba076 added a remove button and fixed a bug where the input component was added to the view instead of getting a new one for the specifig exercise 2023-05-21 00:40:42 +02:00
roberts 0a677bf743 reworked color theme for the project 2023-05-19 08:34:03 +02:00
roberts 9bca0225dd added new color theme 2023-05-16 19:14:44 +02:00
rYeti 8a6c959240 state now working wip for individual exercise 2023-05-15 23:41:54 +02:00
roberts 3a98ef751f wip weightInput state 2023-05-14 18:02:48 +02:00
rYeti c44c3c4fb4 resolved binding error and added number validator for inputs 2023-05-14 01:20:43 +02:00
roberts dd3aa18cd4 added state for weightsinput 2023-05-13 17:45:02 +02:00
rYeti d305af0547 resovled binding issue 2023-05-11 16:30:42 +02:00
22 changed files with 258 additions and 154 deletions

16
TODOS Normal file
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
colors(1)/colors.txt Normal file
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!

BIN
colors(1)/palette.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

File diff suppressed because one or more lines are too long

2
dist/assets/index-4ea6f92e.js vendored Normal file

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-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>

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

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>

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;
}

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

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
src/stores/storeInput.js Normal file
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 }
}
)

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);
},
}
})

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>

View File

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

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>

View File

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

View File

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

View File

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

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>

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: [],
}