Added an option to reset timers daily

This commit is contained in:
2021-11-06 01:50:05 +03:00
parent 6cd4a91ec7
commit 9f07a0897f
13 changed files with 143 additions and 8 deletions

3
src/assets/cross.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16">
<path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>
</svg>

After

Width:  |  Height:  |  Size: 332 B

4
src/assets/gear.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#f7f7f7" class="bi bi-gear" viewBox="0 0 16 16">
<path d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"/>
<path d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -1 +1,3 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="512px" id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M224,435.8V76.1c0-6.7-5.4-12.1-12.2-12.1h-71.6c-6.8,0-12.2,5.4-12.2,12.1v359.7c0,6.7,5.4,12.2,12.2,12.2h71.6 C218.6,448,224,442.6,224,435.8z"/><path d="M371.8,64h-71.6c-6.7,0-12.2,5.4-12.2,12.1v359.7c0,6.7,5.4,12.2,12.2,12.2h71.6c6.7,0,12.2-5.4,12.2-12.2V76.1 C384,69.4,378.6,64,371.8,64z"/></g></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-pause-fill" viewBox="0 0 16 16">
<path d="M5.5 3.5A1.5 1.5 0 0 1 7 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5zm5 0A1.5 1.5 0 0 1 12 5v6a1.5 1.5 0 0 1-3 0V5a1.5 1.5 0 0 1 1.5-1.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 664 B

After

Width:  |  Height:  |  Size: 289 B

View File

@@ -1 +1,3 @@
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="512px" id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" width="512px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M405.2,232.9L126.8,67.2c-3.4-2-6.9-3.2-10.9-3.2c-10.9,0-19.8,9-19.8,20H96v344h0.1c0,11,8.9,20,19.8,20 c4.1,0,7.5-1.4,11.2-3.4l278.1-165.5c6.6-5.5,10.8-13.8,10.8-23.1C416,246.7,411.8,238.5,405.2,232.9z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-play-fill" viewBox="0 0 16 16">
<path d="m11.596 8.697-6.363 3.692c-.54.313-1.233-.066-1.233-.697V4.308c0-.63.692-1.01 1.233-.696l6.363 3.692a.802.802 0 0 1 0 1.393z"/>
</svg>

Before

Width:  |  Height:  |  Size: 566 B

After

Width:  |  Height:  |  Size: 273 B

View File

@@ -1 +1,4 @@
<?xml version="1.0" ?><svg fill="none" height="24" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><polyline stroke="#f7f7f7" points="3 6 5 6 21 6"/><path stroke="#f7f7f7" d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><line stroke="#f7f7f7" x1="10" x2="10" y1="11" y2="17"/><line stroke="#f7f7f7" x1="14" x2="14" y1="11" y2="17"/></svg> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#f7f7f7" class="bi bi-trash" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg>

Before

Width:  |  Height:  |  Size: 470 B

After

Width:  |  Height:  |  Size: 568 B

View File

