Skip to content

Commit

Permalink
feat: add edit task & records (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
antonreshetov authored Feb 15, 2024
1 parent 784ec94 commit 2beb049
Show file tree
Hide file tree
Showing 47 changed files with 1,288 additions and 42 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@
"electron-store": "^8.1.0",
"interactjs": "^1.10.26",
"lucide-vue-next": "^0.321.0",
"maska": "^2.1.11",
"nanoid": "^5.0.5",
"radix-vue": "^1.4.6",
"tailwind-merge": "^2.2.1",
"vue": "^3.4.15",
"vue-router": "^4.2.5"
Expand Down
6 changes: 6 additions & 0 deletions src/assets/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
body {
@apply text-neutral-800 dark:text-neutral-300 bg-white dark:bg-neutral-900 text-sm;
}

input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
}

:root {
Expand Down
62 changes: 52 additions & 10 deletions src/renderer/components/records/Item.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,72 @@
<script setup lang="ts">
import { format } from 'date-fns'
import { computed, watchEffect } from 'vue'
import { useRecords } from './composables'
import type { TaskRecordWithInfo } from '~/services/api/types'
import { timeFormat } from '@/utils'
import * as Popover from '@/components/ui/shadcn/popover'
interface Props {
data: TaskRecordWithInfo
}
defineProps<Props>()
const props = defineProps<Props>()
const { contextRecordId, isOpenEditMenu, editRecordId } = useRecords()
const isOpen = computed(
() => isOpenEditMenu.value && editRecordId.value === props.data.id,
)
function onUpdateOpen(bool: boolean) {
if (!bool) {
isOpenEditMenu.value = false
contextRecordId.value = ''
}
}
watchEffect(() => {
if (isOpen.value)
contextRecordId.value = props.data.id
})
</script>

<template>
<div
data-tracking-item
class="grid grid-cols-[60px_1fr_100px] gap-2 px-4 py-2 border-b border-neutral-200 dark:border-neutral-700 last:border-none"
:class="[
contextRecordId === data.id
? 'bg-neutral-100 dark:bg-neutral-800 '
: null,
]"
>
<div class="flex flex-col justify-between text-xs leading-normal relative">
<div>
<span v-if="!data.updatedAt"> now </span>
<span v-else>
{{ format(data.createdAt + data.duration * 1000, "HH:mm") }}
</span>
</div>
<div class="text-neutral-400 dark:text-neutral-500">
{{ format(data.createdAt, "HH:mm") }}
</div>
<Popover.Root
:open="isOpen"
@update:open="onUpdateOpen"
>
<Popover.Trigger
:as-child="true"
as="div"
>
<div>
<span v-if="!data.updatedAt"> now </span>
<span v-else>
{{ format(data.createdAt + data.duration * 1000, "HH:mm") }}
</span>
</div>
<div class="text-neutral-400 dark:text-neutral-500">
{{ format(data.createdAt, "HH:mm") }}
</div>
</Popover.Trigger>
<Popover.Content
side="left"
class="w-[300px]"
>
<RecordsEditMenu />
</Popover.Content>
</Popover.Root>
<div
class="absolute w-[2px] top-0 bottom-0 right-2"
:style="{ backgroundColor: data.color }"
Expand Down
76 changes: 70 additions & 6 deletions src/renderer/components/records/List.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,42 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useRecords } from '@/components/records/composables'
import { useTasks } from '@/components/tasks/composables'
import * as ContextMenu from '@/components/ui/shadcn/context-menu'
import * as Dialog from '@/components/ui/shadcn/dialog'
const { getTaskRecords, taskRecordsGroupedByCreatedDate } = useRecords()
const {
getTaskRecords,
taskRecordsGroupedByCreatedDate,
contextRecordId,
editRecordId,
isOpenEditMenu,
deleteTaskRecord,
} = useRecords()
const { stop, currentTaskItemId } = useTasks()
getTaskRecords()
const isConfirmOpen = ref(false)
function onClick(id: string) {
editRecordId.value = id
contextRecordId.value = id
}
function onOpen(bool: boolean) {
if (!bool)
contextRecordId.value = ''
}
function onDelete() {
if (currentTaskItemId.value === editRecordId.value)
stop()
deleteTaskRecord(editRecordId.value)
isConfirmOpen.value = false
}
</script>

