hdwposxy/src/pages/obi/order/list/index.vue

412 lines
11 KiB
Vue

<script setup lang="ts">
import { endOfMonth, format, startOfDay, startOfMonth, subDays, subMonths } from 'date-fns'
import { VDataTableServer } from 'vuetify/labs/VDataTable'
import { paginationMeta } from '@api-utils/paginationMeta'
const { t } = useI18n()
// Data table Headers
const headers = [
{ title: 'Id', key: 'meta.id' },
{ title: t('Order'), key: 'common.orderId' },
{ title: t('Date'), key: 'common.transaction.transactionDate' },
{ title: t('Status'), key: 'common.statusData.code' },
{ title: t('Type'), key: 'common.transaction.transactionTypeDescription' },
]
const selectedStatus = ref()
const status = [
'canceled',
'complete',
'fulfilled',
'intransit',
'intransit polled',
'new_order',
'open',
'polled',
'received',
'unfulfillable',
]
const selectedType = ref()
const type = [
{ id: 'PICKUP', title: 'Pickup Order' },
{ id: 'DELIVERY', title: 'Delivery Order' },
{ id: 'SHIPTOSTORE', title: 'Ship-to-Store Order' },
{ id: 'RETAILPICKUP', title: 'Retail Pickup Order' },
{ id: 'SHIPFORPICKUP', title: 'Ship-for-Pickup Order' },
{ id: 'UNKNOWN', title: 'unknown transaction type' },
]
const searchQuery = ref('')
// Data table options
const itemsPerPage = ref(10)
const page = ref(1)
const sortBy = ref('request_id')
const orderBy = ref('desc')
const beginDate = ref<Date | null>(null)
const endDate = ref<Date | null>(null)
const sortByMapping = (sortby: string) => {
const headerMapping: { [key: string]: string } = {
'meta.id': 'request_id',
'common.orderId': 'order_id',
'common.transaction.transactionDate': 'transaction_date',
'common.statusData.code': 'status',
'common.transaction.transactionTypeDescription': 'transaction_type_description',
}
return headerMapping[sortby] || sortby
}
const updateOptions = (options: any) => {
page.value = options.page
// updateOptions was called systematically by VDataTableServer with an empty object
if (options.sortBy[0]?.key) {
sortBy.value = sortByMapping(options.sortBy[0].key)
orderBy.value = options.sortBy[0].order
}
}
const { data: ordersData } = await useApi<any>(createUrl('/obi/order',
{
query: {
q: searchQuery,
page,
itemsPerPage,
sortBy,
orderBy,
status: selectedStatus,
type: selectedType,
minDate: beginDate,
maxDate: endDate,
},
},
))
const widgetData = computed(() => ordersData.value.statistics)
const orders = computed(() => ordersData.value.orders)
const totalOrder = computed(() => ordersData.value.total)
watch(beginDate, newBeginDate => {
if (endDate.value && newBeginDate !== null && newBeginDate > endDate.value)
endDate.value = newBeginDate
})
watch(endDate, newEndDate => {
if (beginDate.value && newEndDate !== null && newEndDate < beginDate.value)
beginDate.value = newEndDate
})
const selectLastMonth = () => {
beginDate.value = startOfMonth(subMonths(new Date(), 1))
endDate.value = endOfMonth(subMonths(new Date(), 1))
}
const selectThisMonth = () => {
const today = new Date()
const firstDayOfMonth = startOfMonth(today)
const lastDayOfMonth = endOfMonth(today)
beginDate.value = firstDayOfMonth
endDate.value = today < lastDayOfMonth ? today : lastDayOfMonth
}
const selectLast7Days = () => {
beginDate.value = startOfDay(subDays(new Date(), 6))
endDate.value = startOfDay(new Date())
}
const selectToday = () => {
beginDate.value = startOfDay(new Date())
endDate.value = startOfDay(new Date())
}
const clearDates = () => {
beginDate.value = null
endDate.value = null
}
</script>
<template>
<VBreadcrumbs
class="px-0 py-2"
:items="[
{ title: t('Home'), to: { name: 'root' } },
{ title: t('Order list') },
]"
/>
<div>
<VCard class="mb-6">
<!-- 👉 Widgets -->
<VCardText>
<VRow>
<template
v-for="(data, id) in widgetData"
:key="id"
>
<VCol
cols="12"
sm="6"
md="2"
class="px-6"
>
<div
class="d-flex justify-space-between"
:class="$vuetify.display.xs
? 'product-widget'
: $vuetify.display.sm
? id < 2 ? 'product-widget' : ''
: ''"
>
<div class="d-flex flex-column gap-y-1">
<h4 class="text-h4">
{{ data.value }}
</h4>
<VChip
v-bind="resolveOrderStatus(data.title)"
variant="tonal"
label
size="default"
/>
</div>
<VAvatar
variant="tonal"
rounded
size="38"
>
<VIcon
:icon="data.icon"
size="28"
/>
</VAvatar>
</div>
</VCol>
<VDivider
v-if="$vuetify.display.mdAndUp ? id !== widgetData.length - 1
: $vuetify.display.smAndUp ? id % 2 === 0
: false"
vertical
inset
length="55"
/>
</template>
</VRow>
</VCardText>
</VCard>
<VCard
:title="$t('Filters')"
class="mb-6"
>
<VCardText>
<VRow>
<!-- 👉 Select Status -->
<VCol
cols="12"
sm="4"
>
<AppSelect
v-model="selectedStatus"
:placeholder="$t('Status')"
:items="status"
clearable
clear-icon="tabler-x"
/>
</VCol>
<!-- 👉 Select Type -->
<VCol
cols="12"
sm="4"
>
<AppSelect
v-model="selectedType"
:placeholder="$t('Type')"
:items="type"
clearable
clear-icon="tabler-x"
item-text="title"
item-value="id"
/>
</VCol>
</VRow>
<VRow>
<VCol
cols="12"
sm="4"
>
<!-- 👉 Begin Date -->
<AppDateTimePicker
v-model="beginDate"
:placeholder="$t('Date begin')"
:config="{ altFormat: 'J M Y', altInput: true, dateFormat: 'Ymd' }"
/>
</VCol>
<VCol
cols="12"
sm="4"
>
<!-- 👉 End Date -->
<AppDateTimePicker
v-model="endDate"
:placeholder="$t('Date end')"
:config="{ altFormat: 'J M Y', altInput: true, dateFormat: 'Ymd' }"
/>
</VCol>
<VCol
cols="12"
sm="4"
>
<VBtn
variant="text"
@click="selectLastMonth"
>
{{ $t('Last month') }}
</VBtn>
<VBtn
variant="text"
@click="selectThisMonth"
>
{{ $t('This month') }}
</VBtn>
<VBtn
variant="text"
@click="selectLast7Days"
>
{{ $t('Last 7 days') }}
</VBtn>
<VBtn
variant="text"
@click="selectToday"
>
{{ $t('Today') }}
</VBtn>
<VBtn
variant="text"
@click="clearDates"
>
{{ $t('All') }}
</VBtn>
</VCol>
</VRow>
</VCardText>
</VCard>
<!-- 👉 Order Table -->
<VCard>
<!-- 👉 Filters -->
<VCardText>
<div class="d-flex justify-sm-space-between justify-start flex-wrap gap-4">
<VTextField
v-model="searchQuery"
density="compact"
:placeholder="$t('Search')"
style=" max-inline-size: 200px; min-inline-size: 200px;"
/>
<div class="d-flex gap-x-4 align-center">
<AppSelect
v-model="itemsPerPage"
style="min-inline-size: 6.25rem;"
:items="[5, 10, 20, 50, 100]"
/>
<VBtn
variant="tonal"
color="secondary"
prepend-icon="tabler-screen-share"
text="Export"
append-icon="tabler-chevron-down"
/>
</div>
</div>
</VCardText>
<VDivider />
<!-- 👉 Order Table -->
<VDataTableServer
v-model:items-per-page="itemsPerPage"
v-model:page="page"
v-model:sort-desc="orderBy"
v-model:sort-by:="sortBy"
:headers="headers"
:items="orders"
:items-length="totalOrder"
class="text-no-wrap"
density="compact"
@update:options="updateOptions"
>
<!-- Order ID -->
<template #item.common.orderId="{ item }">
<RouterLink
:to="{ name: 'obi-order-details-id', params: { id: item.meta.id } }"
class="font-weight-medium"
>
#{{ item.common.orderId }}
</RouterLink>
</template>
<!-- Date -->
<template #item.common.transaction.transactionDate="{ item }">
{{ format(item.common.transaction.transactionDate, "EEEE d MMMM yyyy HH:mm:ss") }}
</template>
<!-- Status -->
<template #item.common.statusData.code="{ item }">
<VChip
v-bind="resolveOrderStatus(item.common.statusData.code)"
label
/>
</template>
<!-- pagination -->
<template #bottom>
<VDivider />
<div class="d-flex align-center justify-sm-space-between justify-center flex-wrap gap-3 pa-5 pt-3">
<p class="text-sm text-disabled mb-0">
{{ paginationMeta({ page, itemsPerPage }, totalOrder) }}
</p>
<VPagination
v-model="page"
:length="Math.ceil(totalOrder / itemsPerPage)"
:total-visible="$vuetify.display.xs ? 1 : Math.min(Math.ceil(totalOrder / itemsPerPage), 5)"
>
<template #prev="slotProps">
<VBtn
variant="tonal"
color="default"
v-bind="slotProps"
:icon="false"
>
{{ $t('$vuetify.pagination.ariaLabel.previous') }}
</VBtn>
</template>
<template #next="slotProps">
<VBtn
variant="tonal"
color="default"
v-bind="slotProps"
:icon="false"
>
{{ $t('$vuetify.pagination.ariaLabel.next') }}
</VBtn>
</template>
</VPagination>
</div>
</template>
</VDataTableServer>
</VCard>
</div>
</template>