feat: add obi order visualization

feat/issue-3/obi
Frédérik Benoist 2024-01-07 21:10:13 +01:00
parent c2d60ae2b3
commit 5419bb538e
14 changed files with 796 additions and 0 deletions

63
dependencies.txt Executable file
View File

@ -0,0 +1,63 @@
# Dépendances avec les liens npm et GitHub
## Dépendances de développement
- @antfu/eslint-config-vue : [npm](https://www.npmjs.com/package/@antfu/eslint-config-vue), [GitHub](https://github.com/antfu/eslint-config) - Configuration ESLint pour les projets Vue.js
- @antfu/utils : [npm](https://www.npmjs.com/package/@antfu/utils), [GitHub](https://github.com/antfu/utils) - Utilitaires utiles pour le développement avec Vite
- @fullcalendar/core : [npm](https://www.npmjs.com/package/@fullcalendar/core), [GitHub](https://github.com/fullcalendar/fullcalendar) - Bibliothèque de calendrier complète pour les applications web
- @fullcalendar/daygrid : [npm](https://www.npmjs.com/package/@fullcalendar/daygrid), [GitHub](https://github.com/fullcalendar/daygrid) - Extension de grille de jours pour FullCalendar
- @fullcalendar/interaction : [npm](https://www.npmjs.com/package/@fullcalendar/interaction), [GitHub](https://github.com/fullcalendar/interaction) - Prise en charge de l'interaction utilisateur pour FullCalendar
- @fullcalendar/list : [npm](https://www.npmjs.com/package/@fullcalendar/list), [GitHub](https://github.com/fullcalendar/list) - Extension de liste pour FullCalendar
- @fullcalendar/timegrid : [npm](https://www.npmjs.com/package/@fullcalendar/timegrid), [GitHub](https://github.com/fullcalendar/timegrid) - Extension de grille temporelle pour FullCalendar
- @fullcalendar/vue3 : [npm](https://www.npmjs.com/package/@fullcalendar/vue3), [GitHub](https://github.com/fullcalendar/vue) - Intégration Vue 3 pour FullCalendar
- @iconify-json/mdi : [npm](https://www.npmjs.com/package/@iconify-json/mdi), [GitHub](https://github.com/iconify/iconify-json) - Bibliothèque d'icônes Material Design pour Iconify
- @iconify/tools : [npm](https://www.npmjs.com/package/@iconify/tools), [GitHub](https://github.com/iconify/iconify-tools) - Outils pour travailler avec Iconify
- @iconify/utils : [npm](https://www.npmjs.com/package/@iconify/utils), [GitHub](https://github.com/iconify/iconify-utils) - Utilitaires pour Iconify
- @iconify/vue : [npm](https://www.npmjs.com/package/@iconify/vue), [GitHub](https://github.com/iconify/iconify-vue) - Composant Vue pour Iconify
- @intlify/unplugin-vue-i18n : [npm](https://www.npmjs.com/package/@intlify/unplugin-vue-i18n), [GitHub](https://github.com/intlify/unplugin) - Plugin Vue I18n pour Vite
- @tabler/icons : [npm](https://www.npmjs.com/package/@tabler/icons), [GitHub](https://github.com/tabler/tabler-icons) - Bibliothèque d'icônes Tabler
- @tiptap/extension-character-count : [npm](https://www.npmjs.com/package/@tiptap/extension-character-count), [GitHub](https://github.com/ueberdosis/tiptap) - Extension pour compter le nombre de caractères dans Tiptap
- @tiptap/extension-placeholder : [npm](https://www.npmjs.com/package/@tiptap/extension-placeholder), [GitHub](https://github.com/ueberdosis/tiptap) - Extension de l'indicateur de position dans Tiptap
- @tiptap/extension-subscript : [npm](https://www.npmjs.com/package/@tiptap/extension-subscript), [GitHub](https://github.com/ueberdosis/tiptap) - Extension pour le texte en indice dans Tiptap
- @tiptap/extension-superscript : [npm](https://www.npmjs.com/package/@tiptap/extension-superscript), [GitHub](https://github.com/ueberdosis/tiptap) - Extension pour le texte en exposant dans Tiptap
- @tiptap/extension-underline : [npm](https://www.npmjs.com/package/@tiptap/extension-underline), [GitHub](https://github.com/ueberdosis/tiptap) - Extension pour souligner le texte dans Tiptap
- @types/mapbox-gl : [npm](https://www.npmjs.com/package/@types/mapbox-gl), [GitHub](https://github.com/DefinitelyTyped/DefinitelyTyped) - Types TypeScript pour Mapbox GL
- @types/node : [npm](https://www.npmjs.com/package/@types/node), [GitHub](https://github.com/DefinitelyTyped/DefinitelyTyped) - Types TypeScript pour Node.js
- @types/webfontloader : [npm](https://www.npmjs.com/package/@types/webfontloader), [GitHub](https://github.com/DefinitelyTyped/DefinitelyTyped) - Types TypeScript pour WebFontLoader
- @typescript-eslint/eslint-plugin : [npm](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin), [GitHub](https://github.com/typescript-eslint/typescript-eslint) - Plugin ESLint pour TypeScript
- @typescript-eslint/parser : [npm](https://www.npmjs.com/package/@typescript-eslint/parser), [GitHub](https://github.com/typescript-eslint/typescript-eslint) - Analyseur ESLint pour TypeScript
- @videojs-player/vue : [npm](https://www.npmjs.com/package/@videojs-player/vue), [GitHub](https://github.com/videojs/theater) - Composant Vue pour Video.js
- @vitejs/plugin-vue : [npm](https://www.npmjs.com/package/@vitejs/plugin-vue), [GitHub](https://github.com/vitejs/vite)
- @vitejs/plugin-vue-jsx : [npm](https://www.npmjs.com/package/@vitejs/plugin-vue-jsx), [GitHub](https://github.com/vitejs/vite)
- date-fns : [npm](https://www.npmjs.com/package/date-fns), [GitHub](https://github.com/date-fns/date-fns) - Bibliothèque JavaScript moderne de manipulation de dates
- eslint : [npm](https://www.npmjs.com/package/eslint), [GitHub](https://github.com/eslint/eslint) - Linter JavaScript/TypeScript
- eslint-config-airbnb-base : [npm](https://www.npmjs.com/package/eslint-config-airbnb-base), [GitHub](https://github.com/airbnb/javascript) - Configuration ESLint pour les règles Airbnb (base)
- eslint-import-resolver-typescript : [npm](https://www.npmjs.com/package/eslint-import-resolver-typescript), [GitHub](https://github.com/alexgorbatchev/eslint-import-resolver-typescript) - Résolveur d'importation ESLint pour TypeScript
- eslint-plugin-case-police : [npm](https://www.npmjs.com/package/eslint-plugin-case-police), [GitHub](https://github.com/antfu/eslint-plugin-case-police) - Plugin ESLint pour l'ajustement de casse dans le code
- eslint-plugin-import : [npm](https://www.npmjs.com/package/eslint-plugin-import), [GitHub](https://github.com/benmosher/eslint-plugin-import) - Plugin ESLint pour les règles d'importation
- eslint-plugin-promise : [npm](https://www.npmjs.com/package/eslint-plugin-promise), [GitHub](https://github.com/xjamundx/eslint-plugin-promise) - Plugin ESLint pour les règles liées aux promesses
- eslint-plugin-regex : [npm](https://www.npmjs.com/package/eslint-plugin-regex), [GitHub](https://github.com/ota-meshi/eslint-plugin-regex) - Plugin ESLint pour les règles de regex
- eslint-plugin-sonarjs : [npm](https://www.npmjs.com/package/eslint-plugin-sonarjs), [GitHub](https://github.com/SonarSource/eslint-plugin-sonarjs) - Plugin ESLint pour les règles SonarJS
- eslint-plugin-unicorn : [npm](https://www.npmjs.com/package/eslint-plugin-unicorn), [GitHub](https://github.com/sindresorhus/eslint-plugin-unicorn) - Plugin ESLint pour des règles diverses et utiles
- eslint-plugin-vue : [npm](https://www.npmjs.com/package/eslint-plugin-vue), [GitHub](https://github.com/vuejs/eslint-plugin-vue) - Plugin ESLint pour les règles Vue.js
- msw : [npm](https://www.npmjs.com/package/msw), [GitHub](https://github.com/mswjs/msw) - Outil de simulation de requêtes HTTP pour les tests
- postcss-html : [npm](https://www.npmjs.com/package/postcss-html), [GitHub](https://github.com/yisar/postcss-html) - Plugin PostCSS pour traiter les fichiers HTML en CSS
- postcss-scss : [npm](https://www.npmjs.com/package/postcss-scss), [GitHub](https://github.com/postcss/postcss-scss) - Plugin PostCSS pour la syntaxe SCSS
- sass : [npm](https://www.npmjs.com/package/sass), [GitHub](https://github.com/sass/sass) - Préprocesseur CSS Sass
- stylelint : [npm](https://www.npmjs.com/package/stylelint), [GitHub](https://github.com/stylelint/stylelint) - Linter pour les feuilles de style CSS/SCSS
- stylelint-codeguide : [npm](https://www.npmjs.com/package/stylelint-codeguide), [GitHub](https://github.com/kristerkari/stylelint-codeguide) - Guide de style et configuration Stylelint
- stylelint-config-idiomatic-order : [npm](https://www.npmjs.com/package/stylelint-config-idiomatic-order), [GitHub](https://github.com/ream88/stylelint-config-idiomatic-order) - Configuration Stylelint avec un ordre idiomatique
- stylelint-config-standard-scss : [npm](https://www.npmjs.com/package/stylelint-config-standard-scss), [GitHub](https://github.com/kristerkari/stylelint-config-standard-scss) - Configuration Stylelint pour SCSS basée sur les règles standard
- stylelint-use-logical-spec : [npm](https://www.npmjs.com/package/stylelint-use-logical-spec), [GitHub](https://github.com/iKettles/stylelint-use-logical-spec) - Plugin Stylelint pour promouvoir l'utilisation de spécifications logiques
- tsx : [npm](https://www.npmjs.com/package/tsx), [GitHub](https://github.com/windicss/tsx) - Plugin WindiCSS pour la prise en charge de JSX/TSX
- type-fest : [npm](https://www.npmjs.com/package/type-fest), [GitHub](https://github.com/sindresorhus/type-fest) - Collection de types TypeScript utiles
- typescript : [npm](https://www.npmjs.com/package/typescript), [GitHub](https://github.com/microsoft/TypeScript) - Langage de programmation TypeScript
- unplugin-auto-import : [npm](https://www.npmjs.com/package/unplugin-auto-import), [GitHub](https://github.com/antfu/unplugin-auto-import) - Plugin Vite pour l'importation automatique
- unplugin-vue-components : [npm](https://www.npmjs.com/package/unplugin-vue-components), [GitHub](https://github.com/antfu/unplugin) - Plugin Vite pour la gestion des composants Vue
- unplugin-vue-router : [npm](https://www.npmjs.com/package/unplugin-vue-router), [GitHub](https://github.com/antfu/unplugin-vue-router) - Plugin Vite pour Vue Router
- video.js : [npm](https://www.npmjs.com/package/video.js), [GitHub](https://github.com/videojs/video.js) - Bibliothèque de lecteur vidéo JavaScript
- vite : [npm](https://www.npmjs.com/package/vite), [GitHub](https://github.com/vitejs/vite) - Constructeur d'outils rapide pour le développement web moderne
- vite-plugin-vue-devtools : [npm](https://www.npmjs.com/package/vite-plugin-vue-devtools), [GitHub](https://github.com/antfu/vite-plugin-vue-devtools) - Plugin Vite pour intégrer les outils de développement Vue.js
- vite-plugin-vue-layouts : [npm](https://www.npmjs.com/package/vite-plugin-vue-layouts), [GitHub](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) - Plugin Vite pour la gestion des mises en page Vue.js
- vite-plugin-vuetify : [npm](https://www.npmjs.com/package/vite-plugin-vuetify), [GitHub](https://github.com/antfu/vite-plugin-vuetify) - Plugin Vite pour l'intégration de Vuetify
- vue-shepherd : [npm](https://www.npmjs.com/package/vue-shepherd), [GitHub](https://github.com/hipstersmoothie/vue-shepherd) - Tour de guide pour les applications Vue.js
- vue-tsc : [npm](https://www.npmjs.com/package/vue-tsc), [GitHub](https://github.com/johnsoncodehk/vue-tsc) - Plugin TypeScript pour la compilation de fichiers `.vue`

68
src/models/Order.ts Normal file
View File

@ -0,0 +1,68 @@
interface meta {
id: number
}
interface statusData {
code: string
title: string
}
interface transaction {
transactionTypeId: number
transactionDate: Date
transactionNo: string
transactionTypeDescription: string
transactionSubtotal: number
transactionTax: number
transactionTotal: number
}
interface Common {
orderId: string
requestingLocationCd: string
requestingSystemCd: string
customerId: string
customerFirstName: string
customerLastName: string
status: string
submitOrdMsg: string
fdateCreation: Date
consumed: boolean
shipforpickupLocationCd: string
shipforpickupSystemCd: string
statusData: statusData
transaction: transaction
}
interface Lines {
lineOrderId: number
lineItemNo: number
orderId: string
requestId: number
lineItemOms: string
itemId: string
orderedLineQty: number
status: string
transactionDate: Date
shippingAgent: string
trackingNumber: string
fulfillmentId: string
cartonNumber: string
fdateCreation: Date
consumed: boolean
}
interface History {
statusId: number
Id: number
status: string
transactionDate: Date
fdateCreation: Date
}
export interface Order {
meta: meta
common: Common
lines: Lines[]
history: History[]
}

View File

@ -23,6 +23,13 @@ export default [
{
title: 'OBI',
icon: { icon: 'tabler-shopping-bag-check' },
children: [
{
title: 'Orders list',
to: { name: 'obi-order-list' },
icon: { icon: 'tabler-bug' },
},
],
},
{
title: 'Dotsoft',

View File

@ -23,6 +23,13 @@ export default [
{
title: 'OBI',
icon: { icon: 'tabler-shopping-bag-check' },
children: [
{
title: 'Orders',
to: { name: 'obi-order-list' },
icon: { icon: 'tabler-bug' },
},
],
},
{
title: 'Dotsoft',

View File

@ -302,6 +302,7 @@ const exportEXCEL = () => {
:items-per-page="options.itemsPerPage"
:page="options.page"
:options="options"
density="compact"
/>
</VCol>
</Vcard>

View File

@ -0,0 +1,109 @@
<script setup lang="ts">
import type { Order } from '@/models/Order'
import OrderPanel from '@/views/pages/order/view/OrderPanel.vue'
import OrderTabGeneral from '@/views/pages/order/view/OrderTabGeneralH.vue'
const { t } = useI18n()
const route = useRoute('obi-order-details-id')
const orderData = ref<Order>()
const orderTab = ref(null)
const tabs = [
{ title: 'General' },
{ title: 'Preparation' },
{ title: 'Receipt' },
{ title: 'Flow' },
]
const { data, error } = await useApi<Order>(`/obi/order/${route.params.id}`)
if (error.value)
console.log(error.value)
else if (data.value)
orderData.value = data.value
</script>
<template>
<VBreadcrumbs
class="px-0 py-2"
:items="[
{ title: t('Home'), to: { name: 'root' } },
{ title: t('Order list'), to: { name: 'obi-order-list' } },
{ title: `#${route.params.id}` },
]"
/>
<div>
<!-- 👉 Header -->
<div class="d-flex justify-space-between align-center flex-wrap gap-y-4 mb-6">
<div>
<div class="d-flex gap-2 align-center mb-0 flex-wrap">
<h4 class="text-h3 font-weight-medium">
Order Id: {{ orderData && orderData.common.orderId }}
</h4>
<div class="d-flex gap-2">
<VChip
label
color="success"
size="x-large"
>
{{ orderData && orderData.common.statusData.code }}
</VChip>
<VChip
label
size="x-large"
:color="orderData && orderData.common.consumed ? 'success' : 'error'"
>
{{ orderData && orderData.common.consumed ? 'Consumed' : 'Not consumed' }}
</VChip>
</div>
</div>
</div>
<div class="d-flex gap-4">
<VBtn
variant="tonal"
color="primary"
>
Reload
</VBtn>
</div>
</div>
<!-- 👉 Order -->
<VRow v-if="orderData">
<VCol
cols="12"
md="5"
lg="4"
>
<OrderPanel :order-data="orderData" />
</VCol>
<VCol
cols="12"
md="7"
lg="8"
>
<VTabs
v-model="orderTab"
class="v-tabs-pill mb-3 disable-tab-transition"
>
<VTab
v-for="tab in tabs"
:key="tab.title"
>
<span>{{ tab.title }}</span>
</VTab>
</VTabs>
<VWindow
v-model="orderTab"
class="disable-tab-transition"
:touch="false"
>
<!-- 👉 General -->
<VWindowItem>
<OrderTabGeneral :order-data="orderData" />
</VWindowItem>
</VWindow>
</VCol>
</VRow>
</div>
</template>

View File

@ -0,0 +1,244 @@
<script setup lang="ts">
import { VDataTableServer } from 'vuetify/labs/VDataTable'
import { paginationMeta } from '@api-utils/paginationMeta'
const { t } = useI18n()
const widgetData = ref([
{ title: 'Pending Payment', value: 56, icon: 'tabler-calendar-stats' },
{ title: 'Unfulfilled', value: 25, icon: 'tabler-circle-x' },
{ title: 'Completed', value: 12689, icon: 'tabler-checks' },
{ title: 'Refunded', value: 124, icon: 'tabler-wallet' },
])
const searchQuery = ref('')
// Data table options
const itemsPerPage = ref(10)
const page = ref(1)
const sortBy = ref()
const orderBy = ref()
// Data table Headers
const headers = [
{ title: 'Id', key: 'meta.id' },
{ title: 'Order', key: 'common.orderId' },
{ title: 'Date', key: 'common.transaction.transactionDate' },
{ title: 'Status', key: 'common.statusData.code' },
{ title: 'Type', key: 'common.transaction.transactionTypeDescription' },
]
// Update data table options
const updateOptions = (options: any) => {
page.value = options.page
sortBy.value = options.sortBy[0]?.key
orderBy.value = options.sortBy[0]?.order
}
const resolveStatus = (status: string) => {
if (status === 'fulfilled')
return { text: 'fulfilled', color: 'success' }
else if (status === 'received')
return { text: 'received', color: 'primary' }
else if (status === 'intransit polled')
return { text: 'intransit polled', color: 'info' }
else if (status === 'new_order')
return { text: 'new_order', color: 'warning' }
else
return { text: status, color: 'error' }
}
const { data: ordersData } = await useApi<any>(createUrl('/obi/order',
{
query: {
q: searchQuery,
page,
itemsPerPage,
sortBy,
orderBy,
},
},
))
const orders = computed(() => ordersData.value.orders)
const totalOrder = computed(() => ordersData.value.total)
</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="3"
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>
<h6 class="text-h6">
{{ data.title }}
</h6>
</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>
<!-- 👉 Filters -->
<VCardText>
<div class="d-flex justify-sm-space-between justify-start flex-wrap gap-4">
<VTextField
v-model="searchQuery"
density="compact"
placeholder="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"
: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>
<!-- Status -->
<template #item.common.statusData.code="{ item }">
<VChip
v-bind="resolveStatus(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"
>
Previous
</VBtn>
</template>
<template #next="slotProps">
<VBtn
variant="tonal"
color="default"
v-bind="slotProps"
:icon="false"
>
Next
</VBtn>
</template>
</VPagination>
</div>
</template>
</VDataTableServer>
</VCard>
</div>
</template>
<style lang="scss" scoped>
.customer-title:hover{
color: rgba(var(--v-theme-primary)) !important;
}
.product-widget{
border-block-end: 1px solid rgba(var(--v-theme-on-surface), var(--v-border-opacity));
padding-block-end: 1rem;
}
</style>

View File

@ -275,6 +275,7 @@ watch(route, (to, from) => {
:items-per-page="stStoreList.itemsPerPage"
:page="stStoreList.currentPage"
:sort-by="stStoreList.getSortBy()"
density="compact"
@update:sort-by="sortBy => { stStoreList.setSortBy(sortBy[0]?.key) ; stStoreList.setSortOrder(sortBy[0]?.order) }"
@update:items-per-page="itemsPerPage => { stStoreList.setItemsPerPage(itemsPerPage) }"
@update:page="page => { stStoreList.setCurrentPage(page) }"

View File

@ -70,6 +70,7 @@
"Dates range error": "With a date range, a text of at least 5 characters must be specified",
"Close": "Close",
"Connect to invidual POS": "Connect to invidual POS",
"Orders list": "Orders list",
"---------------------------": "---------------------------",
"UI Elements": "عناصر واجهة المستخدم",
"Forms & Tables": "النماذج والجداول",

View File

@ -70,6 +70,7 @@
"Dates range error": "With a date range, a text of at least 5 characters must be specified",
"Close": "Close",
"Connect to invidual POS": "Connect to invidual POS",
"Orders list": "Orders list",
"---------------------------": "---------------------------",
"UI Elements": "UI Elements",
"Forms & Tables": "Forms & Tables",

View File

@ -70,6 +70,7 @@
"Dates range error": "Dans le cas d'une plage de dates, un texte d'au moins 5 caractères doit être spécifié.",
"Close": "Fermer",
"Connect to invidual POS": "Connexion à une caisse individuelle",
"Orders list": "Liste des commandes",
"---------------------------": "---------------------------",
"UI Elements": "ÉLÉMENTS DE L'UI",
"Forms & Tables": "Formulaires et tableaux",

View File

@ -0,0 +1,133 @@
import { propsToCopy } from '@iconify/utils/lib/icon-set/get-icons';
<script setup lang="ts">
import { format } from 'date-fns'
import type { Order } from '@/models/Order'
const props = defineProps<Props>()
const resolveConsumed = (consumed: boolean) => {
if (consumed)
return { text: 'Consumed', color: 'success' }
else
return { text: 'Not consumed', color: 'error' }
}
interface Props {
orderData: Order
}
</script>
<template>
<VRow>
<!-- SECTION Order -->
<VCol cols="12">
<VCard v-if="props.orderData">
<!-- 👉 Order Details -->
<VCardText>
<div class="text-disabled text-uppercase text-sm">
Order Details
</div>
<VList class="card-list mt-2">
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Origin request:</span>
<span>
{{ props.orderData.common.requestingLocationCd }} / {{ props.orderData.common.requestingSystemCd }}
</span>
</div>
</VListItem>
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Cust Id:</span>
<span>
{{ props.orderData.common.customerId }}
</span>
</div>
</VListItem>
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Cust. name:</span>
<span>
{{ props.orderData.common.customerLastName }} {{ props.orderData.common.customerFirstName }}
</span>
</div>
</VListItem>
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Date creation:</span>
<span>
{{ format(props.orderData.common.fdateCreation, "yyyy-MM-dd HH:mm:ss") }}
</span>
</div>
</VListItem>
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Ship for Pickup:</span>
<span>
{{ props.orderData.common.shipforpickupLocationCd }} / {{ props.orderData.common.shipforpickupSystemCd }}
</span>
</div>
</VListItem>
</VList>
<div class="text-disabled text-uppercase mt-4 text-sm">
Transaction
</div>
<VList class="card-list mt-2">
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">No:</span>
<span>
{{ props.orderData.common.transaction.transactionNo }}
</span>
</div>
</VListItem>
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Date:</span>
<span>
{{ format(props.orderData.common.transaction.transactionDate, "yyyy-MM-dd HH:mm:ss") }}
</span>
</div>
</VListItem>
<VListItem>
<div class="text-body-1">
<span class="font-weight-bold me-2">Type:</span>
<span>
{{ props.orderData.common.transaction.transactionTypeDescription }}
</span>
</div>
</VListItem>
</VList>
</VCardText>
<VCardText class="text-center">
<VBtn>
Edit XML Details
</VBtn>
</VCardText>
<VCardText class="text-center">
<VBtn>
Proximis
</VBtn>
</VCardText>
<VCardText class="text-center">
<VBtn>
SQL Obi
</VBtn>
</VCardText>
</VCard>
</VCol>
</vrow>
</template>
<style lang="scss" scoped>
.card-list {
--v-card-list-gap: 0.75rem;
}
.text-capitalize {
text-transform: capitalize !important;
}
</style>

View File

@ -0,0 +1,158 @@
<script setup lang="ts">
import { format } from 'date-fns'
import { VDataTable } from 'vuetify/labs/VDataTable'
import type { Order } from '@/models/Order'
const props = defineProps<Props>()
const { t } = useI18n()
interface Props {
orderData: Order
}
const headers = computed(() => [
{ title: '', key: 'data-table-expand' },
{ title: '#', key: 'lineItemNo' },
{ title: t('Item'), key: 'itemId' },
{ title: t('Qty'), key: 'orderedLineQty' },
{ title: t('Date'), key: 'transactionDate' },
{ title: t('Status'), key: 'status' },
{ title: t('Created'), key: 'fdateCreation' },
])
</script>
<template>
<!-- 👉 Order Details -->
<VCard class="mb-6">
<VCardItem>
<template #title>
<h5 class="text-h5">
Order Lines
</h5>
</template>
</VCardItem>
<VDivider />
<VDataTable
:headers="headers"
:items="props.orderData.lines"
density="compact"
class="text-no-wrap dt-row-striped"
expand-on-click
>
<!-- Expanded Row Data -->
<template #expanded-row="slotProps">
<td :colspan="headers.length">
<VTable
density="compact"
class="text-no-wrap"
>
<thead>
<tr>
<th class="text-uppercase">
Status history
</th>
<th class="text-uppercase">
Transaction date history
</th>
<th class="text-uppercase">
Creation date history
</th>
</tr>
</thead>
<tbody>
<tr
v-for="item in slotProps.item.history"
:key="item.statusId"
>
<td>
{{ item.status }}
</td>
<td>
{{ format(item.transactionDate, "EEEE d MMMM yyyy HH:mm:ss") }}
</td>
<td>
{{ format(item.fdateCreation, "EEEE d MMMM yyyy HH:mm:ss") }}
</td>
</tr>
</tbody>
</VTable>
</td>
</template>
<template #item.transactionDate="{ item }">
{{ format(new Date(item.transactionDate), 'dd/MM/yyyy HH:mm:ss') }}
</template>
<template #item.fdateCreation="{ item }">
{{ format(new Date(item.fdateCreation), 'dd/MM/yyyy HH:mm:ss') }}
</template>
<template #bottom />
</VDataTable>
<VDivider />
<VCardText>
<div class="d-flex align-end flex-column">
<table class="text-high-emphasis">
<tbody>
<tr>
<td class="text-high-emphasis font-weight-medium">
Tax:
</td>
<td style="text-align: end;">
{{ parseFloat(orderData.common.transaction.transactionTax.toString()).toFixed(2) }}
</td>
</tr>
<tr>
<td class="text-high-emphasis font-weight-medium">
Total:
</td>
<td style="text-align: end;">
{{ parseFloat(orderData.common.transaction.transactionTotal.toString()).toFixed(2) }}
</td>
</tr>
</tbody>
</table>
</div>
</VCardText>
</VCard>
<!-- 👉 Order History -->
<VCard title="Order History">
<VCardText>
<VTimeline
truncate-line="both"
align="start"
side="end"
line-color="primary"
density="compact"
class="v-timeline-density-compact"
>
<template
v-for="(historyItem, index) in props.orderData.history"
:key="index"
>
<VTimelineItem
dot-color="primary"
size="x-small"
>
<div class="d-flex justify-space-between align-center">
<div class="app-timeline-title">
Order was {{ historyItem.status }} (Id: #{{ historyItem.statusId }})
</div>
<div class="app-timeline-meta">
{{ format(historyItem.transactionDate, "EEEE d MMMM yyyy HH:mm:ss") }}
</div>
</div>
<p class="app-timeline-text mb-0">
Your order has been {{ historyItem.status }} successfully
</p>
</VTimelineItem>
</template>
</VTimeline>
</VCardText>
</VCard>
</template>

2
typed-router.d.ts vendored
View File

@ -43,6 +43,8 @@ declare module 'vue-router/auto/routes' {
'$error': RouteRecordInfo<'$error', '/:error(.*)', { error: ParamValue<true> }, { error: ParamValue<false> }>,
'flux-bl-not-sent': RouteRecordInfo<'flux-bl-not-sent', '/flux/bl/not_sent', Record<never, never>, Record<never, never>>,
'login': RouteRecordInfo<'login', '/login', Record<never, never>, Record<never, never>>,
'obi-order-details-id': RouteRecordInfo<'obi-order-details-id', '/obi/order/details/:id', { id: ParamValue<true> }, { id: ParamValue<false> }>,
'obi-order-list': RouteRecordInfo<'obi-order-list', '/obi/order/list', Record<never, never>, Record<never, never>>,
'store-details': RouteRecordInfo<'store-details', '/store/details', Record<never, never>, Record<never, never>>,
'store-list': RouteRecordInfo<'store-list', '/store/list', Record<never, never>, Record<never, never>>,
'xadmin-log': RouteRecordInfo<'xadmin-log', '/xadmin/log', Record<never, never>, Record<never, never>>,