229 lines
5.1 KiB
Vue
229 lines
5.1 KiB
Vue
<script lang="ts" setup>
|
|
import { QTableProps } from 'quasar';
|
|
import TableComponents from 'src/components/TableComponents.vue';
|
|
import { watch } from 'vue';
|
|
|
|
const employeeAmount = defineModel<number>('employeeAmount', { default: 1 });
|
|
|
|
defineEmits<{
|
|
(e: 'delete', index: number): void;
|
|
(e: 'check', index: number): void;
|
|
}>();
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
readonly?: boolean;
|
|
fallbackImg?: string;
|
|
hideQuantity?: boolean;
|
|
checkable?: boolean;
|
|
inTable?: boolean;
|
|
rows: {
|
|
foreignRefNo: string;
|
|
employeeName: string;
|
|
birthDate: string;
|
|
gender: string;
|
|
age: string;
|
|
nationality: string;
|
|
documentExpireDate: string;
|
|
imgUrl?: string;
|
|
status: string;
|
|
}[];
|
|
}>(),
|
|
{
|
|
rows: () => [],
|
|
},
|
|
);
|
|
|
|
const checkList = defineModel<number[]>('checkList', { default: [] });
|
|
|
|
const columns = [
|
|
{
|
|
name: 'order',
|
|
align: 'center',
|
|
label: 'general.order',
|
|
field: 'order',
|
|
},
|
|
{
|
|
name: 'foreignRefNo',
|
|
align: 'center',
|
|
label: 'quotation.foreignRefNo',
|
|
field: 'foreignRefNo',
|
|
},
|
|
{
|
|
name: 'employeeName',
|
|
align: 'left',
|
|
label: 'quotation.employeeName',
|
|
field: 'employeeName',
|
|
},
|
|
{
|
|
name: 'birthDate',
|
|
align: 'left',
|
|
label: 'general.birthDate',
|
|
field: 'birthDate',
|
|
},
|
|
{
|
|
name: 'age',
|
|
align: 'left',
|
|
label: 'general.age',
|
|
field: 'age',
|
|
},
|
|
{
|
|
name: 'nationality',
|
|
align: 'left',
|
|
label: 'general.nationality',
|
|
field: 'nationality',
|
|
},
|
|
{
|
|
name: 'documentExpireDate',
|
|
align: 'left',
|
|
label: 'quotation.documentExpireDate',
|
|
field: 'documentExpireDate',
|
|
},
|
|
{
|
|
name: 'action',
|
|
align: 'left',
|
|
label: '',
|
|
field: 'action',
|
|
},
|
|
] satisfies QTableProps['columns'];
|
|
|
|
watch(
|
|
() => props.rows,
|
|
() => {
|
|
if (props.readonly) return;
|
|
employeeAmount.value = props.rows.length;
|
|
},
|
|
);
|
|
</script>
|
|
<template>
|
|
<div>
|
|
<TableComponents
|
|
flat
|
|
bordered
|
|
hideView
|
|
:button-delete="!checkable && !readonly"
|
|
img-column="employeeName"
|
|
:readonly="readonly"
|
|
:inTable
|
|
:columns="
|
|
checkable
|
|
? [
|
|
{
|
|
name: 'check',
|
|
align: 'center',
|
|
label: '',
|
|
field: 'check',
|
|
},
|
|
...columns.filter((c) => c.name !== 'action'),
|
|
]
|
|
: columns
|
|
"
|
|
:rows="
|
|
readonly && inTable
|
|
? rows.filter((_, index) => checkList.includes(index))
|
|
: rows
|
|
"
|
|
hidePagination
|
|
:customColumn="['check']"
|
|
@delete="(i) => $emit('delete', i)"
|
|
>
|
|
<template v-slot:img-column="{ props }">
|
|
<q-avatar class="q-mr-sm" size="md">
|
|
<q-img
|
|
v-if="props.row.imgUrl"
|
|
:src="props.row.imgUrl"
|
|
class="full-height full-width"
|
|
>
|
|
<template #error>
|
|
<q-img
|
|
:src="`/images/employee-avatar-${props.row.gender}.png`"
|
|
:ratio="1"
|
|
/>
|
|
</template>
|
|
</q-img>
|
|
<q-img
|
|
v-else
|
|
:src="`/images/employee-avatar-${props.row.gender}.png`"
|
|
:ratio="1"
|
|
/>
|
|
<div
|
|
class="absolute-bottom-right"
|
|
style="
|
|
border-radius: 50%;
|
|
width: 10px;
|
|
height: 10px;
|
|
z-index: 2;
|
|
background: var(--surface-1);
|
|
"
|
|
>
|
|
<div
|
|
class="absolute-center"
|
|
style="border-radius: 50%; width: 8px; height: 8px"
|
|
:style="`background: hsl(var(${props.row.status !== 'INACTIVE' ? '--positive-bg' : '--text-mute'}))`"
|
|
></div>
|
|
</div>
|
|
</q-avatar>
|
|
</template>
|
|
|
|
<template v-slot:body-cell-check="{ props }">
|
|
<q-td class="text-center">
|
|
<q-checkbox
|
|
size="xs"
|
|
@click.stop="
|
|
() => {
|
|
$emit('check', props.rowIndex);
|
|
}
|
|
"
|
|
:model-value="checkList.includes(props.rowIndex)"
|
|
></q-checkbox>
|
|
</q-td>
|
|
</template>
|
|
</TableComponents>
|
|
|
|
<div v-if="!hideQuantity" class="row q-pt-md items-center">
|
|
<span class="q-ml-auto q-mr-sm">
|
|
{{ $t('general.numberOf', { msg: $t('quotation.employee') }) }}
|
|
</span>
|
|
|
|
<q-input
|
|
for="worker-count"
|
|
dense
|
|
outlined
|
|
style="width: 67px"
|
|
:type="readonly ? 'text' : 'number'"
|
|
class="col-1"
|
|
input-class="text-center"
|
|
:readonly
|
|
hide-bottom-space
|
|
:min="rows.length"
|
|
v-model="employeeAmount"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.worker-item {
|
|
--side-color: var(--brand-1);
|
|
position: relative;
|
|
overflow-x: hidden;
|
|
|
|
&.worker-item__female {
|
|
--side-color: hsl(var(--gender-female));
|
|
}
|
|
|
|
&.worker-item__male {
|
|
--side-color: hsl(var(--gender-male));
|
|
}
|
|
}
|
|
|
|
.worker-item::before {
|
|
position: absolute;
|
|
content: ' ';
|
|
left: 0;
|
|
width: 7px;
|
|
top: 0;
|
|
bottom: 0;
|
|
background: var(--side-color);
|
|
}
|
|
</style>
|