Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved: Order detail page on the open tab (#283) #302

Merged
merged 27 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
428740b
Implemented: Mobile-Responsive Order Detail Page UI with Order Items …
sanskar345 Sep 20, 2023
eb2a5fd
Implemented: Order Detail Page UI, inspired by Job Manager app (#283)
sanskar345 Sep 21, 2023
dda48c5
Implemented: alphabatical ordering of export components and imports a…
sanskar345 Sep 21, 2023
ba26058
Implemented: option in setting to allow partial order rejection and c…
sanskar345 Sep 26, 2023
8b79775
Implemented: order item rejection history modal and report an issue m…
sanskar345 Sep 27, 2023
21869d8
Fixed: error while refreshing order detail page (#283)
sanskar345 Sep 27, 2023
2c85db2
Implemented: comment the code to display text below the reject order …
sanskar345 Sep 27, 2023
68dfd0a
Implemented: logic for showing user the status of the current order i…
sanskar345 Sep 29, 2023
2d531d3
Implemented logic to reject single item in an order (#283)
sanskar345 Sep 29, 2023
72c3cf7
Improved: logic to reject single item in an order (#283)
sanskar345 Oct 3, 2023
df0ae34
Implemented: entries in locale files (#283)
sanskar345 Oct 3, 2023
4f59112
Improved: code by removing the unwanted lines (#283)
sanskar345 Oct 3, 2023
e997b7c
Implemented: logic to fetch orderItemHistory and reject reasons and c…
sanskar345 Oct 3, 2023
53d6883
Improved: order detail page UI using css grid, removed the the usage …
sanskar345 Oct 4, 2023
b5b2ca3
Implemented: entries in locale files for partial order rejection card…
sanskar345 Oct 4, 2023
4c3b8d1
Implemented: display order item rejection history (#283)
sanskar345 Oct 4, 2023
11273ca
Improved: order detail page css - placing the grid item (#283)
sanskar345 Oct 5, 2023
9826ba9
Implemented: logic to fetch products that exist in order item rejecti…
sanskar345 Oct 5, 2023
228e81e
Improved: reject order alert heading and button label (#283)
sanskar345 Oct 5, 2023
a19a276
Implemented: show alert before rejecting a single item (#283)
sanskar345 Oct 5, 2023
4b3e6e0
Improved: code and indentation (#283)
sanskar345 Oct 5, 2023
b81152c
Implemented: service to reject a single order item (#283)
sanskar345 Oct 6, 2023
3368b32
Improved: code and removed conditions that are unnecessary (#283)
sanskar345 Oct 6, 2023
4817eef
Improved: the placement of empty states css code in variables.css (#283)
sanskar345 Oct 9, 2023
2d32058
Merge branch 'main' of https://github.com/hotwax/bopis into bopis/#283
sanskar345 Oct 11, 2023
2f7a6cb
Implemented: do not dispatch stock/addProducts action while dispatchi…
sanskar345 Oct 11, 2023
a3f2c89
Implemented: modal to select reject reason before rejecting an order …
sanskar345 Oct 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/adapter/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { api, client, hasError, initialise, resetConfig, updateInstanceUrl, updateToken, getUserFacilities } from '@hotwax/oms-api'
import { api, client, getConfig, hasError, initialise, resetConfig, updateInstanceUrl, updateToken, getUserFacilities } from '@hotwax/oms-api'

export {
api,
client,
getConfig,
initialise,
hasError,
resetConfig,
Expand Down
111 changes: 111 additions & 0 deletions src/components/OrderItemRejHistoryModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon slot="icon-only" :icon="closeOutline" />
</ion-button>
</ion-buttons>
<ion-title>{{ $t("Order item rejection history") }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list v-for="(history, index) in rejectionHistory" :key="index">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to define for loop on the ion-item instead of defining it on ion-list

<ion-item>
<ion-thumbnail slot="start">
<ShopifyImg :src="getProduct(history.productId).mainImageUrl" size="small" />
</ion-thumbnail>
<ion-label>
<h5>{{ getProduct(history.productId).brandName }}</h5>
<h2>{{ getProduct(history.productId).productName }}</h2>
<p v-if="$filters.getFeature(getProduct(history.productId).featureHierarchy, '1/COLOR/')">{{ $t("Color") }}: {{ $filters.getFeature(getProduct(history.productId).featureHierarchy, '1/COLOR/') }}</p>
<p v-if="$filters.getFeature(getProduct(history.productId).featureHierarchy, '1/SIZE/')">{{ $t("Size") }}: {{ $filters.getFeature(getProduct(history.productId).featureHierarchy, '1/SIZE/') }}</p>
</ion-label>
<ion-label slot="end" class="ion-text-right">
<h2>{{ getRejectReasonDescription(history?.changeReasonEnumId) }}</h2>
<p>{{ history?.changeUserLogin }}</p>
<p>{{ getTime(history.changeDatetime) }}</p>
</ion-label>
</ion-item>
</ion-list>

<!-- Empty state -->
<div v-if="!rejectionHistory.length && !isLoading" class="empty-state">
<p>{{ $t('No records found.') }}</p>
</div>
</ion-content>
</template>

<script lang="ts">
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonThumbnail,
IonLabel,
IonList,
IonTitle,
IonToolbar,
modalController
} from '@ionic/vue';
import { defineComponent } from 'vue';
import { closeOutline } from 'ionicons/icons';
import { mapGetters, useStore } from "vuex";
import { DateTime } from 'luxon';

export default defineComponent({
name: "OrderItemRejHistoryModal",
components: {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonThumbnail,
IonLabel,
IonList,
IonTitle,
IonToolbar,
},
data () {
return {
isLoading: true
}
},
computed: {
...mapGetters({
getProduct: 'product/getProduct',
order: "order/getCurrent",
rejectReasons: 'util/getRejectReasons',
rejectionHistory: 'order/getOrderItemRejectionHistory'
})
},
async mounted() {
await this.store.dispatch('order/getOrderItemRejHistory', { orderId: this.order.orderId, rejectReasonEnumIds: this.rejectReasons.reduce((enumIds: [], reason: any) => [...enumIds, reason.enumId], []) });
this.isLoading = false;
},
methods: {
closeModal() {
modalController.dismiss({ dismissed: true });
},
getRejectReasonDescription(rejectReasonEnumId: string) {
return this.rejectReasons.find((reason: any) => reason.enumId === rejectReasonEnumId)?.description;
},
getTime(time: number) {
return DateTime.fromMillis(time).toLocaleString(DateTime.DATETIME_MED)
}
},
setup() {
const store = useStore();

return {
closeOutline,
store
};
},
});
</script>
7 changes: 6 additions & 1 deletion src/components/ProductListItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<p v-if="$filters.getFeature(getProduct(item.productId).featureHierarchy, '1/SIZE/')">{{ $t("Size") }}: {{ $filters.getFeature(getProduct(item.productId).featureHierarchy, '1/SIZE/') }}</p>
</ion-label>
<!-- Only show stock if its not a ship to store order -->
<ion-note v-if="!isShipToStoreOrder" slot="end">{{ getProductStock(item.productId) }} {{ $t("in stock") }}</ion-note>
<ion-note v-if="!isShipToStoreOrder" slot="end" :color="updateColor(getProductStock(item.productId))">{{ getProductStock(item.productId) }} {{ $t("in stock") }}</ion-note>
</ion-item>
</template>

Expand Down Expand Up @@ -46,6 +46,11 @@ export default {
getProduct: 'product/getProduct',
getProductStock: 'stock/getProductStock'
})
},
methods: {
updateColor(stock: number) {
return stock ? stock < 10 ? 'warning' : 'success' : 'danger';
}
}
}
</script>
Expand Down
133 changes: 133 additions & 0 deletions src/components/ReportAnIssueModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<template>
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-button @click="closeModal">
<ion-icon slot="icon-only" :icon="closeOutline" />
</ion-button>
</ion-buttons>
<ion-title>{{ $t("Report an issue") }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-item lines="none">
<p>{{ $t('On rejecting this item, will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.', { customerName: order?.customer?.name }) }}</p>
</ion-item>
<ion-list>
<ion-list-header>{{ $t("Select reason") }}</ion-list-header>
<ion-radio-group v-model="rejectReasonId">
<ion-item v-for="reason in unfillableReasons" :key="reason.id">
<ion-radio slot="start" :value="reason.id"/>
<ion-label>{{ $t(reason.label) }}</ion-label>
</ion-item>
</ion-radio-group>
</ion-list>
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button :disabled="!rejectReasonId" @click="confirmSave()">
<ion-icon :icon="saveOutline" />
</ion-fab-button>
</ion-fab>
</ion-content>
</template>

<script lang="ts">
import {
alertController,
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonTitle,
IonToolbar,
modalController,
IonRadio,
IonRadioGroup
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
alertController,
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonTitle,
IonToolbar,
modalController,
IonRadio,
IonRadioGroup
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonTitle,
IonToolbar,
IonRadio,
IonRadioGroup,
alertController,
modalController,

} from '@ionic/vue';
import { defineComponent } from 'vue';
import { closeOutline, saveOutline } from 'ionicons/icons';
import { mapGetters, useStore } from 'vuex'

export default defineComponent({
name: "ReportAnIssueModal",
components: {
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonListHeader,
IonTitle,
IonToolbar,
IonRadio,
IonRadioGroup
},
props: ['item'],
data () {
return {
unfillableReasons: JSON.parse(process.env.VUE_APP_UNFILLABLE_REASONS),
rejectReasonId: ''
}
},
computed: {
...mapGetters({
order: "order/getCurrent",
getProduct: 'product/getProduct',
})
},
methods: {
closeModal() {
modalController.dismiss({ dismissed: true });
},
async confirmSave () {
const alert = await alertController
.create({
header: this.$t('Reject Order Item'),
// TODO: Show primary identifier in message instead of productName when product identifier functionality implemented in the app.
message: this.$t('will be removed from your dashboard. This action cannot be undone.', { productName: this.getProduct(this.item.productId)?.productName, space: '<br /><br />' }),
buttons: [{
text: this.$t('Cancel'),
role: 'cancel'
}, {
text: this.$t('Reject'),
handler: () => {
this.store.dispatch('order/setUnfillableOrderOrItem', { orderId: this.order.orderId, part: { ...this.order.part, items: [{ ...this.item, reason: this.rejectReasonId }] } }).then((resp) => {
if (resp) {
// creating an current order copy by removing the selected item from the order.part
const order = { ...this.order, part: { ...this.order.part, items: this.order.part.items.filter((item: any) => !(item.orderItemSeqId === this.item.orderItemSeqId && item.productId === this.item.productId)) } };

// If this is the last item of the order then the order is fully rejected
if (this.order.part.items.length === 1) order.rejected = true;

this.store.dispatch('order/updateCurrent', { order });
}
this.closeModal();
})
},
}]
});
return alert.present();
}
},
setup() {
const store = useStore();

return {
closeOutline,
saveOutline,
store
};
}
});
</script>
14 changes: 13 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"App": "App",
"All items were canceled from the order": "All items were canceled from the order",
"Allow partial rejection": "Allow partial rejection",
"An email notification will be sent to that their order is ready for pickup. This order will also be moved to the packed orders tab.": "An email notification will be sent to { customerName } that their order is ready for pickup.{ space } This order will also be moved to the packed orders tab.",
"An email notification will be sent to that their order is ready for pickup.": "An email notification will be sent to { customerName } that their order is ready for pickup.",
"Are you sure you want to change the time zone to?": "Are you sure you want to change the time zone to?",
Expand Down Expand Up @@ -63,15 +64,19 @@
"No reason": "No reason",
"No picker assigned.": "No picker assigned.",
"No picker found": "No picker found",
"No records found.": "No records found.",
"No time zone found": "No time zone found",
"Open": "Open",
"OMS": "OMS",
"OMS instance": "OMS instance",
"On rejecting this item, will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.": "On rejecting this item, { customerName } will be sent an email with alternate fulfillment options and this order item will be removed from your dashboard.",
"Other stores inventory": "Other stores inventory",
"Order": "Order",
"Order delivered to": "Order delivered to { customerName }",
"Order details": "Order details",
"Order edit permissions": "Order edit permissions",
"Order is now ready to handover.": "Order is now ready to handover.",
"Order has been rejected.": "Order has been rejected.",
"Order marked as ready for pickup, an email notification has been sent to the customer": "Order marked as ready for pickup, an email notification has been sent to the customer",
"Order marked as ready for pickup but something went wrong while sending the email notification": "Order marked as ready for pickup but something went wrong while sending the email notification",
"Order not found": "Order not found",
Expand All @@ -80,10 +85,12 @@
"Order will be marked as completed. This action is irreversible.": "Order will be marked as completed. This action is irreversible.",
"Orders": "Orders",
"Orders Not Found": "Orders Not Found",
"Order item rejection history": "Order item rejection history",
"Other stores": "Other stores",
"Packed": "Packed",
"Packing Slip": "Packing Slip",
"Packing slips help customer reconcile their order against the delivered items.": "Packing slips help customer reconcile their order against the delivered items.",
"Partial Order rejection": "Partial Order rejection",
"Password": "Password",
"pending approval": "pending approval",
"Picked by": "Picked by { pickers }",
Expand All @@ -95,13 +102,17 @@
"Ready for pickup": "Ready for pickup",
"Ready to create an app?": "Ready to create an app?",
"Ready to ship": "Ready to ship",
"Reject": "Reject",
"Reject Order": "Reject Order",
"Reject Order Item": "Reject Order Item",
"Reason": "Reason",
"Report an issue": "Report an issue",
"Resend ready for pickup email": "Resend ready for pickup email",
"Search": "Search",
"Search Orders": "Search Orders",
"Search time zones": "Search time zones",
"Select facility": "Select facility",
"Select reason": "Select reason",
"Select time zone": "Select time zone",
"Select your preferred language.": "Select your preferred language.",
"Settings": "Settings",
Expand All @@ -124,6 +135,7 @@
"Something went wrong while login. Please contact administrator": "Something went wrong while login. Please contact administrator.",
"Sorry, your username or password is incorrect. Please try again.": "Sorry, your username or password is incorrect. Please try again.",
"Specify which facility you want to operate from. Order, inventory and other configuration data will be specific to the facility you select.": "Specify which facility you want to operate from. Order, inventory and other configuration data will be specific to the facility you select.",
"Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.": "Specify whether you reject partial BOPIS order when any order item’s inventory is insufficient at the store.",
"State": "State",
"Staff": "Staff",
"Street": "Street",
Expand All @@ -138,10 +150,10 @@
"Track Pickers": "Track Pickers",
"Track who picked orders by entering picker IDs when packing an order.": "Track who picked orders by entering picker IDs when packing an order.",
"Unfillable Items": "Unfillable Items",
"Update Order": "Update Order",
"Update time zone": "Update time zone",
"Username": "Username",
"Warehouse": "Warehouse",
"will be removed from your dashboard. This action cannot be undone.": "{ productName } will be removed from your dashboard.{ space } This action cannot be undone.",
"Worn Display": "Worn Display",
"This order will be removed from your dashboard. This action cannot be undone.": "This order will be removed from your dashboard.{ space } This action cannot be undone.",
"View shipping orders along with pickup orders.": "View shipping orders along with pickup orders.",
Expand Down
Loading