273 lines
7.5 KiB
Vue
273 lines
7.5 KiB
Vue
<script setup lang="ts">
|
|
import { QTable, QTableProps, QTableSlots } from 'quasar';
|
|
|
|
import QuotationCard from 'src/components/05_quotation/QuotationCard.vue';
|
|
import BadgeComponent from 'src/components/BadgeComponent.vue';
|
|
import AvatarGroup from 'src/components/shared/AvatarGroup.vue';
|
|
|
|
import { RequestData } from 'src/stores/request-list/types';
|
|
import { RequestDataStatus } from 'src/stores/request-list/types';
|
|
import useOptionStore from 'src/stores/options';
|
|
|
|
import KebabAction from 'src/components/shared/KebabAction.vue';
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
rows: QTableProps['rows'];
|
|
columns: QTableProps['columns'];
|
|
grid?: boolean;
|
|
visibleColumns?: string[];
|
|
}>(),
|
|
{
|
|
row: () => [],
|
|
column: () => [],
|
|
grid: false,
|
|
visibleColumns: () => [],
|
|
},
|
|
);
|
|
|
|
defineEmits<{
|
|
(e: 'view', data: RequestData): void;
|
|
(e: 'delete', data: RequestData): void;
|
|
}>();
|
|
|
|
function getCustomerName(
|
|
record: RequestData,
|
|
opts?: {
|
|
locale?: string;
|
|
noCode?: boolean;
|
|
},
|
|
) {
|
|
const customer = record.quotation.customerBranch;
|
|
|
|
return (
|
|
{
|
|
['CORP']: {
|
|
['eng']: customer.registerNameEN,
|
|
['tha']: customer.registerName,
|
|
}[opts?.locale || 'eng'],
|
|
['PERS']:
|
|
{
|
|
['eng']: `${useOptionStore().mapOption(customer?.namePrefix || '')} ${customer?.firstNameEN} ${customer?.lastNameEN}`,
|
|
['tha']: `${useOptionStore().mapOption(customer?.namePrefix || '')} ${customer?.firstName} ${customer?.lastName}`,
|
|
}[opts?.locale || 'eng'] || '-',
|
|
}[customer.customer.customerType] +
|
|
(opts?.noCode ? '' : ' ' + `(${customer.code})`)
|
|
);
|
|
}
|
|
|
|
function getEmployeeName(
|
|
record: RequestData,
|
|
opts?: {
|
|
locale?: string;
|
|
},
|
|
) {
|
|
const employee = record.employee;
|
|
|
|
return (
|
|
{
|
|
['eng']: `${useOptionStore().mapOption(employee?.namePrefix || '')} ${employee?.firstNameEN} ${employee?.lastNameEN}`,
|
|
['tha']: `${useOptionStore().mapOption(employee?.namePrefix || '')} ${employee?.firstName} ${employee?.lastName}`,
|
|
}[opts?.locale || 'eng'] || '-'
|
|
);
|
|
}
|
|
</script>
|
|
<template>
|
|
<q-table
|
|
v-bind="props"
|
|
bordered
|
|
flat
|
|
hide-pagination
|
|
card-container-class="q-col-gutter-sm"
|
|
:rows-per-page-options="[0]"
|
|
class="full-width"
|
|
>
|
|
<template v-slot:header="props">
|
|
<q-tr
|
|
style="background-color: hsla(var(--info-bg) / 0.07)"
|
|
:props="props"
|
|
>
|
|
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
|
{{ col.label && $t(col.label) }}
|
|
</q-th>
|
|
<q-th></q-th>
|
|
</q-tr>
|
|
</template>
|
|
|
|
<template
|
|
v-slot:body="props: {
|
|
row: RequestData;
|
|
} & Omit<Parameters<QTableSlots['body']>[0], 'row'>"
|
|
>
|
|
<q-tr
|
|
:class="{ urgent: props.row.quotation.urgent, dark: $q.dark.isActive }"
|
|
class="text-center"
|
|
>
|
|
<q-td v-if="visibleColumns.includes('order')">
|
|
{{ props.rowIndex + 1 }}
|
|
</q-td>
|
|
<q-td v-if="visibleColumns.includes('requestList')" class="text-left">
|
|
{{ props.row.quotation.workName || '-' }}
|
|
<div class="text-caption app-text-muted">
|
|
{{ props.row.code || '-' }}
|
|
</div>
|
|
</q-td>
|
|
<q-td v-if="visibleColumns.includes('employer')" class="text-left">
|
|
{{
|
|
getCustomerName(props.row, {
|
|
noCode: true,
|
|
locale: $i18n.locale,
|
|
}) || '-'
|
|
}}
|
|
</q-td>
|
|
<q-td v-if="visibleColumns.includes('employee')" class="text-left">
|
|
{{ getEmployeeName(props.row, { locale: $i18n.locale }) || '-' }}
|
|
</q-td>
|
|
<q-td v-if="visibleColumns.includes('quotationCode')">
|
|
{{ props.row.quotation.code || '-' }}
|
|
</q-td>
|
|
<q-td v-if="visibleColumns.includes('responsiblePerson')">
|
|
{{ '-' }}
|
|
</q-td>
|
|
<q-td v-if="visibleColumns.includes('status')">
|
|
<BadgeComponent
|
|
:hsla-color="
|
|
{
|
|
[RequestDataStatus.Pending]: '--orange-5-hsl',
|
|
[RequestDataStatus.InProgress]: '--blue-6-hsl',
|
|
[RequestDataStatus.Completed]: '--green-8-hsl',
|
|
[RequestDataStatus.Canceled]: '--red-5-hsl',
|
|
}[props.row.requestDataStatus]
|
|
"
|
|
:title="
|
|
$t(`requestList.status.${props.row.requestDataStatus}`) || '-'
|
|
"
|
|
/>
|
|
</q-td>
|
|
<q-td class="text-right">
|
|
<q-btn
|
|
:id="`btn-eye-${props.row.quotation.workName}`"
|
|
icon="mdi-eye-outline"
|
|
size="sm"
|
|
dense
|
|
round
|
|
flat
|
|
@click.stop="$emit('view', props.row)"
|
|
/>
|
|
|
|
<KebabAction
|
|
hide-edit
|
|
hide-toggle
|
|
hide-view
|
|
hide-delete
|
|
:disable-cancel="
|
|
props.row.requestDataStatus === RequestDataStatus.Canceled
|
|
"
|
|
@cancel="$emit('delete', props.row)"
|
|
/>
|
|
</q-td>
|
|
</q-tr>
|
|
</template>
|
|
|
|
<template
|
|
v-slot:item="props: {
|
|
row: RequestData;
|
|
} & Omit<Parameters<QTableSlots['body']>[0], 'row'>"
|
|
>
|
|
<div class="col-md-4 col-sm-6 col-12">
|
|
<QuotationCard
|
|
hide-preview
|
|
hide-kebab-view
|
|
hide-kebab-edit
|
|
:badge-color="
|
|
props.row.requestDataStatus === RequestDataStatus.Pending
|
|
? '--orange-5-hsl'
|
|
: props.row.requestDataStatus === RequestDataStatus.InProgress
|
|
? '--blue-6-hsl'
|
|
: props.row.requestDataStatus === RequestDataStatus.Completed
|
|
? '--green-8-hsl'
|
|
: '--orange-5-hsl'
|
|
"
|
|
:urgent="props.row.quotation.urgent"
|
|
:code="props.row.code"
|
|
:title="props.row.quotation.workName"
|
|
:status="$t(`requestList.status.${props.row.requestDataStatus}`)"
|
|
:custom-data="[
|
|
{
|
|
label: $t('customer.employer'),
|
|
value:
|
|
getCustomerName(props.row, {
|
|
noCode: true,
|
|
locale: $i18n.locale,
|
|
}) || '-',
|
|
},
|
|
{
|
|
label: $t('customer.employee'),
|
|
value:
|
|
getEmployeeName(props.row, { locale: $i18n.locale }) || '-',
|
|
},
|
|
{
|
|
label: $t('requestList.quotationCode'),
|
|
value: props.row.quotation.code || '-',
|
|
},
|
|
{
|
|
label: $t('flow.responsiblePerson'),
|
|
value: '',
|
|
slotName: 'responsiblePerson',
|
|
},
|
|
]"
|
|
@view="$emit('view', props.row)"
|
|
>
|
|
<template v-slot:responsiblePerson="{ props }">
|
|
<div class="col-4 app-text-muted q-pr-sm self-center">
|
|
{{ props.label }}
|
|
</div>
|
|
<div class="col-8">
|
|
<AvatarGroup />
|
|
</div>
|
|
</template>
|
|
</QuotationCard>
|
|
</div>
|
|
</template>
|
|
</q-table>
|
|
</template>
|
|
|
|
<style scoped>
|
|
:deep(tr:nth-child(2n)) {
|
|
background: #f9fafc;
|
|
&.dark {
|
|
background: hsl(var(--gray-11-hsl) / 0.2);
|
|
}
|
|
}
|
|
|
|
.q-table tr.urgent {
|
|
background: hsla(var(--red-6-hsl) / 0.03);
|
|
}
|
|
|
|
.q-table tr.urgent td:first-child {
|
|
&::after {
|
|
content: ' ';
|
|
display: block;
|
|
position: absolute;
|
|
left: 0;
|
|
top: 15%;
|
|
bottom: 15%;
|
|
background: var(--red-8);
|
|
width: 4px;
|
|
border-radius: 99rem;
|
|
animation: blink 1s infinite;
|
|
}
|
|
}
|
|
|
|
@keyframes blink {
|
|
0% {
|
|
background: var(--red-8);
|
|
}
|
|
50% {
|
|
background: var(--red-3);
|
|
}
|
|
100% {
|
|
background: var(--red-8);
|
|
}
|
|
}
|
|
</style>
|