update frontend ui, i18n, filters, and deps
This commit is contained in:
58
frontend/components/EmplacementPicker.vue
Normal file
58
frontend/components/EmplacementPicker.vue
Normal file
@@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<label style="display: grid; gap: 6px;">
|
||||
<span>{{ t('labels.emplacement') }}</span>
|
||||
<select v-model="selectedId">
|
||||
<option value="">{{ t('labels.chooseEmplacement') }}</option>
|
||||
<option v-for="opt in options" :key="opt.id" :value="opt.id">
|
||||
{{ opt.label }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { t } = useI18n()
|
||||
|
||||
type Emplacement = {
|
||||
id: string
|
||||
nom: string
|
||||
parent_id?: string | null
|
||||
}
|
||||
|
||||
type Option = { id: string; label: string }
|
||||
|
||||
const props = defineProps<{
|
||||
items: Emplacement[]
|
||||
modelValue: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void
|
||||
}>()
|
||||
|
||||
const selectedId = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (value) => emit('update:modelValue', value)
|
||||
})
|
||||
|
||||
const options = computed<Option[]>(() => {
|
||||
const map = new Map(props.items.map((item) => [item.id, item]))
|
||||
const cache = new Map<string, number>()
|
||||
|
||||
const depthOf = (item: Emplacement): number => {
|
||||
if (!item.parent_id) return 0
|
||||
if (cache.has(item.id)) return cache.get(item.id) || 0
|
||||
const parent = map.get(item.parent_id)
|
||||
const depth = parent ? depthOf(parent) + 1 : 0
|
||||
cache.set(item.id, depth)
|
||||
return depth
|
||||
}
|
||||
|
||||
return props.items
|
||||
.map((item) => ({
|
||||
id: item.id,
|
||||
label: `${' '.repeat(depthOf(item) * 2)}${item.nom}`
|
||||
}))
|
||||
.sort((a, b) => a.label.localeCompare(b.label))
|
||||
})
|
||||
</script>
|
||||
Reference in New Issue
Block a user