<template>
Expand All @@ -25,12 +58,43 @@ getTaskRecords()
:date="k"
:records="v"
>
<RecordsItem
v-for="i in v"
:key="i.id"
:data="i"
/>
<ContextMenu.Root @update:open="onOpen">
<ContextMenu.Trigger>
<RecordsItem
v-for="i in v"
:key="i.id"
:data="i"
@contextmenu="onClick(i.id)"
/>
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item @click="isOpenEditMenu = true">
Edit..
</ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item @click="isConfirmOpen = true">
Delete
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
</RecordsGroup>
</div>
<Dialog.Root
:open="isConfirmOpen"
@update:open="isConfirmOpen = !isConfirmOpen"
>
<Dialog.Content class="w-[300px]">
<Dialog.Title>Are you sure you want to remove this entry?</Dialog.Title>
<UiButton
variant="primary"
@click="onDelete"
>
Delete
</UiButton>
<UiButton @click="isConfirmOpen = false">
Cancel
</UiButton>
</Dialog.Content>
</Dialog.Root>
</div>
</template>
17 changes: 17 additions & 0 deletions src/renderer/components/records/composables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ const { api } = window.electron
const { isStarted } = useTasks()

const taskRecords = shallowRef<TaskRecordWithInfo[]>([])
const editRecordId = ref<string>()
const contextRecordId = ref<string>()
const isOpenEditMenu = ref(false)

const editRecord = computed(() => {
return taskRecords.value.find(r => r.id === editRecordId.value)
})

const taskRecordSortedByDate = computed(() => {
return taskRecords.value.sort((a, b) => {
Expand Down Expand Up @@ -35,13 +42,23 @@ function getTaskRecords() {
taskRecords.value = api.getTaskRecords()
}

function deleteTaskRecord(id: string) {
api.deleteTaskRecord(id)
getTaskRecords()
}

watch(isStarted, () => {
getTaskRecords()
})

export function useRecords() {
return {
contextRecordId,
deleteTaskRecord,
editRecord,
editRecordId,
getTaskRecords,
isOpenEditMenu,
taskRecords,
taskRecordsGroupedByCreatedDate,
}
Expand Down
76 changes: 76 additions & 0 deletions src/renderer/components/records/edit/Menu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<script setup lang="ts">
import { onBeforeUnmount, reactive, ref, watchEffect } from 'vue'
import type { MaskaDetail } from 'maska'
import { vMaska } from 'maska'
import { useRecords } from '@/components/records/composables'
import { timeFormat, timeToSec } from '@/utils'
const { editRecord, getTaskRecords } = useRecords()
const { api } = window.electron
const duration = ref(editRecord.value.duration)
const lastSavedDuration = ref(editRecord.value.duration)
const durationFormatted = ref(timeFormat(editRecord.value.duration))
const description = ref(editRecord.value.description)
const lastSavedDescription = ref(editRecord.value.description)
const options = reactive({
mask: '##:##:##',
eager: true,
})
const mask = reactive<MaskaDetail>({
completed: false,
masked: '',
unmasked: '',
})
watchEffect(() => {
if (mask.completed)
duration.value = timeToSec(mask.masked)
})
onBeforeUnmount(() => {
if (duration.value !== lastSavedDuration.value) {
api.updateTaskRecord(editRecord.value.id, {
duration: duration.value,
})
getTaskRecords()
}
if (description.value !== lastSavedDescription.value) {
api.updateTaskRecord(editRecord.value.id, {
description: description.value,
})
getTaskRecords()
}
})
</script>

<template>
<div
data-record-edit-menu
class="p-2"
>
<div class="grid grid-cols-[70px_1fr] gap-4">
<div class="text-right">
Duration
</div>
<UiInput
v-model="durationFormatted"
v-maska:[options]="mask"
size="sm"
/>
<div class="text-right">
Notes
</div>
<UiInput
v-model="description"
size="sm"
type="textarea"
/>
</div>
</div>
</template>
Loading

0 comments on commit 2beb049

Please sign in to comment.