@@ -6,7 +6,7 @@
> >
<div class="bg" @click="close" /> <div class="bg" @click="close" />
<div class="window"> <div class="window">
<div class="close" @click="close">×</div> <div class="close" @click="close"><img src="@/assets/cross.svg" /></div>
<slot /> <slot />
</div> </div>
</div> </div>
@@ -79,6 +79,7 @@ export default {
width: 100%; width: 100%;
bottom: 0; bottom: 0;
top: unset; top: unset;
padding-bottom: 32px;
box-sizing: border-box; box-sizing: border-box;
border-radius: 16px 16px 0 0; border-radius: 16px 16px 0 0;
transform: translate(0, 0); transform: translate(0, 0);

View File

@@ -0,0 +1,53 @@
<template>
<Modal ref="modal">
<div class="title">Settings</div>
<div class="setting">
<input type="checkbox" id="reset" v-model="resetAtMidnight">
<label for="reset">Reset all tasks to 0 at midnight</label>
</div>
</Modal>
</template>
<script>
import { mapState, mapMutations } from 'vuex';
import Modal from '@/components/Modal.vue';
export default {
components: {
Modal,
},
data() {
return {
resetAtMidnight: undefined,
};
},
computed: {
...mapState(['midnightReset']),
},
watch: {
resetAtMidnight(newVal) {
this.setMidnightReset(newVal);
},
},
beforeMount() {
this.resetAtMidnight = this.midnightReset;
},
methods: {
...mapMutations(['setMidnightReset']),
open() {
this.$refs.modal.open();
},
},
};
</script>
<style lang="scss" scoped>
.setting {
margin-top: 16px;
label {
margin-left: 16px;
}
}
</style>

View File

@@ -19,9 +19,15 @@
@click="selectCategory(category)" @click="selectCategory(category)"
> >
{{ category }} {{ category }}
<span @click.stop="removeCategory(category)">×</span> <span @click.stop="removeCategory(category)"><img src="@/assets/cross.svg" /></span>
</div> </div>
</div> </div>
<div class="settings" @click="openSettings">
<img src="@/assets/gear.svg" />
</div>
<SettingsModal ref="settingsModal" />
</div> </div>
</template> </template>
@@ -29,7 +35,12 @@
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import toColor from '@/stringToColor'; import toColor from '@/stringToColor';
import SettingsModal from './SettingsModal.vue';
export default { export default {
components: {
SettingsModal,
},
data() { data() {
return { return {
newCategory: '+', newCategory: '+',
@@ -68,6 +79,9 @@ export default {
} }
this.$emit('select', this.selectedCategory); this.$emit('select', this.selectedCategory);
}, },
openSettings() {
this.$refs.settingsModal.open();
},
}, },
computed: { computed: {
...mapState({ ...mapState({
@@ -89,6 +103,7 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
padding: 0 64px; padding: 0 64px;
box-sizing: border-box;
.add-category { .add-category {
color: $darker; color: $darker;
@@ -106,7 +121,7 @@ export default {
.categories { .categories {
display: flex; display: flex;
margin-left: 32px; margin: 0 32px;
overflow-x: scroll; overflow-x: scroll;
.category { .category {
@@ -118,11 +133,33 @@ export default {
} }
} }
} }
.settings {
position: absolute;
right: 64px;
height: 32px;
width: 32px;
cursor: pointer;
> * {
height: inherit;
}
}
} }
@media screen and (max-width: $max-width) { @media screen and (max-width: $max-width) {
.category-bar { .category-bar {
padding: 0 0 0 8px; padding: 0 0 0 8px;
.categories {
margin-right: 0;
}
.settings {
position: fixed;
bottom: 8px;
right: 8px;
}
} }
} }
</style> </style>

View File

@@ -30,6 +30,7 @@
.category { .category {
border-radius: 16px; border-radius: 16px;
height: 1rem;
padding: 6px 12px; padding: 6px 12px;
cursor: pointer; cursor: pointer;
display: flex; display: flex;
@@ -38,7 +39,10 @@
color: $darker; color: $darker;
span { span {
width: 16px;
height: 16px;
margin-left: 4px; margin-left: 4px;
vertical-align: middle;
} }
} }
} }

View File

@@ -10,7 +10,7 @@ export default createStore({
categories: [], categories: [],
tasks: [], tasks: [],
midnightReset: false, midnightReset: false,
lastReset: undefined, lastReset: new Date(),
darkTheme: true, darkTheme: true,
}, },
mutations: { mutations: {
@@ -77,6 +77,16 @@ export default createStore({
return newTask; return newTask;
}); });
}, },
resetTasks(state) {
state.tasks = state.tasks.map((task) => {
const newTask = task;
newTask.running = false;
newTask.totalTime = 0;
newTask.startedAt = undefined;
return newTask;
});
state.lastReset = new Date();
},
setMidnightReset(state, value) { setMidnightReset(state, value) {
state.midnightReset = !!value; state.midnightReset = !!value;

View File

@@ -6,6 +6,8 @@
</template> </template>
<script> <script>
import { mapState, mapMutations } from 'vuex';
import TheCategoryBar from '@/components/TheCategoryBar.vue'; import TheCategoryBar from '@/components/TheCategoryBar.vue';
import TheTaskList from './TheTaskList.vue'; import TheTaskList from './TheTaskList.vue';
@@ -20,7 +22,18 @@ export default {
selectedCategory: undefined, selectedCategory: undefined,
}; };
}, },
computed: {
...mapState(['midnightReset', 'lastReset']),
},
beforeMount() {
const lastMidnight = new Date();
lastMidnight.setHours(0, 0, 0, 0);
if (this.midnightReset && this.lastReset < lastMidnight) {
this.resetTasks();
}
},
methods: { methods: {
...mapMutations(['resetTasks']),
select(category) { select(category) {
this.selectedCategory = category; this.selectedCategory = category;
}, },

View File

@@ -23,7 +23,7 @@
:style="{ background: stringToColor(task.category) }" :style="{ background: stringToColor(task.category) }"
> >
{{ task.category }} {{ task.category }}
<span @click="removeCategory">×</span> <span @click="removeCategory"><img src="@/assets/cross.svg" /></span>
</div> </div>
<div v-else class="select-category" @click="$refs.categorySelect.open"> <div v-else class="select-category" @click="$refs.categorySelect.open">
Assign Category Assign Category

View File

@@ -3,6 +3,9 @@ module.exports = {
? '/worktime/' ? '/worktime/'
: '/', : '/',
pwa: { pwa: {
appleMobileWebAppCapable: 'yes',
appleMobileWebAppStatusBarStyle: 'black-transculent',
themeColor: '#252525',
workboxOptions: { workboxOptions: {
skipWaiting: true, skipWaiting: true,
clientsClaim: true, clientsClaim: true,