Skip to content

Commit

Permalink
Merge pull request #66 from k2maan/virtual-facility
Browse files Browse the repository at this point in the history
Implemented: flow to create and perform actions on virtual facilities
  • Loading branch information
ravilodhi authored Dec 6, 2023
2 parents 6bd7749 + b436c28 commit 7caa417
Show file tree
Hide file tree
Showing 16 changed files with 767 additions and 73 deletions.
111 changes: 111 additions & 0 deletions src/components/ArchivedFacilityModal.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>{{ translate("Archived parking") }}</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-list v-if="archivedFacilities.length">
<ion-item v-for="(archivedFacility, index) in archivedFacilities" :key="index">
<ion-label>
{{ archivedFacility.facilityName }}
<p>{{ archivedFacility.facilityId }}</p>
</ion-label>
<ion-button fill="clear" color="medium" @click="unarchiveFacility(archivedFacility)">
<ion-icon slot="icon-only" :icon="gitPullRequestOutline" />
</ion-button>
</ion-item>
</ion-list>
<div v-else class='empty-state'>
{{ translate('No archived parkings to show.') }}
</div>
</ion-content>
</template>

<script lang="ts">
import {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
modalController,
} from "@ionic/vue";
import { defineComponent } from "vue";
import { closeOutline, gitPullRequestOutline } from 'ionicons/icons'
import { translate } from '@hotwax/dxp-components'
import { showToast } from '@/utils';
import logger from "@/logger";
import { FacilityService } from "@/services/FacilityService";
import { hasError } from "@/adapter";
import { mapGetters, useStore } from "vuex";
import { DateTime } from "luxon";
export default defineComponent({
name: "ArchivedFacilityModal",
components: {
IonButton,
IonButtons,
IonContent,
IonHeader,
IonIcon,
IonItem,
IonLabel,
IonList,
IonTitle,
IonToolbar,
},
computed: {
...mapGetters({
archivedFacilities: 'facility/getArchivedFacilities',
})
},
methods: {
closeModal() {
modalController.dismiss({ dismissed: true});
},
async unarchiveFacility(archivedFacility: any) {
try {
const resp = await FacilityService.updateFacilityToGroup({
facilityId: archivedFacility.facilityId,
facilityGroupId: "ARCHIVE",
fromDate: archivedFacility.fromDate,
thruDate: DateTime.now().toMillis()
})
if (!hasError(resp)) {
showToast(translate("Parking unarchived successfully."))
const archivedFacilities = JSON.parse(JSON.stringify(this.archivedFacilities)).filter((facility: any) => facility.facilityId !== archivedFacility.facilityId)
this.store.dispatch('facility/updateArchivedFacilities', archivedFacilities)
await this.store.dispatch('facility/fetchVirtualFacility', { facilityId: archivedFacility.facilityId })
} else {
throw resp.data
}
} catch (err) {
showToast(translate("Failed to unarchive parking."))
logger.error(err)
}
}
},
setup() {
const store = useStore()
return {
closeOutline,
gitPullRequestOutline,
store,
translate
}
},
});
</script>
195 changes: 195 additions & 0 deletions src/components/CreateVirtualFacilityModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
<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("New parking") }}</ion-title>
</ion-toolbar>
</ion-header>

<ion-content>
<form @keyup.enter="createVirtualFacility">
<ion-list>
<ion-item>
<ion-label position="floating">
{{ translate("Name") }} <ion-text color="danger">*</ion-text>
</ion-label>
<ion-input @ionBlur="setFacilityId($event)" v-model="formData.facilityName"/>
</ion-item>
<ion-item ref="facilityId">
<ion-label position="floating">
{{ translate("Internal ID") }}
</ion-label>
<ion-input v-model="formData.facilityId" @ionChange="validateFacilityId" @ionBlur="markFacilityIdTouched" />
<ion-note slot="error">
{{ translate('Internal ID cannot be more than 20 characters.') }}
</ion-note>
</ion-item>
<ion-item>
<ion-label position="floating">
{{ translate("Description") }}
</ion-label>
<ion-input v-model="formData.description"/>
</ion-item>
</ion-list>

