feat: media page T1

This commit is contained in:
fsylvain committed 2026-10-01 01:36:35 +02:00
1 parent 67d456baf6
commit 008b0dfbb9
46 files changed
+5742 -204

No files matched your search

+67
View File
@@ -0,0 +1,67 @@
import { computed, ref, watch, type Ref } from 'vue'
import type { MediaItem } from '@/composables/useMedia'
export type SelectAllState = 'none' | 'partial' | 'all'
export function useMediaSelection(items: Ref<MediaItem[]>) {
const selectedIds = ref<number[]>([])
const count = computed(() => selectedIds.value.length)
const selectedItems = computed(() =>
items.value.filter((item) => selectedIds.value.includes(item.id)),
)
const allState = computed<SelectAllState>(() => {
if (count.value === 0) {
return 'none'
}
return count.value >= items.value.length ? 'all' : 'partial'
})
function isSelected(id: number) {
return selectedIds.value.includes(id)
}
function select(id: number) {
if (!isSelected(id)) {
selectedIds.value = [...selectedIds.value, id]
}
}
function toggle(id: number) {
selectedIds.value = isSelected(id)
? selectedIds.value.filter((entry) => entry !== id)
: [...selectedIds.value, id]
}
function replace(ids: number[]) {
selectedIds.value = ids
}
function clear() {
selectedIds.value = []
}
function toggleAll() {
selectedIds.value = allState.value === 'all' ? [] : items.value.map((item) => item.id)
}
watch(items, (loaded) => {
const kept = selectedIds.value.filter((id) => loaded.some((item) => item.id === id))
if (kept.length !== selectedIds.value.length) {
selectedIds.value = kept
}
})
return {
selectedIds,
selectedItems,
count,
allState,
isSelected,
select,
toggle,
replace,
clear,
toggleAll,
}
}