fix(ui): ArrangementDialog drag whole box, persist changes across switch, hover highlight
- Remove drag handle restriction — entire pill box is now draggable - Keep local copy of arrangements so edits survive switching between arrangements (was reading stale props after switch-back) - Highlight corresponding left pill when hovering right lyric preview
This commit is contained in:
parent
78b8fc2e3d
commit
852231ae01
|
|
@ -89,20 +89,40 @@ async function assignSong() {
|
|||
|
||||
/* ── State ── */
|
||||
|
||||
// Local copy of arrangements so changes survive switching between arrangements
|
||||
const localArrangements = ref(JSON.parse(JSON.stringify(props.arrangements)))
|
||||
|
||||
watch(
|
||||
() => props.arrangements,
|
||||
(newArr) => {
|
||||
// Merge server updates (e.g. after create/clone/delete) but keep local edits for existing arrangements
|
||||
const localById = Object.fromEntries(localArrangements.value.map((a) => [a.id, a]))
|
||||
localArrangements.value = newArr.map((a) => localById[a.id] ?? JSON.parse(JSON.stringify(a)))
|
||||
// Add any new arrangements not in local
|
||||
for (const a of newArr) {
|
||||
if (!localById[a.id]) {
|
||||
localArrangements.value.push(JSON.parse(JSON.stringify(a)))
|
||||
}
|
||||
}
|
||||
},
|
||||
{ deep: true },
|
||||
)
|
||||
|
||||
const currentArrangementId = ref(
|
||||
props.selectedArrangementId ?? props.arrangements.find((a) => a.is_default)?.id ?? props.arrangements[0]?.id ?? null,
|
||||
)
|
||||
|
||||
const currentArrangement = computed(() =>
|
||||
props.arrangements.find((a) => a.id === Number(currentArrangementId.value)) ?? null,
|
||||
localArrangements.value.find((a) => a.id === Number(currentArrangementId.value)) ?? null,
|
||||
)
|
||||
|
||||
const arrangementGroups = ref([])
|
||||
const hoveredIndex = ref(null)
|
||||
|
||||
watch(
|
||||
currentArrangementId,
|
||||
(id) => {
|
||||
const arr = props.arrangements.find((a) => a.id === Number(id))
|
||||
const arr = localArrangements.value.find((a) => a.id === Number(id))
|
||||
if (arr?.groups?.length) {
|
||||
arrangementGroups.value = arr.groups.map((g, i) => ({ ...g, _uid: `${g.id}-${i}-${Date.now()}` }))
|
||||
} else {
|
||||
|
|
@ -212,6 +232,16 @@ function deleteArrangement() {
|
|||
|
||||
function saveArrangement() {
|
||||
if (!currentArrangement.value) return
|
||||
|
||||
// Update local arrangements copy so changes survive switching
|
||||
const localArr = localArrangements.value.find((a) => a.id === currentArrangement.value.id)
|
||||
if (localArr) {
|
||||
localArr.groups = arrangementGroups.value.map((g, i) => ({
|
||||
...g,
|
||||
order: i + 1,
|
||||
}))
|
||||
}
|
||||
|
||||
router.put(
|
||||
`/arrangements/${currentArrangement.value.id}`,
|
||||
{
|
||||
|
|
@ -454,7 +484,6 @@ function closeOnBackdrop(e) {
|
|||
ghost-class="drag-ghost"
|
||||
chosen-class="drag-chosen"
|
||||
drag-class="drag-active"
|
||||
handle=".drag-handle"
|
||||
class="flex flex-col gap-2"
|
||||
@end="saveArrangement"
|
||||
>
|
||||
|
|
@ -462,23 +491,13 @@ function closeOnBackdrop(e) {
|
|||
v-for="(element, index) in arrangementGroups"
|
||||
:key="element._uid"
|
||||
data-testid="arrangement-pill"
|
||||
class="flex items-center gap-2 rounded-lg border-2 px-3 py-2"
|
||||
class="flex cursor-grab items-center gap-2 rounded-lg border-2 px-3 py-2"
|
||||
:class="{ 'ring-2 ring-indigo-400 ring-offset-1': hoveredIndex === index }"
|
||||
:style="{
|
||||
borderColor: element.color ?? '#6b7280',
|
||||
backgroundColor: (element.color ?? '#6b7280') + '20',
|
||||
}"
|
||||
>
|
||||
<!-- Drag handle -->
|
||||
<span class="drag-handle cursor-grab text-gray-400 hover:text-gray-600">
|
||||
<svg
|
||||
class="h-4 w-4"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 20 20"
|
||||
>
|
||||
<path d="M7 2a2 2 0 10.001 4.001A2 2 0 007 2zm0 6a2 2 0 10.001 4.001A2 2 0 007 8zm0 6a2 2 0 10.001 4.001A2 2 0 007 14zm6-8a2 2 0 10-.001-4.001A2 2 0 0013 6zm0 2a2 2 0 10.001 4.001A2 2 0 0013 8zm0 6a2 2 0 10.001 4.001A2 2 0 0013 14z" />
|
||||
</svg>
|
||||
</span>
|
||||
|
||||
<!-- Group name -->
|
||||
<span class="flex-1 text-sm font-medium">
|
||||
{{ element.name }}
|
||||
|
|
@ -562,10 +581,13 @@ function closeOnBackdrop(e) {
|
|||
</h4>
|
||||
|
||||
<div
|
||||
v-for="element in arrangementGroups"
|
||||
v-for="(element, index) in arrangementGroups"
|
||||
:key="element._uid"
|
||||
class="rounded-r-lg border-l-4 bg-white p-3 shadow-sm"
|
||||
class="rounded-r-lg border-l-4 bg-white p-3 shadow-sm transition-shadow"
|
||||
:class="{ 'ring-2 ring-indigo-400 ring-offset-1': hoveredIndex === index }"
|
||||
:style="{ borderColor: element.color ?? '#6b7280' }"
|
||||
@mouseenter="hoveredIndex = index"
|
||||
@mouseleave="hoveredIndex = null"
|
||||
>
|
||||
<!-- Group name pill -->
|
||||
<span
|
||||
|
|
|
|||
Loading…
Reference in a new issue