<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button @click="createVirtualFacility" @keyup.enter.stop>
<ion-icon :icon="addOutline" />
</ion-fab-button>
</ion-fab>
</form>
</ion-content>
</template>

<script lang="ts">
import {
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonList,
IonNote,
IonText,
IonTitle,
IonToolbar,
modalController
} from "@ionic/vue";
import { defineComponent } from "vue";
import { addOutline, closeOutline } from "ionicons/icons";
import { translate } from '@hotwax/dxp-components'
import { FacilityService } from "@/services/FacilityService";
import { mapGetters, useStore } from 'vuex'
import { hasError } from "@/adapter";
import { showToast } from "@/utils";
import logger from "@/logger";
export default defineComponent({
name: "CreateVirtualFacility",
components: {
IonButton,
IonButtons,
IonContent,
IonFab,
IonFabButton,
IonHeader,
IonIcon,
IonInput,
IonItem,
IonLabel,
IonList,
IonNote,
IonText,
IonTitle,
IonToolbar
},
computed: {
...mapGetters({
virtualFacilities: 'facility/getVirtualFacilities',
})
},
data() {
return {
formData: {
facilityName: '',
facilityId: '',
description: '',
},
}
},
ionViewWillEnter() {
this.clearFormData()
},
methods: {
clearFormData() {
this.formData = {
facilityName: '',
facilityId: '',
description: '',
}
},
setFacilityId(event: any) {
this.formData.facilityId = event.target.value.trim().toUpperCase().split(' ').join('_');
},
closeModal() {
modalController.dismiss();
},
async createVirtualFacility() {
if (!this.formData.facilityName?.trim()) {
showToast(translate('Please fill all the required fields'))
return;
}
if (this.formData.facilityId.length > 20) {
showToast(translate('Internal ID cannot be more than 20 characters.'))
return
}
// In case the user does not lose focus from the facility name input
// and click on create the button, we need to set the internal id manually
if (!this.formData.facilityId) {
this.formData.facilityId = this.formData.facilityName.trimEnd().trimStart().toUpperCase().split(' ').join('_');
}
try {
const payload = {
...this.formData,
facilityTypeId: 'VIRTUAL_FACILITY',
ownerPartyId: "COMPANY"
}
const resp = await FacilityService.createVirtualFacility(payload);
if (!hasError(resp)) {
showToast(translate("New parking created successfully."))
const createdFacility = {
...this.formData,
facilityTypeId: 'VIRTUAL_FACILITY',
orderCount: 0
}
const updatedVirtualFacilities = [...this.virtualFacilities, createdFacility]
this.store.dispatch('facility/updateVirtualFacilities', updatedVirtualFacilities)
} else {
throw resp.data;
}
} catch (error) {
logger.error(error)
showToast(translate('Failed to create parking.'))
}
modalController.dismiss()
},
validateFacilityId(event: any) {
const value = event.target.value;
(this as any).$refs.facilityId.$el.classList.remove('ion-valid');
(this as any).$refs.facilityId.$el.classList.remove('ion-invalid');
if (value === '') return;
this.formData.facilityId.length <= 20
? (this as any).$refs.facilityId.$el.classList.add('ion-valid')
: (this as any).$refs.facilityId.$el.classList.add('ion-invalid');
},
markFacilityIdTouched() {
(this as any).$refs.facilityId.$el.classList.add('ion-touched');
},
},
setup() {
const store = useStore();
return {
addOutline,
closeOutline,
store,
translate
};
},
});
</script>
3 changes: 2 additions & 1 deletion src/components/ProductStorePopover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@ export default defineComponent({
facilityGroupId: productStoreId
},
entityName: 'FacilityGroup',
viewSize: 100
fieldList: ['facilityGroupId', 'facilityId'],
viewSize: 1
})
if(!hasError(resp)) {
Expand Down
Loading

0 comments on commit 7caa417

Please sign in to comment.