jws-frontend/src/components/05_quotation/WorkerItem.vue
2025-01-24 14:28:36 +07:00

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>