Skip to content

Commit ba5dd33

Browse files
committed
fix: photo/note reordering
1 parent 11cb7aa commit ba5dd33

4 files changed

Lines changed: 21 additions & 13 deletions

File tree

src/composables/useNotes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ export function useNotes(houseId: number) {
4343
}
4444

4545
async function reorder(items: { id: number; sortOrder: number }[]): Promise<void> {
46-
await api.reorderNotes(houseId, items)
46+
// Apply optimistically so there's no visual jump while the API call is in flight.
4747
const map = new Map(items.map((i) => [i.id, i.sortOrder]))
4848
notes.value = notes.value
4949
.map((n) => (map.has(n.id) ? { ...n, sortOrder: map.get(n.id)! } : n))
5050
.sort((a, b) => a.sortOrder - b.sortOrder)
51+
await api.reorderNotes(houseId, items)
5152
}
5253

5354
return { notes, loading, error, load, create, update, remove, reorder }

src/composables/usePhotos.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ describe('usePhotos', () => {
128128
const result = await wall.upload(file, 5)
129129

130130
expect(mockApi.uploadPhoto).toHaveBeenCalledWith(1, file, 5, null, expect.any(Function))
131-
expect(result).toEqual(newPhoto)
131+
expect(result.id).toBe(newPhoto.id)
132132
expect(wall.photos.value).toHaveLength(1)
133-
expect(wall.photos.value[0]).toEqual(newPhoto)
133+
expect(wall.photos.value[0].id).toBe(newPhoto.id)
134134
})
135135
})
136136

src/composables/usePhotos.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ export function usePhotos(houseId: number) {
3333
}
3434

3535
const rootPhotos = computed(() =>
36-
photos.value.filter((p) => p.folderId === null).sort((a, b) => b.createdAt - a.createdAt),
36+
photos.value.filter((p) => p.folderId === null).sort((a, b) => a.sortOrder - b.sortOrder),
3737
)
3838

3939
function photosInFolder(folderId: number): Photo[] {
4040
return photos.value
4141
.filter((p) => p.folderId === folderId)
42-
.sort((a, b) => b.createdAt - a.createdAt)
42+
.sort((a, b) => a.sortOrder - b.sortOrder)
4343
}
4444

4545
// ----- Photos -----
@@ -56,8 +56,12 @@ export function usePhotos(houseId: number) {
5656
const created = await api.uploadPhoto(houseId, file, folderId, null, (progress) => {
5757
uploads.value = uploads.value.map((u) => (u.id === entry.id ? { ...u, progress } : u))
5858
})
59-
photos.value = [...photos.value, created]
60-
return created
59+
// Place new photo first by giving it a sortOrder below the current minimum.
60+
const siblings = photos.value.filter((p) => p.folderId === (folderId ?? null))
61+
const minSort = siblings.length > 0 ? Math.min(...siblings.map((p) => p.sortOrder)) : 0
62+
const placed = { ...created, sortOrder: minSort - 1 }
63+
photos.value = [...photos.value, placed]
64+
return placed
6165
} finally {
6266
uploads.value = uploads.value.filter((u) => u.id !== entry.id)
6367
}
@@ -77,12 +81,12 @@ export function usePhotos(houseId: number) {
7781
}
7882

7983
async function reorderPhotos(items: { id: number; sortOrder: number }[]): Promise<void> {
80-
await api.reorderPhotos(houseId, items)
81-
// Apply locally
84+
// Apply optimistically so there's no visual jump while the API call is in flight.
8285
const map = new Map(items.map((i) => [i.id, i.sortOrder]))
8386
photos.value = photos.value
8487
.map((p) => (map.has(p.id) ? { ...p, sortOrder: map.get(p.id)! } : p))
8588
.sort((a, b) => a.sortOrder - b.sortOrder)
89+
await api.reorderPhotos(houseId, items)
8690
}
8791

8892
// ----- Folders -----
@@ -109,11 +113,11 @@ export function usePhotos(houseId: number) {
109113
}
110114

111115
async function reorderFolders(items: { id: number; sortOrder: number }[]): Promise<void> {
112-
await api.reorderFolders(houseId, items)
113116
const map = new Map(items.map((i) => [i.id, i.sortOrder]))
114117
folders.value = folders.value
115118
.map((f) => (map.has(f.id) ? { ...f, sortOrder: map.get(f.id)! } : f))
116119
.sort((a, b) => a.sortOrder - b.sortOrder)
120+
await api.reorderFolders(houseId, items)
117121
}
118122

119123
return {

src/views/NotesView.vue

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,18 +174,21 @@ async function commitReorder() {
174174
await reorder(items)
175175
}
176176
177-
// Capture-phase listeners
177+
// Capture-phase listeners — commit the reorder on drop, reset on dragend.
178178
function onDropCapture() {
179+
commitReorder()
180+
}
181+
function onDragEndCapture() {
179182
draggingNoteId.value = null
180183
dropIndex.value = null
181184
}
182185
onMounted(() => {
183186
wallRef.value?.addEventListener('drop', onDropCapture, true)
184-
wallRef.value?.addEventListener('dragend', onDropCapture, true)
187+
wallRef.value?.addEventListener('dragend', onDragEndCapture, true)
185188
})
186189
onBeforeUnmount(() => {
187190
wallRef.value?.removeEventListener('drop', onDropCapture, true)
188-
wallRef.value?.removeEventListener('dragend', onDropCapture, true)
191+
wallRef.value?.removeEventListener('dragend', onDragEndCapture, true)
189192
})
190193
191194
// ----- Create / Edit -----

0 commit comments

Comments
 (0)