201 lines
5.3 KiB
Vue
201 lines
5.3 KiB
Vue
<script lang="ts" setup>
|
|
import { QTableProps } from 'quasar';
|
|
import { dateFormat } from 'src/utils/datetime';
|
|
|
|
import { formatNumberDecimal, commaInput } from 'stores/utils';
|
|
|
|
import BadgeComponent from 'components/BadgeComponent.vue';
|
|
import KebabAction from 'components/shared/KebabAction.vue';
|
|
|
|
import { hslaColors } from 'src/pages/05_quotation/constants';
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
rows: QTableProps['rows'];
|
|
columns: QTableProps['columns'];
|
|
grid?: boolean;
|
|
visibleColumns?: string[];
|
|
hideEdit?: boolean;
|
|
}>(),
|
|
{
|
|
row: () => [],
|
|
column: () => [],
|
|
grid: false,
|
|
visibleColumns: () => [],
|
|
},
|
|
);
|
|
|
|
function payCondition(value: string) {
|
|
if (value === 'Full') return 'quotation.type.fullAmountCash';
|
|
if (value === 'Split') return 'quotation.type.installmentsCash';
|
|
if (value === 'SplitCustom') return 'quotation.type.installmentsCustomCash';
|
|
|
|
return '';
|
|
}
|
|
|
|
function quotationStatus(value: string) {
|
|
if (value === 'Issued') return 'quotation.status.Issued';
|
|
if (value === 'Accepted') return 'quotation.status.Accepted';
|
|
if (value === 'Expired') return 'quotation.status.Expired';
|
|
if (value === 'PaymentInProcess') return 'quotation.status.Invoice';
|
|
if (value === 'PaymentSuccess') return 'quotation.status.PaymentSuccess';
|
|
if (value === 'ProcessComplete') return 'quotation.status.ProcessComplete';
|
|
return '';
|
|
}
|
|
|
|
defineEmits<{
|
|
(e: 'preview', data: any): void;
|
|
(e: 'view', data: any): void;
|
|
(e: 'edit', data: any): void;
|
|
(e: 'delete', data: any): void;
|
|
}>();
|
|
</script>
|
|
|
|
<template>
|
|
<q-table
|
|
v-bind="props"
|
|
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-tr>
|
|
</template>
|
|
|
|
<template v-slot:body="props">
|
|
<q-tr :class="{ urgent: props.row.urgent }">
|
|
<q-td v-if="visibleColumns.includes('order')">
|
|
{{ props.rowIndex + 1 }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('workName')">
|
|
<div class="column">
|
|
<div class="col-6">{{ props.row.workName }}</div>
|
|
<div class="col-6 app-text-muted">{{ props.row.code }}</div>
|
|
</div>
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('createdAt')">
|
|
{{ dateFormat(props.row.createdAt) }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('dueDate')">
|
|
{{ dateFormat(props.row.dueDate) }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('contactName')">
|
|
{{ props.row.contactName }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('actor')">
|
|
{{ props.row.createdBy.firstName }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('summaryPrice')">
|
|
{{ formatNumberDecimal(props.row.finalPrice, 2) }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('payCondition')">
|
|
{{ $t(payCondition(props.row.payCondition)) }}
|
|
</q-td>
|
|
|
|
<q-td v-if="visibleColumns.includes('status')">
|
|
<div class="row" style="min-width: 150px">
|
|
<BadgeComponent
|
|
:title="$t(quotationStatus(props.row.quotationStatus))"
|
|
:hsla-color="hslaColors[props.row.quotationStatus] || ''"
|
|
/>
|
|
|
|
<div v-if="props.row.urgent" class="q-ml-sm" style="font-size: 90%">
|
|
<BadgeComponent
|
|
icon="mdi-fire"
|
|
:title="$t('general.urgent2')"
|
|
hsla-color="--gray-1-hsl"
|
|
hsla-background="--red-8-hsl"
|
|
solid
|
|
/>
|
|
</div>
|
|
</div>
|
|
</q-td>
|
|
|
|
<q-td class="text-right">
|
|
<q-btn
|
|
:id="`btn-eye-${props.row.firstName}`"
|
|
icon="mdi-play-box-outline"
|
|
size="sm"
|
|
dense
|
|
round
|
|
flat
|
|
@click.stop="$emit('preview', props.row.id)"
|
|
/>
|
|
|
|
<q-btn
|
|
:id="`btn-eye-${props.row.firstName}`"
|
|
icon="mdi-eye-outline"
|
|
size="sm"
|
|
dense
|
|
round
|
|
flat
|
|
@click.stop="$emit('view', props.row)"
|
|
/>
|
|
|
|
<KebabAction
|
|
:idName="`btn-kebab-${props.row.firstName}`"
|
|
status="'ACTIVE'"
|
|
hide-toggle
|
|
:hide-edit="hideEdit"
|
|
@view="$emit('view', props.row)"
|
|
@edit="$emit('edit', props.row)"
|
|
@delete="$emit('delete', props.row.id)"
|
|
/>
|
|
</q-td>
|
|
</q-tr>
|
|
</template>
|
|
|
|
<template v-slot:item="props">
|
|
<slot name="grid" :item="props" />
|
|
</template>
|
|
</q-table>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.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>
|