Skip to content

Commit

Permalink
Merge pull request #434 from amansinghbais/423-rejection-reason-imple…
Browse files Browse the repository at this point in the history
…mentation

Implemented: added functionality to the rejection reasons (#423)
  • Loading branch information
ymaheshwari1 authored Mar 15, 2024
2 parents d12d4f3 + 0a67629 commit e19f42f
Show file tree
Hide file tree
Showing 17 changed files with 602 additions and 81 deletions.
1 change: 1 addition & 0 deletions src/authorization/Rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export default {
"APP_IN_PROGRESS_ORDERS_VIEW": "",
"APP_COMPLETED_ORDERS_VIEW": "",
"APP_ORDER_DETAIL_VIEW": "",
"APP_REJECTION_REASONS_VIEW": "SFA_ADMIN",
"APP_EXIM_VIEW": "",
"APP_UPLOAD_IMPORT_ORDERS_VIEW": "",
"APP_DOWNLOAD_PACKED_ORDERS_VIEW": "",
Expand Down
106 changes: 98 additions & 8 deletions src/components/CreateRejectionReasonModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,37 @@
<ion-list>
<ion-item>
<ion-label>{{ translate("Name") }}</ion-label>
<ion-input />
<ion-input @ionBlur="setEnumId($event)" v-model="formData.enumName" />
</ion-item>
<ion-item>
<ion-item ref="enumId">
<ion-label>{{ translate("ID") }}</ion-label>
<ion-input />
<ion-input v-model="formData.enumId" @ionChange="validateEnumId" @ionBlur="markEnumIdTouched" />
<ion-note slot="error">
{{ translate("ID cannot be more than 20 characters.") }}
</ion-note>
</ion-item>
<ion-item>
<ion-label>{{ translate("Description") }}</ion-label>
<ion-input />
<ion-input v-model="formData.description" />
</ion-item>
</ion-list>

<ion-list>
<ion-item>
<ion-label>{{ translate("Variance type") }}</ion-label>
<ion-select interface="popover" value="">
<ion-select-option value="">{{ "No variance" }}</ion-select-option>
<ion-select interface="popover" v-model="formData.enumTypeId">
<ion-select-option v-for="type in rejectReasonEnumTypes" :key="type.enumTypeId" :value="type.enumTypeId">{{ type.enumTypeId }}</ion-select-option>
</ion-select>
</ion-item>
<ion-item lines="none">
<ion-label>
<p>{{ "< Variance type desc >" }}</p>
<p>{{ getDescription() }}</p>
</ion-label>
</ion-item>
</ion-list>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button>
<ion-fab-button @click="createReason()">
<ion-icon :icon="checkmarkDoneOutline" />
</ion-fab-button>
</ion-fab>
Expand All @@ -63,6 +66,7 @@ import {
IonItem,
IonLabel,
IonList,
IonNote,
IonSelect,
IonSelectOption,
IonTitle,
Expand All @@ -72,6 +76,11 @@ import {
import { defineComponent } from "vue";
import { checkmarkDoneOutline, closeOutline } from "ionicons/icons";
import { translate } from '@hotwax/dxp-components'
import { generateInternalId, showToast } from "@/utils";
import { mapGetters, useStore } from "vuex";
import { UtilService } from "@/services/UtilService";
import { hasError } from "@/adapter";
import logger from "@/logger";
export default defineComponent({
name: "CreateRejectionReasonModal",
Expand All @@ -87,20 +96,101 @@ export default defineComponent({
IonItem,
IonLabel,
IonList,
IonNote,
IonSelect,
IonSelectOption,
IonTitle,
IonToolbar
},
data() {
return {
formData: {
description: "",
enumId: "",
enumName: "",
enumTypeId: ""
} as any
}
},
computed: {
...mapGetters({
rejectReasons: 'util/getRejectReasons',
rejectReasonEnumTypes: 'util/getRejectReasonEnumTypes',
})
},
methods: {
closeModal() {
modalController.dismiss()
},
setEnumId(event: any) {
this.formData.enumId = generateInternalId(event.target.value)
},
async createReason() {
if(!this.formData.description?.trim()) {
showToast(translate("Rejection reason description is required."))
return
}
if(this.formData.enumId.length > 20) {
showToast(translate("ID cannot be more than 20 characters."))
return
}
if(!this.formData.enumTypeId) {
showToast(translate("Variance type is required."))
return
}
// In case the user does not lose focus from the name input
// and click on create the button, we need to set the id manually
if (!this.formData.enumId) {
this.formData.enumId = generateInternalId(this.formData.enumName)
}
const sequenceNum = this.rejectReasons[this.rejectReasons.length - 1].sequenceNum
this.formData['sequenceNum'] = sequenceNum ? sequenceNum + 5 : 5;
try {
const resp = await UtilService.createEnumeration(this.formData)
if(!hasError(resp)) {
showToast(translate("Rejection reason created successfully."))
this.rejectReasons.push(this.formData)
await this.store.dispatch('util/updateRejectReasons', this.rejectReasons)
modalController.dismiss({ isUpdated: true })
} else {
throw resp.data
}
} catch(err) {
showToast(translate("Failed to create rejection reason."))
logger.error(err)
}
},
validateEnumId(event: any) {
const value = event.target.value;
(this as any).$refs.enumId.$el.classList.remove('ion-valid');
(this as any).$refs.enumId.$el.classList.remove('ion-invalid');
if (value === '') return;
this.formData.enumId.length <= 20
? (this as any).$refs.enumId.$el.classList.add('ion-valid')
: (this as any).$refs.enumId.$el.classList.add('ion-invalid');
},
markEnumIdTouched() {
(this as any).$refs.enumId.$el.classList.add('ion-touched');
},
getDescription() {
return this.rejectReasonEnumTypes.find((type: any) => type.enumTypeId === this.formData.enumTypeId)?.description
}
},
setup() {
const store = useStore();
return {
checkmarkDoneOutline,
closeOutline,
store,
translate
};
},
Expand Down
130 changes: 130 additions & 0 deletions src/components/EditRejectionReasonModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<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>{{ translate("Edit name and description") }}</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<form @keyup.enter="updateRejectionReason()">
<ion-item>
<ion-label>{{ translate("Name") }}</ion-label>
<ion-input v-model="rejectionReason.enumName" />
</ion-item>
<ion-item>
<ion-label>{{ translate("Description") }}</ion-label>
<ion-textarea v-model="rejectionReason.description" />
</ion-item>
</form>
</ion-content>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button @click="updateRejectionReason()" :disabled="!isReasonUpdated()">
<ion-icon :icon="saveOutline" />
</ion-fab-button>
</ion-fab>
</template>

<script lang="ts">
import {
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonTextarea,
IonTitle,
IonToolbar,
modalController
} from "@ionic/vue";
import { defineComponent } from "vue";
import { mapGetters, useStore } from "vuex";
import { closeOutline, saveOutline } from "ionicons/icons";
import { translate } from '@hotwax/dxp-components'
import logger from "@/logger";
import { UtilService } from "@/services/UtilService";
import { hasError } from "@/adapter";
import { showToast } from "@/utils";
export default defineComponent({
name: "EditRejectionReasonModal",
components: {
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonTextarea,
IonTitle,
IonToolbar
},
computed: {
...mapGetters({
rejectReasons: 'util/getRejectReasons',
})
},
data() {
return {
rejectionReason: {} as any,
}
},
props: ['reason'],
beforeMount() {
this.rejectionReason = JSON.parse(JSON.stringify(this.reason))
},
methods: {
closeModal() {
modalController.dismiss()
},
isReasonUpdated() {
return JSON.stringify(this.reason) !== JSON.stringify(this.rejectionReason)
},
async updateRejectionReason() {
try {
const resp = await UtilService.updateEnumeration(this.rejectionReason)
if(!hasError(resp)) {
showToast(translate("Rejection reason updated successfully."))
const rejectReason = this.rejectReasons.find((reason: any) => reason.enumId === this.rejectionReason.enumId)
if(rejectReason) {
rejectReason.enumName = this.rejectionReason.enumName
rejectReason.description = this.rejectionReason.description
}
await this.store.dispatch('util/updateRejectReasons', this.rejectReasons)
modalController.dismiss()
} else {
throw resp.data;
}
} catch(err) {
logger.error(err)
showToast(translate("Failed to update rejection reason."))
}
}
},
setup() {
const store = useStore()
return {
closeOutline,
saveOutline,
store,
translate
};
},
});
</script>
58 changes: 55 additions & 3 deletions src/components/RejectReasonActionsPopver.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
<ion-content>
<ion-list>
<ion-list-header>
{{ "<enumName>" }}
{{ reason.description }}
</ion-list-header>
<ion-item button>
<ion-item button @click="openEditRejectionReasonModal()">
{{ translate("Edit name and description") }}
</ion-item>
<ion-item button lines="none">
<ion-item button lines="none" @click="removeRejectionReason()">
{{ translate("Remove reason") }}
</ion-item>
</ion-list>
Expand All @@ -20,9 +20,18 @@ import {
IonItem,
IonList,
IonListHeader,
modalController,
popoverController
} from "@ionic/vue";
import { defineComponent } from "vue";
import { translate } from '@hotwax/dxp-components'
import EditRejectionReasonModal from "@/components/EditRejectionReasonModal.vue";
import { UtilService } from "@/services/UtilService";
import { hasError } from "@/adapter";
import { showToast } from "@/utils";
import logger from "@/logger";
import { mapGetters, useStore } from "vuex";
export default defineComponent({
name: "RejectReasonActionsPopover",
components: {
Expand All @@ -31,8 +40,51 @@ export default defineComponent({
IonList,
IonListHeader
},
props: ["reason"],
computed: {
...mapGetters({
rejectReasons: 'util/getRejectReasons',
rejectReasonEnumTypes: 'util/getRejectReasonEnumTypes',
})
},
methods: {
async openEditRejectionReasonModal() {
const editRejectionReasonModal = await modalController.create({
component: EditRejectionReasonModal,
componentProps: { reason: this.reason }
})
editRejectionReasonModal.onDidDismiss().then(() => {
popoverController.dismiss()
})
editRejectionReasonModal.present()
},
async removeRejectionReason() {
try {
const resp = await UtilService.deleteEnumeration({
enumId: this.reason.enumId
})
if(!hasError(resp)) {
showToast(translate("Rejection reason removed successfully."))
const updatedRejectReasons = this.rejectReasons.filter((rejectReason: any) => rejectReason.enumId !== this.reason.enumId)
await this.store.dispatch('util/updateRejectReasons', updatedRejectReasons)
} else {
throw resp.data
}
} catch(err) {
showToast(translate("Failed to remove rejection reason."))
logger.error(err)
}
popoverController.dismiss()
}
},
setup() {
const store = useStore()
return {
store,
translate
}
},
Expand Down
Loading

0 comments on commit e19f42f

Please sign in to comment.