implement the start and next to a record

This commit is contained in:
Julien Calixte
2023-04-10 19:44:03 +02:00
parent a934c51a2e
commit dcdd871025
3 changed files with 128 additions and 41 deletions

View File

@@ -1,5 +1,8 @@
<script setup lang="ts">
import { useTaskStore } from '@/modules/task/stores/useTask.store'
import { formatDate } from '@/shared/format-date'
import { toISODate } from '@/shared/types/date'
import { computed } from 'vue'
import { useTaskRecordStore } from '../stores/useTaskRecordStore'
const props = defineProps<{
@@ -10,23 +13,104 @@ const props = defineProps<{
const taskStore = useTaskStore()
const recordStore = useTaskRecordStore()
const task = taskStore.getTask(props.taskId)
const task = computed(() => taskStore.getTask(props.taskId))
const record = recordStore.createAndRetriveTaskRecord(
props.taskId,
props.recordId
const record = computed(() =>
recordStore.createAndRetrieveTaskRecord(props.taskId, props.recordId)
)
const getNextStepId = () => {
if (!task.value) {
return null
}
if (!recordStore.currentStepId) {
return task.value.steps[0].id
}
const currentStepIndex = task.value.steps.findIndex(
(step) => step.id === recordStore.currentStepId
)
const canHaveNextIndex =
currentStepIndex >= 0 && currentStepIndex < task.value.steps.length - 1
if (canHaveNextIndex) {
return task.value.steps[currentStepIndex + 1].id
}
return null
}
const startRecording = () => {
if (!task.value) {
return
}
recordStore.startStepRecord({
recordId: props.recordId,
stepId: task.value.steps[0].id,
start: toISODate(new Date())
})
}
const nextStep = () => {
if (!task.value || !recordStore.currentStepId) {
return
}
recordStore.nextStepRecord({
recordId: record.value.id,
currentStepId: recordStore.currentStepId,
nextStepId: getNextStepId(),
tick: toISODate(new Date())
})
}
</script>
<template>
<div class="task-record">
<pre>{{ task }}</pre>
<pre>{{ record }}</pre>
<div class="task-record" v-if="task">
<h1>Task: {{ task.title }}</h1>
<h2>start time: {{ formatDate(record.start) }}</h2>
<button v-if="!record.hasStepRecords" @click="startRecording">start</button>
<button v-else @click="nextStep">next</button>
<button @click="recordStore.$reset">reset</button>
<table>
<thead>
<tr>
<th>#</th>
<th>Task</th>
<th>estimation</th>
<th>actual</th>
</tr>
</thead>
<tbody>
<tr
v-for="(step, key) in task.steps"
:key="step.id"
:class="{ current: recordStore.currentStepId === step.id }"
>
<td>{{ key + 1 }}</td>
<td>{{ step.title }}</td>
<td class="estimation">{{ step.estimation }} minutes</td>
<td v-if="record.stepRecords[step.id]">
{{ record.stepRecords[step.id] }} minutes
</td>
<td v-else>NA</td>
</tr>
</tbody>
</table>
</div>
</template>
<style scoped lang="scss">
.task-record {
display: flex;
.current {
background-color: red;
}
.estimation {
font-style: italic;
}
}
</style>

View File

@@ -23,6 +23,10 @@ export class TaskRecord implements Recordable {
return Math.round(durationMilliseconds / (1000 * 60))
}
public get hasStepRecords() {
return Object.values(this.stepRecords).length > 0
}
public static fromRecordable(recordable: Recordable) {
const taskRecord = new TaskRecord(recordable.id, recordable.taskId)

View File

@@ -1,41 +1,25 @@
import type { ISODate } from '@/shared/types/date'
import { toISODate, type ISODate } from '@/shared/types/date'
import { defineStore } from 'pinia'
import type { Recordable } from '../interfaces/recordable'
import type { StepRecordable } from '../interfaces/step-recordable'
import { TaskRecord } from '../models/task-record'
type RecordId = string
export interface TaskRecordStoreState {
currentStepId: string | null
records: { [recordId: string]: Recordable }
taskRecordMaps: { [taskId: string]: RecordId[] }
}
export const useTaskRecordStore = defineStore('task-record-store', {
persist: true,
state: (): TaskRecordStoreState => ({
currentStepId: null,
records: {},
taskRecordMaps: {}
records: {}
}),
actions: {
addRecord(taskRecord: TaskRecord) {
if (!this.taskRecordMaps[taskRecord.taskId]) {
this.taskRecordMaps[taskRecord.taskId] = []
}
this.taskRecordMaps[taskRecord.taskId].push(taskRecord.id)
this.records[taskRecord.id] = taskRecord
},
removeRecord(recordId: string) {
for (const taskId in this.taskRecordMaps) {
this.taskRecordMaps[taskId] = this.taskRecordMaps[taskId].filter(
(rId) => rId !== recordId
)
}
delete this.records[recordId]
},
startStepRecord(params: {
@@ -49,11 +33,22 @@ export const useTaskRecordStore = defineStore('task-record-store', {
record.start = params.start
}
this.records[params.recordId].stepRecords[params.stepId] = {
this.$patch({
records: {
...this.records,
[params.recordId]: {
...record,
stepRecords: {
...record.stepRecords,
[params.stepId]: {
problems: [],
start: params.start
}
this.currentStepId = params.stepId
}
}
},
currentStepId: params.stepId
})
},
endStepRecord(params: { recordId: string; stepId: string; end: ISODate }) {
const stepRecord =
@@ -68,7 +63,7 @@ export const useTaskRecordStore = defineStore('task-record-store', {
nextStepRecord(params: {
recordId: string
currentStepId: string
nextStepId: string
nextStepId: string | null
tick: ISODate
}) {
this.endStepRecord({
@@ -76,13 +71,20 @@ export const useTaskRecordStore = defineStore('task-record-store', {
stepId: params.currentStepId,
end: params.tick
})
if (!params.nextStepId) {
this.endRecord(params.recordId)
return
}
this.startStepRecord({
recordId: params.recordId,
stepId: params.nextStepId,
start: params.tick
})
},
endRecord() {
endRecord(recordId: string) {
this.records[recordId].end = toISODate(new Date())
this.currentStepId = null
},
addProblemToStepRecord(recordId: string, stepId: string, problem: string) {
@@ -98,22 +100,19 @@ export const useTaskRecordStore = defineStore('task-record-store', {
getters: {
getTaskRecords() {
return (taskId: string): TaskRecord[] =>
this.taskRecordMaps?.[taskId]?.map((recordId) =>
TaskRecord.fromRecordable(this.records[recordId])
) ?? []
Object.values(this.records)
.filter((record) => record.taskId === taskId)
.map((record) => TaskRecord.fromRecordable(record))
},
createAndRetriveTaskRecord() {
createAndRetrieveTaskRecord() {
return (taskId: string, recordId: string): TaskRecord => {
const hasTaskRecord = this.taskRecordMaps[taskId]?.some(
(rId) => rId === recordId
)
const hasTaskRecord = !!this.records[recordId]
if (hasTaskRecord) {
return TaskRecord.fromRecordable(this.records[recordId])
}
const newTaskRecord = new TaskRecord(recordId, taskId)
this.taskRecordMaps[taskId]?.push(recordId)
this.records[recordId] = newTaskRecord
return newTaskRecord