feat/fix: new component(select input/zone, quoCard)
This commit is contained in:
parent
08068137af
commit
c04039d8a7
7 changed files with 332 additions and 37 deletions
155
src/components/05_quotation/QuotationCard.vue
Normal file
155
src/components/05_quotation/QuotationCard.vue
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { Icon } from '@iconify/vue/dist/iconify.js';
|
||||||
|
import { formatNumberDecimal } from 'src/stores/utils';
|
||||||
|
import KebabAction from '../shared/KebabAction.vue';
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
type?:
|
||||||
|
| 'fullAmountCash'
|
||||||
|
| 'installmentsCash'
|
||||||
|
| 'fullAmountBill'
|
||||||
|
| 'installmentsBill'
|
||||||
|
| string;
|
||||||
|
title?: string;
|
||||||
|
code?: string;
|
||||||
|
amount?: number;
|
||||||
|
date?: string;
|
||||||
|
customerName?: string;
|
||||||
|
reporter?: string;
|
||||||
|
totalPrice?: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'view'): void;
|
||||||
|
(e: 'edit'): void;
|
||||||
|
(e: 'link'): void;
|
||||||
|
(e: 'upload'): void;
|
||||||
|
(e: 'delete'): void;
|
||||||
|
(e: 'changeStatus'): void;
|
||||||
|
(e: 'example'): void;
|
||||||
|
}>();
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="surface-1 rounded bordered q-pa-sm quo-card">
|
||||||
|
<!-- SEC: header -->
|
||||||
|
<header class="row items-center no-wrap">
|
||||||
|
<div
|
||||||
|
class="badge-card rounded q-pa-xs"
|
||||||
|
:class="{ [`badge-card__${type}`]: true }"
|
||||||
|
>
|
||||||
|
{{ $t(`quotation.type.${type}`) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="column q-ml-md relative-position" style="font-size: 12px">
|
||||||
|
<span>
|
||||||
|
{{ $t('general.itemNo', { msg: $t('quotation.title') }) }}
|
||||||
|
</span>
|
||||||
|
<span class="text-caption app-text-muted" style="top: 10px">
|
||||||
|
{{ code }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<nav class="col text-right">
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
rounded
|
||||||
|
icon="mdi-eye-outline"
|
||||||
|
size="12px"
|
||||||
|
@click.stop="$emit('view')"
|
||||||
|
/>
|
||||||
|
<KebabAction
|
||||||
|
:idName="code"
|
||||||
|
status="ACTIVE"
|
||||||
|
use-link
|
||||||
|
use-upload
|
||||||
|
@view="$emit('view')"
|
||||||
|
@edit="$emit('edit')"
|
||||||
|
@link="$emit('link')"
|
||||||
|
@upload="$emit('upload')"
|
||||||
|
@delete="$emit('delete')"
|
||||||
|
@change-status="$emit('changeStatus')"
|
||||||
|
/>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- SEC: body -->
|
||||||
|
<section class="row no-wrap q-py-md">
|
||||||
|
<q-img src="/images/quotation-avatar.png" width="4rem" class="q-mr-lg" />
|
||||||
|
<div class="column">
|
||||||
|
<span class="col q-pt-sm">{{ title || '-' }}</span>
|
||||||
|
<span class="app-text-muted">x {{ amount || '0' }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="col text-right app-text-muted q-mr-md self-end"
|
||||||
|
style="font-size: 12px"
|
||||||
|
>
|
||||||
|
{{ date || '-' }}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<q-separator />
|
||||||
|
<section class="row q-py-sm">
|
||||||
|
<div class="col-3 app-text-muted">{{ $t('quotation.customerName') }}</div>
|
||||||
|
<div class="col-9">{{ customerName || '-' }}</div>
|
||||||
|
<div class="col-3 app-text-muted">{{ $t('quotation.reporter') }}</div>
|
||||||
|
<div class="col-9">{{ reporter || '-' }}</div>
|
||||||
|
</section>
|
||||||
|
<q-separator />
|
||||||
|
<footer class="row no-wrap items-center q-mt-sm">
|
||||||
|
<Icon
|
||||||
|
class="q-mr-md"
|
||||||
|
icon="ph:money-fill"
|
||||||
|
style="font-size: 24px; color: var(--green-9)"
|
||||||
|
/>
|
||||||
|
{{ $t('quotation.totalPrice') }} :
|
||||||
|
<div class="q-pl-xs" style="color: var(--orange-5)">
|
||||||
|
{{ formatNumberDecimal(totalPrice || 0, 2) }}
|
||||||
|
</div>
|
||||||
|
<q-btn
|
||||||
|
dense
|
||||||
|
outline
|
||||||
|
color="primary"
|
||||||
|
class="rounded q-ml-auto"
|
||||||
|
padding="2px 8px"
|
||||||
|
>
|
||||||
|
<q-icon name="mdi-play-box-outline" size="xs" class="q-mr-xs" />
|
||||||
|
{{ $t('general.view', { msg: $t('general.example') }) }}
|
||||||
|
</q-btn>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.badge-card {
|
||||||
|
font-size: 12px;
|
||||||
|
color: hsla(var(--gray-0-hsl) / 1);
|
||||||
|
background: hsla(var(--_color) / 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-card__fullAmountCash {
|
||||||
|
--_color: var(--red-6-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-card__installmentsCash {
|
||||||
|
--_color: var(--blue-6-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-card__fullAmountBill {
|
||||||
|
--_color: var(--jungle-8-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-card__installmentsBill {
|
||||||
|
--_color: var(--purple-7-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .badge-card__installmentsCash {
|
||||||
|
--_color: var(--blue-10-hsl);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: inline-block;
|
||||||
|
/*new:*/
|
||||||
|
line-height: 12px;
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -23,6 +23,7 @@ defineProps<{
|
||||||
|
|
||||||
saveAmount?: number;
|
saveAmount?: number;
|
||||||
submitLabel?: string;
|
submitLabel?: string;
|
||||||
|
submitIcon?: string;
|
||||||
isEdit?: boolean;
|
isEdit?: boolean;
|
||||||
tabsList?: { name: string; label: string }[];
|
tabsList?: { name: string; label: string }[];
|
||||||
hideCloseEvent?: boolean;
|
hideCloseEvent?: boolean;
|
||||||
|
|
@ -217,6 +218,7 @@ const currentTab = defineModel<string>('currentTab');
|
||||||
id="btn-form-submit"
|
id="btn-form-submit"
|
||||||
type="submit"
|
type="submit"
|
||||||
solid
|
solid
|
||||||
|
:icon="submitIcon"
|
||||||
:label="submitLabel"
|
:label="submitLabel"
|
||||||
:amount="saveAmount"
|
:amount="saveAmount"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ defineProps<{
|
||||||
dark?: boolean;
|
dark?: boolean;
|
||||||
|
|
||||||
label?: string;
|
label?: string;
|
||||||
|
icon?: string;
|
||||||
|
|
||||||
amount?: number;
|
amount?: number;
|
||||||
}>();
|
}>();
|
||||||
|
|
@ -21,7 +22,7 @@ defineProps<{
|
||||||
<MainButton
|
<MainButton
|
||||||
@click="(e) => $emit('click', e)"
|
@click="(e) => $emit('click', e)"
|
||||||
v-bind="{ ...$props, ...$attrs }"
|
v-bind="{ ...$props, ...$attrs }"
|
||||||
icon="mdi-content-save-outline"
|
:icon="icon || 'mdi-content-save-outline'"
|
||||||
color="207 96% 32%"
|
color="207 96% 32%"
|
||||||
:title="iconOnly ? $t('general.save') : undefined"
|
:title="iconOnly ? $t('general.save') : undefined"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -76,18 +76,28 @@ const fullAddress = computed(() => {
|
||||||
|
|
||||||
if (moo.value) addressParts.push(`${t('form.moo')} ${moo.value}`);
|
if (moo.value) addressParts.push(`${t('form.moo')} ${moo.value}`);
|
||||||
if (soi.value) addressParts.push(`${t('form.soi')} ${soi.value}`);
|
if (soi.value) addressParts.push(`${t('form.soi')} ${soi.value}`);
|
||||||
if (street.value) addressParts.push(`${t('form.street')} ${street.value}`);
|
if (street.value) addressParts.push(`${t('form.road')} ${street.value}`);
|
||||||
|
|
||||||
if (subDistrictId.value && sDistrict) {
|
if (subDistrictId.value && sDistrict) {
|
||||||
addressParts.push(typeof sDistrict.name === 'string' ? sDistrict.name : '');
|
addressParts.push(
|
||||||
|
typeof sDistrict.name === 'string'
|
||||||
|
? `${t('form.subDistrict')} ${sDistrict.name}`
|
||||||
|
: '',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (districtId.value && district)
|
if (districtId.value && district)
|
||||||
addressParts.push(typeof district.name === 'string' ? district.name : '');
|
addressParts.push(
|
||||||
|
typeof district.name === 'string'
|
||||||
|
? `${t('form.district')} ${district.name}`
|
||||||
|
: '',
|
||||||
|
);
|
||||||
|
|
||||||
if (provinceId.value && province) {
|
if (provinceId.value && province) {
|
||||||
addressParts.push(
|
addressParts.push(
|
||||||
typeof province.name === 'string' ? `${province.name}` : '',
|
typeof province.name === 'string'
|
||||||
|
? `${t('form.province')} ${province.name}`
|
||||||
|
: '',
|
||||||
);
|
);
|
||||||
sDistrict &&
|
sDistrict &&
|
||||||
addressParts.push(
|
addressParts.push(
|
||||||
|
|
@ -99,26 +109,26 @@ const fullAddress = computed(() => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const fullAddressEN = computed(() => {
|
const fullAddressEN = computed(() => {
|
||||||
const addressParts = [addressEN.value];
|
const addressParts = [`${addressEN.value},`];
|
||||||
const province = provinceOptions.value.find((v) => v.id === provinceId.value);
|
const province = provinceOptions.value.find((v) => v.id === provinceId.value);
|
||||||
const district = districtOptions.value.find((v) => v.id === districtId.value);
|
const district = districtOptions.value.find((v) => v.id === districtId.value);
|
||||||
const sDistrict = subDistrictOptions.value.find(
|
const sDistrict = subDistrictOptions.value.find(
|
||||||
(v) => v.id === subDistrictId.value,
|
(v) => v.id === subDistrictId.value,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mooEN.value) addressParts.push(`Moo ${mooEN.value}`);
|
if (mooEN.value) addressParts.push(`Moo ${mooEN.value},`);
|
||||||
if (soiEN.value) addressParts.push(`Soi ${soiEN.value}`);
|
if (soiEN.value) addressParts.push(`Soi ${soiEN.value},`);
|
||||||
if (streetEN.value) addressParts.push(`${streetEN.value} Street`);
|
if (streetEN.value) addressParts.push(`${streetEN.value} Rd.`);
|
||||||
|
|
||||||
if (subDistrictId.value && sDistrict) {
|
if (subDistrictId.value && sDistrict) {
|
||||||
addressParts.push(
|
addressParts.push(
|
||||||
typeof sDistrict.nameEN === 'string' ? sDistrict.nameEN : '',
|
typeof sDistrict.nameEN === 'string' ? `${sDistrict.nameEN},` : '',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (districtId.value && district)
|
if (districtId.value && district)
|
||||||
addressParts.push(
|
addressParts.push(
|
||||||
typeof district.nameEN === 'string' ? district.nameEN : '',
|
typeof district.nameEN === 'string' ? `${district.nameEN},` : '',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (provinceId.value && province) {
|
if (provinceId.value && province) {
|
||||||
|
|
@ -397,7 +407,7 @@ watch(districtId, fetchSubDistrict);
|
||||||
class="col-md-3 col-6"
|
class="col-md-3 col-6"
|
||||||
:model-value="readonly ? street || '-' : street"
|
:model-value="readonly ? street || '-' : street"
|
||||||
:dense="dense"
|
:dense="dense"
|
||||||
:label="$t('form.street')"
|
:label="$t('form.road')"
|
||||||
:readonly="readonly || sameWithEmployer"
|
:readonly="readonly || sameWithEmployer"
|
||||||
:for="`${prefixId}-${indexId !== undefined ? `input-street-${indexId}` : 'input-street'}`"
|
:for="`${prefixId}-${indexId !== undefined ? `input-street-${indexId}` : 'input-street'}`"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
|
|
@ -552,7 +562,13 @@ watch(districtId, fetchSubDistrict);
|
||||||
outlined
|
outlined
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
class="col-12"
|
class="col-12"
|
||||||
:model-value="address ? fullAddress : ''"
|
:model-value="
|
||||||
|
address
|
||||||
|
? $i18n.locale === 'eng'
|
||||||
|
? fullAddressEN
|
||||||
|
: fullAddress
|
||||||
|
: ''
|
||||||
|
"
|
||||||
:dense="dense"
|
:dense="dense"
|
||||||
:label="$t('form.fullAddress')"
|
:label="$t('form.fullAddress')"
|
||||||
readonly
|
readonly
|
||||||
|
|
@ -635,7 +651,7 @@ watch(districtId, fetchSubDistrict);
|
||||||
class="col-md-3 col-6"
|
class="col-md-3 col-6"
|
||||||
:model-value="readonly ? streetEN || '-' : streetEN"
|
:model-value="readonly ? streetEN || '-' : streetEN"
|
||||||
:dense="dense"
|
:dense="dense"
|
||||||
label="Street"
|
label="Road"
|
||||||
:readonly="readonly || sameWithEmployer"
|
:readonly="readonly || sameWithEmployer"
|
||||||
:for="`${prefixId}-${indexId !== undefined ? `input-street-${indexId}` : 'input-street'}`"
|
:for="`${prefixId}-${indexId !== undefined ? `input-street-${indexId}` : 'input-street'}`"
|
||||||
@update:model-value="
|
@update:model-value="
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ defineEmits<{
|
||||||
}"
|
}"
|
||||||
@click="$emit('enterCard', 'INFO')"
|
@click="$emit('enterCard', 'INFO')"
|
||||||
>
|
>
|
||||||
<div class="column items-center">
|
<div class="column items-center" :class="{ 'q-pt-sm': noAction }">
|
||||||
<!-- kebab menu -->
|
<!-- kebab menu -->
|
||||||
<div class="full-width flex no-wrap" v-if="!noAction">
|
<div class="full-width flex no-wrap" v-if="!noAction">
|
||||||
<div style="margin-right: auto">
|
<div style="margin-right: auto">
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,82 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
import { selectFilterOptionRefMod } from 'src/stores/utils';
|
import { selectFilterOptionRefMod } from 'src/stores/utils';
|
||||||
|
import { QSelect } from 'quasar';
|
||||||
|
|
||||||
const model = defineModel<string | Date | null>();
|
const model = defineModel<string | Date | null>();
|
||||||
const option = defineModel<[]>('option', { default: [] });
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
id?: string;
|
|
||||||
readonly?: boolean;
|
|
||||||
clearable?: boolean;
|
|
||||||
label?: string;
|
|
||||||
rules?: ((value: string) => string | true)[];
|
|
||||||
disabledDates?: string[] | Date[] | ((date: Date) => boolean);
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const options = ref<Record<string, unknown>[]>([]);
|
const options = ref<Record<string, unknown>[]>([]);
|
||||||
let typeBusinessFilter = selectFilterOptionRefMod(option, options, 'label');
|
let defaultFilter: (
|
||||||
|
value: string,
|
||||||
|
update: (callbackFn: () => void, afterFn?: (ref: QSelect) => void) => void,
|
||||||
|
) => void;
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
id?: string;
|
||||||
|
label?: string;
|
||||||
|
option: Record<string, unknown>[];
|
||||||
|
optionLabel?: string;
|
||||||
|
optionValue?: string;
|
||||||
|
|
||||||
|
readonly?: boolean;
|
||||||
|
clearable?: boolean;
|
||||||
|
incremental?: boolean;
|
||||||
|
|
||||||
|
rules?: ((value: string) => string | true)[];
|
||||||
|
}>(),
|
||||||
|
{ option: () => [], optionLabel: 'label', optionValue: 'value' },
|
||||||
|
);
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'filter', val: string, update: void): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
defaultFilter = selectFilterOptionRefMod(
|
||||||
|
ref(props.option),
|
||||||
|
options,
|
||||||
|
props.optionLabel,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.option,
|
||||||
|
() => {
|
||||||
|
defaultFilter = selectFilterOptionRefMod(
|
||||||
|
ref(props.option),
|
||||||
|
options,
|
||||||
|
props.optionLabel,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<q-select
|
<q-select
|
||||||
outlined
|
outlined
|
||||||
clearable
|
:clearable
|
||||||
use-input
|
use-input
|
||||||
fill-input
|
|
||||||
emit-value
|
emit-value
|
||||||
map-options
|
map-options
|
||||||
hide-selected
|
hide-selected
|
||||||
hide-bottom-space
|
hide-bottom-space
|
||||||
|
:fill-input="!!model"
|
||||||
:hide-dropdown-icon="readonly"
|
:hide-dropdown-icon="readonly"
|
||||||
input-debounce="0"
|
input-debounce="0"
|
||||||
option-value="value"
|
:option-value="optionValue"
|
||||||
option-label="label"
|
:option-label="optionLabel"
|
||||||
v-model="model"
|
v-model="model"
|
||||||
class="col-md-6 col-12"
|
|
||||||
dense
|
dense
|
||||||
:readonly="readonly"
|
:readonly
|
||||||
:label="label"
|
:label="label"
|
||||||
:options="options"
|
:options="incremental ? option : options"
|
||||||
:for="`${prefixId}-select-business-type`"
|
:for="`select-${id}`"
|
||||||
@filter="typeBusinessFilter"
|
@filter="
|
||||||
:rules="[(val: string) => !!val || $t('form.error.required')]"
|
(val, update) => {
|
||||||
|
incremental ? $emit('filter', val, update) : defaultFilter(val, update);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
:rules
|
||||||
>
|
>
|
||||||
<template v-slot:no-option>
|
<template v-slot:no-option>
|
||||||
<q-item>
|
<q-item>
|
||||||
|
|
@ -48,5 +85,13 @@ let typeBusinessFilter = selectFilterOptionRefMod(option, options, 'label');
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-if="$slots.name" v-slot:selected-item="scope">
|
||||||
|
<slot name="selected-item" :scope="scope"></slot>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-if="$slots.option" v-slot:option="scope">
|
||||||
|
<slot name="option" :scope="scope"></slot>
|
||||||
|
</template>
|
||||||
</q-select>
|
</q-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
76
src/components/shared/SelectZone.vue
Normal file
76
src/components/shared/SelectZone.vue
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
const search = defineModel<string>('search');
|
||||||
|
const selectedItem = defineModel<unknown[]>('selectedItem', { default: [] });
|
||||||
|
|
||||||
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
|
items: unknown[];
|
||||||
|
color?: string;
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
items: () => [],
|
||||||
|
color: 'var(--brand-1)',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
function select(item: unknown) {
|
||||||
|
if (selectedItem.value.includes(item)) {
|
||||||
|
let index = selectedItem.value.indexOf(item);
|
||||||
|
selectedItem.value.splice(index, 1);
|
||||||
|
} else selectedItem.value.push(item);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<section class="full-width column q-pa-md">
|
||||||
|
<header class="row items-center no-wrap q-mb-md">
|
||||||
|
<div class="col"><slot name="top"></slot></div>
|
||||||
|
<q-input
|
||||||
|
for="input-search"
|
||||||
|
outlined
|
||||||
|
dense
|
||||||
|
:label="$t('general.search')"
|
||||||
|
class="q-ml-auto"
|
||||||
|
:bg-color="$q.dark.isActive ? 'dark' : 'white'"
|
||||||
|
v-model="search"
|
||||||
|
debounce="200"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<q-icon name="mdi-magnify" />
|
||||||
|
</template>
|
||||||
|
</q-input>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="col">
|
||||||
|
<div class="row q-col-gutter-md">
|
||||||
|
<div
|
||||||
|
v-for="(item, i) in items"
|
||||||
|
:key="i"
|
||||||
|
class="col-md-2 col-sm-6 col-12"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="rounded cursor-pointer relative-position"
|
||||||
|
:style="`border: 1px solid ${selectedItem.includes(item) ? color : 'transparent'}`"
|
||||||
|
@click="() => select(item)"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="selectedItem.includes(item)"
|
||||||
|
class="badge absolute-top-right flex justify-center q-ma-sm"
|
||||||
|
:style="`background-color: ${color}`"
|
||||||
|
>
|
||||||
|
{{ selectedItem.indexOf(item) + 1 }}
|
||||||
|
</div>
|
||||||
|
<slot name="data" :item="item"></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
</template>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.badge {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
color: var(--surface-1);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue