Create document picklist and refactor axios call

This commit is contained in:
2025-11-05 16:34:22 +01:00
parent 738f627f1f
commit b1c70c5fbf
7 changed files with 662 additions and 155 deletions

View File

@@ -0,0 +1,228 @@
<template>
<div class="dynamic-picker" :class="{ 'mt-4': !noMargin }">
<label :for="inputName" v-if="label">
<b>{{ label }}</b>
</label>
<div class="input-wrapper">
<!-- Video Groups MultiSelect -->
<MultiSelect
v-if="dataSource === 'videoGroups'"
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select VideoGroups'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
>
<template #option="slotProps">
<div class="flex align-items-center">
<i class="pi pi-video mr-2"></i>
<div>
<div>{{ slotProps.option.name }}</div>
<small class="text-muted" v-if="slotProps.option.description">
{{ slotProps.option.description }}
</small>
</div>
</div>
</template>
</MultiSelect>
<!-- KS Documents MultiSelect -->
<MultiSelect
v-else-if="dataSource === 'ksDocuments'"
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select Documents'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
>
<template #option="slotProps">
<div class="flex align-items-center">
<i :class="getFileIcon(slotProps.option)" class="mr-2"></i>
<div>
<div>{{ slotProps.option.fileName }}</div>
<small class="text-muted" v-if="slotProps.option.description">
{{ slotProps.option.description }}
</small>
</div>
</div>
</template>
</MultiSelect>
<!-- Dropdown per selezione singola -->
<Dropdown
v-else-if="multiple === false"
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select an option'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
/>
<!-- MultiSelect generico per altri tipi -->
<MultiSelect
v-else
v-model="selectedValue"
:options="options"
:filter="true"
:placeholder="placeholder || 'Select options'"
:disabled="disabled"
:loading="loading"
class="w-full md:w-80"
@change="onSelectionChange"
/>
</div>
<!-- Loading indicator -->
<div v-if="loading" class="text-sm text-gray-500 mt-1">
<i class="pi pi-spin pi-spinner mr-1"></i>
Loading options...
</div>
<!-- Error message -->
<div v-if="error" class="text-red-500 text-sm mt-1">
<i class="pi pi-exclamation-triangle mr-1"></i>
{{ error }}
</div>
<!-- Info message -->
<div v-if="options.length === 0 && !loading && !error" class="text-gray-500 text-sm mt-1">
<i class="pi pi-info-circle mr-1"></i>
No options available
</div>
</div>
</template>
<script setup>
import Dropdown from 'primevue/dropdown';
import MultiSelect from 'primevue/multiselect';
import { computed } from 'vue';
// Props
const props = defineProps({
modelValue: {
type: [Array, Object, String, Number],
default: null
},
inputName: {
type: String,
required: true
},
label: {
type: String,
default: ''
},
placeholder: {
type: String,
default: ''
},
dataSource: {
type: String,
required: true
},
options: {
type: Array,
default: () => []
},
disabled: {
type: Boolean,
default: false
},
loading: {
type: Boolean,
default: false
},
error: {
type: String,
default: ''
},
multiple: {
type: Boolean,
default: true
},
showStatus: {
type: Boolean,
default: false
},
noMargin: {
type: Boolean,
default: false
}
});
// Emits
const emit = defineEmits(['update:modelValue', 'change']);
// Computed
const selectedValue = computed({
get() {
return props.modelValue;
},
set(value) {
emit('update:modelValue', value);
}
});
const getFileIcon = (document) => {
if (!document) return 'pi pi-file';
const fileName = document.fileName || document.name || '';
const extension = fileName.toLowerCase().split('.').pop();
switch (extension) {
case 'pdf':
return 'pi pi-file-pdf text-red-500';
case 'doc':
return 'pi pi-file-word text-blue-500';
case 'docx':
return 'pi pi-file-word text-blue-500';
case 'xls':
return 'pi pi-file-excel text-green-500';
case 'xlsx':
return 'pi pi-file-excel text-green-500';
case 'txt':
return 'pi pi-file text-gray-500';
case 'ppt':
return 'pi pi-file text-red-500';
case 'pptx':
return 'pi pi-file text-red-500';
case 'json':
return 'pi pi-file text-orange-500';
case 'gif':
return 'pi pi-image text-purple-500';
case 'rar':
return 'pi pi-file-archive text-yellow-500';
default:
return 'pi pi-file text-gray-400';
}
};
const onSelectionChange = (event) => {
emit('change', event.value);
};
</script>
<style scoped>
.input-wrapper {
display: flex;
align-items: center;
gap: 0.5em;
margin-top: 10px;
}
.text-muted {
color: #6c757d;
}
</style>