feat: add product document list (#64)

* feat: product => document select
This commit is contained in:
Methapon Metanipat 2024-11-08 10:22:50 +07:00 committed by GitHub
parent e501706e88
commit f3fdaac2b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 226 additions and 5 deletions

View file

@ -0,0 +1,192 @@
<script lang="ts" setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import SelectMenuWithSearch from '../shared/SelectMenuWithSearch.vue';
const { t } = useI18n();
defineProps<{
readonly?: boolean;
}>();
const attachment = defineModel<string[]>('attachment', { default: [] });
const mapName = (val: string): string => {
const name = options.value.find((v) => v.value === val);
return name ? name.label : '';
};
const objectOptions = [
{
label: 'customerEmployee.fileType.passport',
value: 'passport',
},
{
label: 'customerEmployee.fileType.visa',
value: 'visa',
},
{
label: 'customerEmployee.fileType.tm6',
value: 'tm6',
},
{
label: 'customerEmployee.fileType.workPermit',
value: 'workPermit',
},
{
label: 'customerEmployee.fileType.noticeJobEmployment',
value: 'noticeJobEmployment',
},
{
label: 'customerEmployee.fileType.noticeJobEntry',
value: 'noticeJobEntry',
},
{
label: 'customerEmployee.fileType.historyJob',
value: 'historyJob',
},
{
label: 'customerEmployee.fileType.acceptJob',
value: 'acceptJob',
},
];
const options = ref(objectOptions);
function selectAttachment(val: Record<string, unknown>) {
const existIndex = attachment.value.findIndex((p) => p === val.value);
if (existIndex === -1) {
attachment.value.push(val.value as string);
} else {
attachment.value.splice(Number(existIndex), 1);
}
}
function selectAll() {
if (attachment.value.length === options.value.length) {
attachment.value = [];
return;
}
options.value.forEach((opt) => {
const existItem = attachment.value.some((v) => v === opt.value);
if (!existItem) selectAttachment(opt);
});
}
function optionSearch(val: string | null) {
if (val === '') {
options.value = objectOptions;
return;
}
const needle = val ? val.toLowerCase() : '';
options.value = objectOptions.filter(
(v) => t(v.label).toLowerCase().indexOf(needle) > -1,
);
}
</script>
<template>
<div class="row col-12">
<div class="col-12 q-pb-sm row items-center">
<q-icon
flat
size="xs"
class="q-pa-sm rounded q-mr-sm"
color="info"
name="mdi-file-outline"
style="background-color: var(--surface-3)"
/>
<span class="text-body1 text-weight-bold">
{{ $t('general.information', { msg: $t('general.attachment') }) }}
</span>
</div>
<div class="col-12 row q-col-gutter-sm">
<q-select
:readonly
outlined
dense
v-model="attachment"
multiple
:options="options"
use-chips
option-label="label"
option-value="value"
emit-value
:label="$t('general.select', { msg: $t('general.attachment') })"
class="col"
:hide-dropdown-icon="readonly"
>
<template v-slot:selected-item="scope">
<q-chip
:removable="!readonly"
@remove="scope.removeAtIndex(scope.index)"
>
{{ $t(mapName(scope.opt)) }}
</q-chip>
</template>
<template v-slot:option></template>
<SelectMenuWithSearch
v-if="!readonly"
:title="$t('general.select', { msg: $t('general.attachment') })"
:option="options"
width="353.66px"
@search="(v) => optionSearch(v as string)"
@select="(v) => selectAttachment(v)"
>
<template #prepend>
<q-item
dense
clickable
class="bordered-t flex items-center app-text-muted"
style="padding: 0px 16px"
>
<q-icon name="mdi-plus" class="q-pa-sm q-mr-sm" />
{{ $t('general.add', { text: $t('general.attachment') }) }}
</q-item>
<q-item
dense
clickable
class="flex items-center"
style="
padding: 0px 16px;
background-color: hsla(var(--info-bg) / 0.1);
"
@click="selectAll()"
>
<q-checkbox
:model-value="
options.length > 0 && attachment.length === options.length
"
class="q-pr-sm"
size="xs"
@click="selectAll()"
/>
{{ $t('general.selectAll') }}
</q-item>
</template>
<template #option="{ opt }">
<q-checkbox
:model-value="attachment.some((v) => v === opt.value)"
class="q-pr-sm"
size="xs"
@click="selectAttachment(opt)"
/>
<span
:class="{
'app-text-info': attachment.some((v) => v === opt.value),
}"
>
{{ $t(opt.label as string) }}
</span>
</template>
</SelectMenuWithSearch>
</q-select>
</div>
</div>
</template>
<style></style>