diff --git a/frontend/src/components/routine/RoutineEditView.vue b/frontend/src/components/routine/RoutineEditView.vue index ca08c51..d6b77f3 100644 --- a/frontend/src/components/routine/RoutineEditView.vue +++ b/frontend/src/components/routine/RoutineEditView.vue @@ -26,6 +26,7 @@ v-for="(item, idx) in items" :key="item.id || `new-${idx}`" class="item-row" + :data-idx="idx" :class="{ 'drag-over': dragOverIdx === idx, dragging: draggingIdx === idx }" draggable="true" @dragstart="(e) => onDragStart(e, idx)" @@ -33,7 +34,7 @@ @drop.prevent="onDrop(idx)" @dragend="onDragEnd" > - +
{ + moveEvt.preventDefault() + const touch = moveEvt.touches[0] + const el = document.elementFromPoint(touch.clientX, touch.clientY) as Element | null + if (!el) return + const row = el.closest('[data-idx]') as HTMLElement | null + if (!row) return + const rowIdx = parseInt(row.dataset.idx ?? '-1') + if (rowIdx !== -1 && rowIdx !== draggingIdx.value) { + dragOverIdx.value = rowIdx + } + } + + const handleTouchEnd = (endEvt: TouchEvent) => { + const touch = endEvt.changedTouches[0] + const el = document.elementFromPoint(touch.clientX, touch.clientY) as Element | null + const fromIdx = draggingIdx.value + if (el && fromIdx !== null) { + const row = el.closest('[data-idx]') as HTMLElement | null + if (row) { + const toIdx = parseInt(row.dataset.idx ?? '-1') + if (toIdx !== -1 && toIdx !== fromIdx) { + const moved = items.value.splice(fromIdx, 1)[0] + items.value.splice(toIdx, 0, moved) + normalizeItemOrder() + } + } + } + draggingIdx.value = null + dragOverIdx.value = null + document.removeEventListener('touchmove', handleTouchMove) + document.removeEventListener('touchend', handleTouchEnd) + } + + document.addEventListener('touchmove', handleTouchMove, { passive: false }) + document.addEventListener('touchend', handleTouchEnd) +} + async function uploadImage(file: File): Promise { const formData = new FormData() formData.append('file', file) @@ -541,6 +584,13 @@ function handleCancel() { cursor: grabbing; } +@media (hover: none) { + .drag-handle { + padding: 0.5rem 0.6rem; + font-size: 1.4rem; + } +} + .item-left { display: flex; align-items: center;