parsley/app/javascript/components/TaskItemList.vue

223 lines
5.6 KiB
Vue
Raw Normal View History

2018-09-05 17:49:21 -05:00
<template>
<div>
2018-09-13 14:51:41 -05:00
<div class="panel">
<p class="panel-heading">
{{taskList.name}} ({{completedItemCount}} / {{taskList.task_items.length}})
</p>
<div class="panel-block">
<button class="button is-fullwidth is-primary" @click="toggleShowAddItem">{{ showAddItem ? 'Done' : 'New Item' }}</button>
</div>
<app-expand-transition>
<div class="panel-block" v-if="showAddItem">
<task-item-edit @save="save" :task-item="newItem" ref="itemEdit"></task-item-edit>
</div>
</app-expand-transition>
<transition-group tag="div" name="list-item-move">
<a v-for="i in taskItems" :key="i.id" @click="toggleItem(i)" class="panel-block">
<div class="check">
<app-icon v-if="i.completed" icon="check"></app-icon>
<span class="icon" v-else></span>
</div>
<span>{{ i.quantity }} {{ i.name }}</span>
</a>
2018-09-12 17:17:15 -05:00
</transition-group>
2018-09-13 14:51:41 -05:00
<app-expand-transition>
<div class="panel-block" v-if="uncompletedItemCount > 0">
<button class="button is-fullwidth is-link" @click="completeAllItems">
<span class="check">
<app-icon icon="check"></app-icon>
</span>
<span>Check All</span>
</button>
</div>
</app-expand-transition>
<app-expand-transition>
<div class="panel-block" v-if="completedItemCount > 0">
<button class="button is-fullwidth is-link" @click="unCompleteAllItems">
<span class="check">
<span class="icon"></span>
</span>
<span>Uncheck All</span>
</button>
</div>
</app-expand-transition>
<app-expand-transition>
<div class="panel-block" v-if="completedItemCount > 0">
<button class="button is-fullwidth is-link" @click="deleteCompletedItems">
<app-icon icon="x" class="is-text-danger"></app-icon>
<span>Clear Completed</span>
</button>
</div>
</app-expand-transition>
</div>
2018-09-05 17:49:21 -05:00
</div>
</template>
<script>
2018-09-06 18:16:13 -05:00
import * as Errors from '../lib/Errors';
import { mapActions } from "pinia";
import { useTaskStore } from "../stores/task";
2018-09-06 18:16:13 -05:00
2018-09-05 17:49:21 -05:00
import TaskItemEdit from "./TaskItemEdit";
2018-09-06 18:16:13 -05:00
const newItemTemplate = function(listId) {
2018-09-05 17:49:21 -05:00
return {
2018-09-06 18:16:13 -05:00
task_list_id: listId,
2018-09-05 17:49:21 -05:00
name: '',
2018-09-06 18:16:13 -05:00
quantity: '',
completed: false
2018-09-05 17:49:21 -05:00
};
};
export default {
props: {
2018-09-06 18:16:13 -05:00
taskList: {
2018-09-05 17:49:21 -05:00
required: true,
2018-09-06 18:16:13 -05:00
type: Object
2018-09-05 17:49:21 -05:00
}
},
data() {
return {
showAddItem: false,
2018-09-06 18:16:13 -05:00
newItem: null,
2018-09-05 17:49:21 -05:00
newItemValidationErrors: {}
};
},
2018-09-06 18:16:13 -05:00
computed: {
2018-09-13 14:51:41 -05:00
completedItemCount() {
return this.taskList === null ? 0 : this.taskList.task_items.filter(i => i.completed).length;
},
uncompletedItemCount() {
return this.taskList === null ? 0 : this.taskList.task_items.filter(i => !i.completed).length;
},
2018-09-12 17:17:15 -05:00
completedTaskItems() {
return (this.taskList ? this.taskList.task_items : []).filter(i => i.completed);
},
uncompletedTaskItems() {
return (this.taskList ? this.taskList.task_items : []).filter(i => !i.completed);
},
2018-09-06 18:16:13 -05:00
taskItems() {
2018-09-12 17:17:15 -05:00
return this.uncompletedTaskItems.concat(this.completedTaskItems);
2018-09-06 18:16:13 -05:00
}
},
2018-09-05 17:49:21 -05:00
methods: {
...mapActions(useTaskStore, [
2018-09-06 18:16:13 -05:00
'createTaskItem',
2018-09-07 21:56:13 -05:00
'updateTaskItem',
2018-09-13 14:51:41 -05:00
'deleteTaskItems',
2018-09-07 21:56:13 -05:00
'completeTaskItems'
2018-09-06 18:16:13 -05:00
]),
save() {
this.loadResource(
this.createTaskItem(this.newItem)
.then(() => {
this.newItem = newItemTemplate(this.taskList.id);
this.$refs.itemEdit.focus();
})
.catch(Errors.onlyFor(Errors.ApiValidationError, err => this.newItemValidationErrors = err.validationErrors()))
)
},
toggleItem(i) {
this.loadResource(
2018-09-07 21:56:13 -05:00
this.completeTaskItems({
taskList: this.taskList,
taskItems: [i],
completed: !i.completed
})
);
2018-09-06 18:16:13 -05:00
},
2018-09-05 17:49:21 -05:00
toggleShowAddItem() {
2018-09-06 18:16:13 -05:00
this.newItem = newItemTemplate(this.taskList.id);
2018-09-05 17:49:21 -05:00
this.showAddItem = !this.showAddItem;
2018-09-13 14:51:41 -05:00
},
completeAllItems() {
const toComplete = this.taskList.task_items.filter(i => !i.completed);
this.loadResource(
this.completeTaskItems({
taskList: this.taskList,
taskItems: toComplete,
completed: true
})
)
},
unCompleteAllItems() {
const toUnComplete = this.taskList.task_items.filter(i => i.completed);
this.loadResource(
this.completeTaskItems({
taskList: this.taskList,
taskItems: toUnComplete,
completed: false
})
)
},
deleteCompletedItems() {
this.loadResource(
this.deleteTaskItems({
taskList: this.taskList,
taskItems: this.taskList.task_items.filter(i => i.completed)
})
);
},
2018-09-05 17:49:21 -05:00
},
components: {
TaskItemEdit
}
}
</script>
<style lang="scss" scoped>
.columns {
margin-top: 0;
margin-bottom: 0;
}
.column {
padding-top: 0;
padding-bottom: 0;
margin-top: 0;
margin-bottom: 0;
}
2018-09-13 14:51:41 -05:00
.check {
display: inline-flex;
margin-right: 1.5rem;
.icon {
position: relative;
&:after {
content: '';
position: absolute;
top: -3px;
left: -3px;
bottom: -3px;
right: -3px;
border: 2px solid currentColor;
}
}
2018-09-07 21:56:13 -05:00
}
2018-09-05 17:49:21 -05:00
</style>