jws-frontend/src/pages/09_task-order/TableTaskOrder.vue

302 lines
8.8 KiB
Vue
Raw Normal View History

feat: task order (#141) * feat: task order => routes * feat: Page * refactor: pagination * refactor: taskOrder => table, card and constants * feat: add structure select request list comp * fix: re-export type * refactor: edit path route of task order * feat: trigger task order * refactor: edit type task statss * feat: table select request list * feat: i18n * refactor: quasar expansion chevron color * refactor: type * refactor: state btn status done * feat: task order => order view layout * feat: task order => remark expansion * fix: task order => rename attachment to additional file * feat: upload file section optional layout * feat: task order => additional file expansion * feat: task order => payment expansion * feat: conditionally add urgent * feat: send id together with link * refactor: edit type * feat: new form.ts * refactor: edit url * refactor: edit id trigger * feat: select institution component * feat: task order code i18n * feat: task order => document expansion form * feat: fallback address on null * refactor: add type for table * feat: add filter parameter * refactor: edit name routes * refactor: add type of task order payload * refactor: by value form * refactor: responsive quotation form info * refactor: submit form * refactor: add i18n * refactor: status canceled * refactor: handle task status * refactor: handle mode view * refactor: addtaskstatus * refactor: i18n & constants * refactor: table employee * refactor: select ready request work * refactor: handle save form * refactor: edit layout btn * feat: undo() * cleanup delete import * feat: closetab * refactor: handle readonly * fix: body edit * refactor: handle readonly uploadfile * feat: import manage attachment * refactor: quotation/task-order => type * refactor: select ready request work * refactor: i18n & constants * chore: clean duplicate i18n * refactor: type according to backend relation * refactor: edit base url * feat: upload file * feat: fetch file list * feat: get url file * refactor: set default opened * refactor: type * feat: removefile * feat: task order => select product * feat: add parameter only active branch is selectable * refactor: add i18n * feat: set layout * feat: add info product expansion * refactor: new info messenger * refactor: add slot name value * refactor: add i18n * refactor: edit type task status * refactor: use date format * refactor: value can null * refactor: add i18n * cleanup * feat: productlistinput * refactor: edit i18n * refactor: edit redo * refactor: add slot * feat: task order => i18n * refactor: task order => constant * refactor: taskOrder => status type and index * feat: taskOrder => ReceiveDialog * refactor: wording * refactor: table employee due date * refactor: receive task i18n * feat: trigger receive & task stat in receive page * refactor: receive dialog task in cart i18n * fix: remove task-order/receive/add * feat: receivetabletaskorder * refactor: fetch task on receive dialog * feat: add separate api get user task * refactor: receive fetch (messenger) * refactor: edit layout table * refactor: task order i18n & constant * refactor: task order change tab and stat (messenger and !messenger) * fix: task order status display & receive badge color (card) * refactor: trigger receive view * fix: add receive task condition * feat: total count * feat: prepare information * fix: i18n error task order not found * refacor: value * feat: select worker * refactor: status i18n & constant * refactor: table employee props (check box, step) * fix: order => select ready task * refactor: order => toggle status * refactor: receive => receive dialog * feat: featch value * refactor: task status display components * refactor: status active can is null * feat: update status tab * refactor: data display * refactor: i18n & fullTaskOrder variable * refactor: task receive view * refactor: add type responsible user * refactor: set group messenger * cleanup: * refactor: i18n / clone full task order / service => workflow type * refactor: receive view * refactor: show info messenger * refactor: handle flow step * refactor: receive view => opacity when pending * feat: add workflow template name and step name * feat: display workflow data on table * feat: add template step identifier * fix: edit does not change workflow id if changed * feat: detect if same template and step * refactor: handle template * refactor: add slot name product * refactor: map step in list product * refactor: bind data messenger list group * refactor: change endpoint name * chore: add helper package * feat: changetaskstatus * refactor: update type * refactor: set color btn * refactor: add step * refactor: add resposible institution * feat: disabled * refactor: map responsible institution * fix: order view => readonly * chore: clean * refactor: edit url api * refactor: edit name type * refactor: add slots action * refactor: add type row * refactor: add opts of task status * refactor: add select status * refactor: handle btn * refactor: add btn change task status * refactor: edit i18n redo th * refactor: sort status opts * feat: receive & order banner img * refactor: fetch status after submit * refactor: handle create only * refactor: task order status type Accept (messenger only) * feat: receive messenger profile * refactor: receive toggle status (display only) * fix: document expansion readonly * feat: confirmsendingbtn * refactor: constant and task order status * feat: receive task list count * refactor: post or get * refactor: define props institution group * refactor: fetch status after submit * refactor: handle create * refactor: handle query * refactor: update endpoint to support accept multiple order * refactor: change function name * feat: receive => functional accept task order * feat: task status count * feat: receive stat card count * refactor: order messenger profile * refactor: edit value to be task status * refactor: handle status of type order * refactor: use componet task status * refactor: handle show btn saving status * refactor: order => task status * refactor: edit selectStatus => changeStatus * refactor: edit @click btn confirmssending * refactor: add i18n * refactor: add function get template data * refactor: add change status * refactor: handle type receive * feat: order => auto change tab by status * refactor: fetch task after change status * feat: fail remark dialog * refactor: display step order (table employee) * refactor: fail remark dialog * refactor: order => open ready request dialog map selected * refactor: task list type & change status param * refactor: table task order, td background when selected * refactor: order => change status param * refactor: order => selectedEmployee variable type * refactor: task status component => shield btn * refactor: receive => change status * refactor: order => step btn waiting * fix: step btn waiting condition * refactor: filter selectable task (Failed) * refactor: find index condition on check * refactor: no request list available * refactor: fail btn no-wrap * refactor: fail dialog readonly * fix: reset state on open dialog * fix: wrong title position * refactor: hide task status drop down icon * fix: handle check condition * refactor: add userTask type and status * feat: submit task order function * refactor: table employee checkbox display condition * refactor: main layout * fix: task order validate i18n * refactor: table task order add submit status * refactor: status list * refactor: info product => user task status * feat: receive => submit task & step * refactor: i18n * feat: complete task oder function * refactor: task status component no action props * refactor: info messenger status * refactor: receive and order view * refactor: order complete view * refactor: order => complete color and title * refactor: calc price on table * refactor: quotation table i18n + product image * refactor: remove urgent checkbox * refactor: task status color * feat: calc summary price * fix: data is not available * feat: add doc view structure * refactor: format address text * feat: fetch document data from api * fix: value is null * fix: regression cannot edit package * feat: add document view for task order * feat: add view document button * feat: update type add discount * feat: readonly on cancel * feat: add discount from relation * refactor: add taskProduct on submit order * refactor: order => task product discount * refactor: order => date, task status count, view example * refactor: receive date * refactor: receive task status count --------- Co-authored-by: puriphatt <puriphat@frappet.com> Co-authored-by: nwpptrs <jay02499@gmail.com> Co-authored-by: Thanaphon Frappet <thanaphon@frappet.com> Co-authored-by: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Co-authored-by: oat_dev <nattapon@frappet.com>
2024-12-25 11:59:49 +07:00
<script lang="ts" setup>
import { QTableProps, QTableSlots } from 'quasar';
import QuotationCard from 'src/components/05_quotation/QuotationCard.vue';
import BadgeComponent from 'src/components/BadgeComponent.vue';
import KebabAction from 'src/components/shared/KebabAction.vue';
import useOptionStore from 'src/stores/options';
import { dateFormatJS, dateFormat } from 'src/utils/datetime';
import { TaskOrder, TaskOrderStatus } from 'src/stores/task-order/types';
import { column } from './constants';
import { ref } from 'vue';
const selectedTask = defineModel<TaskOrder[]>('selectedTask', { default: [] });
const props = withDefaults(
defineProps<{
rows: QTableProps['rows'];
grid?: boolean;
visibleColumns?: string[];
selection?: 'single' | 'multiple' | 'none';
receive?: boolean;
}>(),
{
rows: () => [],
grid: false,
receive: false,
selection: 'none',
visibleColumns: () => [
'createdAt',
'order',
'taskName',
'issueBranch',
'institution',
'createdBy',
'contactTel',
'contactName',
'taskStatus',
],
},
);
const currentBtnOpen = ref<boolean[]>([]);
function taskOrderStatus(value: TaskOrderStatus, type: 'status' | 'color') {
const mappings: Record<string, Record<'status' | 'color', string>> = {
Pending: {
status: props.receive ? 'taskOrder.taskInCart' : 'taskOrder.title',
color: '--blue-6-hsl',
},
InProgress: {
status: 'taskOrder.inProgress',
color: props.receive ? '--blue-6-hsl' : '--orange-5-hsl',
},
Validate: {
status: 'taskOrder.inProgress',
color: props.receive ? '--blue-6-hsl' : '--orange-5-hsl',
},
Complete: {
status: props.receive ? 'taskOrder.sentTask' : 'taskOrder.goodReceipt',
color: props.receive ? '--blue-6-hsl' : '--green-8-hsl',
},
Accept: {
status: 'taskOrder.receiveTask',
color: '--blue-6-hsl',
},
Submit: {
status: 'taskOrder.sentTask',
color: '--blue-6-hsl',
},
};
return mappings[value]?.[type] || '';
}
function getCreatedByName(
record: TaskOrder,
opts?: {
locale?: string;
},
) {
const createdBy = record.createdBy;
return (
{
['eng']: `${useOptionStore().mapOption(createdBy?.namePrefix) || ''} ${createdBy?.firstNameEN} ${createdBy?.lastNameEN}`,
['tha']: `${useOptionStore().mapOption(createdBy?.namePrefix) || ''} ${createdBy?.firstName} ${createdBy?.lastName}`,
}[opts?.locale || 'eng'] || '-'
);
}
function openList(index: number, data: TaskOrder) {
if (!currentBtnOpen.value[index]) {
// currentBtnOpen.value.map((v, i) => {
// if (i !== index) {
// currentBtnOpen.value[i] = false;
// }
// });
emit('clickSubRow', index, data);
}
currentBtnOpen.value[index] = !currentBtnOpen.value[index];
}
const emit = defineEmits<{
(e: 'view', data: TaskOrder): void;
(e: 'clickSubRow', index: number, data: TaskOrder): void;
}>();
</script>
<template>
<q-table
v-bind="props"
:columns="column"
bordered
flat
hide-pagination
card-container-class="q-col-gutter-sm"
:rows-per-page-options="[0]"
class="full-width"
:no-data-label="$t('general.noDataTable')"
row-key="id"
v-model:selected="selectedTask"
hide-selected-banner
>
<template v-slot:header="props">
<q-tr
style="background-color: hsla(var(--info-bg) / 0.07)"
:props="props"
>
<q-th v-if="selection !== 'none'">
<q-checkbox v-model="props.selected" size="sm" />
</q-th>
<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: TaskOrder;
} & Omit<Parameters<QTableSlots['body']>[0], 'row'>"
>
<q-tr class="text-center">
<q-td v-if="selection !== 'none'">
<q-checkbox v-model="props.selected" size="sm" />
</q-td>
<q-td v-if="visibleColumns.includes('order')">
{{ props.rowIndex + 1 }}
</q-td>
<q-td v-if="visibleColumns.includes('taskName')" class="text-left">
<div>
{{ props.row.taskName || '-' }}
<q-tooltip :delay="300">
{{ props.row.taskName || '-' }}
</q-tooltip>
</div>
<div class="text-caption app-text-muted">
{{ props.row.code || '-' }}
</div>
</q-td>
<q-td v-if="visibleColumns.includes('issueBranch')">-</q-td>
<q-td v-if="visibleColumns.includes('institution')">
{{
$i18n.locale === 'eng'
? props.row.institution.nameEN || '-'
: props.row.institution.name || '-'
}}
</q-td>
<q-td v-if="visibleColumns.includes('createdAt')">
{{
dateFormatJS({
date: props.row.createdAt,
dayStyle: '2-digit',
monthStyle: '2-digit',
}) || '-'
}}
{{ dateFormat(props.row.createdAt, false, true) }}
</q-td>
<q-td v-if="visibleColumns.includes('createdBy')" class="text-left">
{{ getCreatedByName(props.row, $i18n) }}
</q-td>
<q-td v-if="visibleColumns.includes('contactTel')">
{{ props.row.contactTel || '-' }}
</q-td>
<q-td v-if="visibleColumns.includes('contactName')" class="text-left">
{{ props.row.contactName || '-' }}
</q-td>
<q-td v-if="visibleColumns.includes('taskStatus')">
<BadgeComponent
hide-icon
:hsla-color="taskOrderStatus(props.row.taskOrderStatus, 'color')"
:title="$t(taskOrderStatus(props.row.taskOrderStatus, 'status'))"
/>
</q-td>
<q-td v-if="selection === 'none'">
<q-btn
:id="`btn-eye-${props.row.taskName}`"
icon="mdi-eye-outline"
size="sm"
dense
round
flat
@click.stop="$emit('view', props.row)"
/>
<KebabAction
v-if="false"
:idName="`btn-kebab-${props.row.taskName}`"
status="'ACTIVE'"
hide-toggle
:hide-edit="true"
@view="$emit('view', props.row)"
/>
</q-td>
<q-td v-else>
<q-btn
dense
flat
class="rounded"
@click.stop="
() => {
openList(props.rowIndex, props.row);
}
"
>
<div class="row items-center no-wrap">
<q-icon name="mdi-account-group-outline" />
<q-icon
class="btn-arrow-right"
:class="{
active: currentBtnOpen[props.rowIndex],
}"
size="xs"
:name="`mdi-chevron-${currentBtnOpen[props.rowIndex] ? 'down' : 'up'}`"
/>
</div>
</q-btn>
</q-td>
</q-tr>
<q-tr v-show="currentBtnOpen[props.rowIndex]" :props="props">
<q-td colspan="100%" style="padding: 16px">
<slot name="subRow" :props="props"></slot>
</q-td>
</q-tr>
</template>
<template v-slot:item="props">
<div class="col-md-4 col-sm-6 col-12">
<!-- TODO: status -->
<QuotationCard
:status="$t(taskOrderStatus(props.row.taskOrderStatus, 'status'))"
:badge-color="taskOrderStatus(props.row.taskOrderStatus, 'color')"
hide-action
hidePreview
:code="props.row.code"
:title="props.row.taskName"
:custom-data="[
{
label: $t('taskOrder.issueBranch'),
value: props.row.issueBranch,
},
{
label: $t('general.agencies'),
value:
$i18n.locale === 'eng'
? props.row.institution.nameEN
: props.row.institution.name,
},
{
label: $t('taskOrder.issueDate'),
value: `${dateFormatJS({
date: props.row.createdAt,
dayStyle: '2-digit',
monthStyle: '2-digit',
})} ${dateFormat(props.row.createdAt, false, true)}`,
},
{
label: $t('taskOrder.madeBy'),
value: getCreatedByName(props.row, $i18n),
},
{
label: $t('general.telephone'),
value: props.row.contactTel,
},
{
label: $t('taskOrder.contactName'),
value: props.row.contactName,
},
]"
@view="$emit('view', props.row)"
/>
</div>
</template>
</q-table>
</template>
<style scoped>
:deep(.q-table tbody td:after) {
background: transparent;
}
</style>