fix: ai audit improvements

This commit is contained in:
2026-08-22 23:16:06 +02:00
parent c6e45cd067
commit 9b7c83532b
12 changed files with 296 additions and 120 deletions
+2 -1
View File
@@ -38,7 +38,8 @@ function handleConfirm() {
</div>
<p class="modal-description">
Are you sure you want to delete this list? This action cannot be undone and all items in this list will be deleted.
Are you sure you want to delete this list? This action cannot be undone and all items in
this list will be deleted.
</p>
<div class="modal-footer">
+10 -20
View File
@@ -1,10 +1,9 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { computed } from 'vue'
import { RouterLink } from 'vue-router'
import type { LocalList } from '@/database/db'
import { useListsStore } from '@/stores/lists'
import { useClickOutside } from '@/composables/useClickOutside'
import { useEscapeKey } from '@/composables/useEscapeKey'
import { useDismissableMenu } from '@/composables/useDismissableMenu'
const props = defineProps<{ list: LocalList }>()
const emit = defineEmits<{
@@ -13,8 +12,11 @@ const emit = defineEmits<{
}>()
const listsStore = useListsStore()
const isMenuOpen = ref(false)
const menuContainerRef = ref<HTMLElement | null>(null)
const {
isOpen: isMenuOpen,
containerRef: menuContainerRef,
toggle: toggleMenu,
} = useDismissableMenu()
// The server always reports total_items/completed_items once a list has
// synced at least once, so the common case never touches the store's full
@@ -31,19 +33,6 @@ const completedCount = computed(() =>
: listsStore.itemsForList(props.list.id).filter((item) => item.is_completed).length,
)
useClickOutside(menuContainerRef, () => {
isMenuOpen.value = false
})
useEscapeKey(() => {
if (isMenuOpen.value) isMenuOpen.value = false
})
function toggleMenu(event: Event) {
event.preventDefault()
event.stopPropagation()
isMenuOpen.value = !isMenuOpen.value
}
function handleShare(event: Event) {
event.preventDefault()
event.stopPropagation()
@@ -57,7 +46,6 @@ function handleDelete(event: Event) {
isMenuOpen.value = false
emit('delete', props.list)
}
</script>
<template>
@@ -125,7 +113,9 @@ function handleDelete(event: Event) {
stroke-linejoin="round"
>
<polyline points="3 6 5 6 21 6" />
<path 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" />
<path
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 x1="10" y1="11" x2="10" y2="17" />
<line x1="14" y1="11" x2="14" y2="17" />
</svg>
+18 -24
View File
@@ -2,26 +2,25 @@
import { ref } from 'vue'
import type { LocalListItem } from '@/database/db'
import { useListsStore } from '@/stores/lists'
import { useClickOutside } from '@/composables/useClickOutside'
import { useEscapeKey } from '@/composables/useEscapeKey'
import { useDismissableMenu } from '@/composables/useDismissableMenu'
const props = defineProps<{ item: LocalListItem }>()
const emit = defineEmits<{
delete: [item: LocalListItem]
}>()
const listsStore = useListsStore()
const isEditing = ref(false)
const editedTitle = ref(props.item.title)
const isMenuOpen = ref(false)
const menuContainerRef = ref<HTMLElement | null>(null)
useClickOutside(menuContainerRef, () => {
isMenuOpen.value = false
})
useEscapeKey(() => {
if (isMenuOpen.value) isMenuOpen.value = false
})
// Captured separately from `editedTitle` at the moment editing starts: if the
// item is updated remotely (another device) while the field is open,
// `props.item.title` moves but this doesn't, so saveTitle() can tell "user
// didn't touch it" apart from "server changed underneath us" instead of
// diffing against the live (possibly just-changed) prop and overwriting the
// remote edit with the untouched original text.
const originalTitle = ref(props.item.title)
const {
isOpen: isMenuOpen,
containerRef: menuContainerRef,
toggle: toggleMenu,
} = useDismissableMenu()
function toggleCompleted() {
listsStore.setListItemCompleted(props.item.id, !props.item.is_completed)
@@ -29,31 +28,24 @@ function toggleCompleted() {
function startEditing() {
editedTitle.value = props.item.title
originalTitle.value = props.item.title
isEditing.value = true
}
function saveTitle() {
const title = editedTitle.value.trim()
if (title && title !== props.item.title) {
if (title && title !== originalTitle.value) {
listsStore.updateListItem(props.item.id, { title })
}
isEditing.value = false
}
function toggleMenu(event: Event) {
event.preventDefault()
event.stopPropagation()
isMenuOpen.value = !isMenuOpen.value
}
function handleDelete(event: Event) {
event.preventDefault()
event.stopPropagation()
isMenuOpen.value = false
emit('delete', props.item)
listsStore.deleteListItem(props.item.id)
}
</script>
<template>
@@ -114,7 +106,9 @@ function handleDelete(event: Event) {
stroke-linejoin="round"
>
<polyline points="3 6 5 6 21 6" />
<path 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" />
<path
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 x1="10" y1="11" x2="10" y2="17" />
<line x1="14" y1="11" x2="14" y2="17" />
</svg>
@@ -65,8 +65,6 @@ describe('ListItemRow', () => {
await wrapper.find('.submenu-item-danger').trigger('click')
expect(deleteSpy).toHaveBeenCalledWith('item-1')
expect(wrapper.emitted('delete')).toBeTruthy()
expect(wrapper.emitted('delete')?.[0]).toEqual([sampleItem])
expect(wrapper.find('.submenu-dropdown').exists()).toBe(false)
})
})