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"> <script setup lang="ts">
import { useTaskStore } from '@/modules/task/stores/useTask.store' 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' import { useTaskRecordStore } from '../stores/useTaskRecordStore'
const props = defineProps<{ const props = defineProps<{
@@ -10,23 +13,104 @@ const props = defineProps<{
const taskStore = useTaskStore() const taskStore = useTaskStore()
const recordStore = useTaskRecordStore() const recordStore = useTaskRecordStore()
const task = taskStore.getTask(props.taskId) const task = computed(() => taskStore.getTask(props.taskId))
const record = recordStore.createAndRetriveTaskRecord( const record = computed(() =>
props.taskId, recordStore.createAndRetrieveTaskRecord(props.taskId, props.recordId)
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> </script>
<template> <template>
<div class="task-record"> <div class="task-record" v-if="task">
<pre>{{ task }}</pre> <h1>Task: {{ task.title }}</h1>
<pre>{{ record }}</pre> <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> </div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.task-record { .task-record {
display: flex; .current {
background-color: red;
}
.estimation {
font-style: italic;
}
} }
</style> </style>

View File

@@ -23,6 +23,10 @@ export class TaskRecord implements Recordable {
return Math.round(durationMilliseconds / (1000 * 60)) return Math.round(durationMilliseconds / (1000 * 60))
} }
public get hasStepRecords() {
return Object.values(this.stepRecords).length > 0
}
public static fromRecordable(recordable: Recordable) { public static fromRecordable(recordable: Recordable) {
const taskRecord = new TaskRecord(recordable.id, recordable.taskId) 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 { defineStore } from 'pinia'
import type { Recordable } from '../interfaces/recordable' import type { Recordable } from '../interfaces/recordable'
import type { StepRecordable } from '../interfaces/step-recordable' import type { StepRecordable } from '../interfaces/step-recordable'
import { TaskRecord } from '../models/task-record' import { TaskRecord } from '../models/task-record'
type RecordId = string
export interface TaskRecordStoreState { export interface TaskRecordStoreState {
currentStepId: string | null currentStepId: string | null
records: { [recordId: string]: Recordable } records: { [recordId: string]: Recordable }
taskRecordMaps: { [taskId: string]: RecordId[] }
} }
export const useTaskRecordStore = defineStore('task-record-store', { export const useTaskRecordStore = defineStore('task-record-store', {
persist: true, persist: true,
state: (): TaskRecordStoreState => ({ state: (): TaskRecordStoreState => ({
currentStepId: null, currentStepId: null,
records: {}, records: {}
taskRecordMaps: {}
}), }),
actions: { actions: {
addRecord(taskRecord: TaskRecord) { addRecord(taskRecord: TaskRecord) {
if (!this.taskRecordMaps[taskRecord.taskId]) {
this.taskRecordMaps[taskRecord.taskId] = []
}
this.taskRecordMaps[taskRecord.taskId].push(taskRecord.id)
this.records[taskRecord.id] = taskRecord this.records[taskRecord.id] = taskRecord
}, },
removeRecord(recordId: string) { removeRecord(recordId: string) {
for (const taskId in this.taskRecordMaps) {
this.taskRecordMaps[taskId] = this.taskRecordMaps[taskId].filter(
(rId) => rId !== recordId
)
}
delete this.records[recordId] delete this.records[recordId]
}, },
startStepRecord(params: { startStepRecord(params: {
@@ -49,11 +33,22 @@ export const useTaskRecordStore = defineStore('task-record-store', {
record.start = params.start 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: [], problems: [],
start: params.start start: params.start
} }
this.currentStepId = params.stepId }
}
},
currentStepId: params.stepId
})
}, },
endStepRecord(params: { recordId: string; stepId: string; end: ISODate }) { endStepRecord(params: { recordId: string; stepId: string; end: ISODate }) {
const stepRecord = const stepRecord =
@@ -68,7 +63,7 @@ export const useTaskRecordStore = defineStore('task-record-store', {
nextStepRecord(params: { nextStepRecord(params: {
recordId: string recordId: string
currentStepId: string currentStepId: string
nextStepId: string nextStepId: string | null
tick: ISODate tick: ISODate
}) { }) {
this.endStepRecord({ this.endStepRecord({
@@ -76,13 +71,20 @@ export const useTaskRecordStore = defineStore('task-record-store', {
stepId: params.currentStepId, stepId: params.currentStepId,
end: params.tick end: params.tick
}) })
if (!params.nextStepId) {
this.endRecord(params.recordId)
return
}
this.startStepRecord({ this.startStepRecord({
recordId: params.recordId, recordId: params.recordId,
stepId: params.nextStepId, stepId: params.nextStepId,
start: params.tick start: params.tick
}) })
}, },
endRecord() { endRecord(recordId: string) {
this.records[recordId].end = toISODate(new Date())
this.currentStepId = null this.currentStepId = null
}, },
addProblemToStepRecord(recordId: string, stepId: string, problem: string) { addProblemToStepRecord(recordId: string, stepId: string, problem: string) {
@@ -98,22 +100,19 @@ export const useTaskRecordStore = defineStore('task-record-store', {
getters: { getters: {
getTaskRecords() { getTaskRecords() {
return (taskId: string): TaskRecord[] => return (taskId: string): TaskRecord[] =>
this.taskRecordMaps?.[taskId]?.map((recordId) => Object.values(this.records)
TaskRecord.fromRecordable(this.records[recordId]) .filter((record) => record.taskId === taskId)
) ?? [] .map((record) => TaskRecord.fromRecordable(record))
}, },
createAndRetriveTaskRecord() { createAndRetrieveTaskRecord() {
return (taskId: string, recordId: string): TaskRecord => { return (taskId: string, recordId: string): TaskRecord => {
const hasTaskRecord = this.taskRecordMaps[taskId]?.some( const hasTaskRecord = !!this.records[recordId]
(rId) => rId === recordId
)
if (hasTaskRecord) { if (hasTaskRecord) {
return TaskRecord.fromRecordable(this.records[recordId]) return TaskRecord.fromRecordable(this.records[recordId])
} }
const newTaskRecord = new TaskRecord(recordId, taskId) const newTaskRecord = new TaskRecord(recordId, taskId)
this.taskRecordMaps[taskId]?.push(recordId)
this.records[recordId] = newTaskRecord this.records[recordId] = newTaskRecord
return newTaskRecord return newTaskRecord