-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #342 from bcgov/feature/reservationForm
Feature/reservation form
- Loading branch information
Showing
9 changed files
with
344 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
171 changes: 171 additions & 0 deletions
171
services/tenant-ui/frontend/src/components/reservation/Reserve.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
<template> | ||
<form @submit.prevent="handleSubmit(!v$.$invalid)"> | ||
<!-- Email --> | ||
<div class="field mt-5 w-full"> | ||
<label | ||
for="email" | ||
:class="{ 'p-error': v$.contact_email.$invalid && submitted }" | ||
>Email Address | ||
</label> | ||
<InputText | ||
id="email" | ||
v-model="v$.contact_email.$model" | ||
type="text" | ||
option-label="label" | ||
autocomplete="email" | ||
name="email" | ||
autofocus | ||
class="w-full" | ||
/> | ||
<span v-if="v$.contact_email.$error && submitted"> | ||
<span v-for="(error, index) of v$.contact_email.$errors" :key="index"> | ||
<small class="p-error block">{{ error.$message }}</small> | ||
</span> | ||
</span> | ||
<small | ||
v-else-if="v$.contact_email.$invalid && submitted" | ||
class="p-error" | ||
>{{ v$.contact_email.required.$message }}</small | ||
> | ||
</div> | ||
|
||
<!-- FullName --> | ||
<div class="field mt-5 w-full"> | ||
<label | ||
for="full-name" | ||
:class="{ 'p-error': v$.contact_name.$invalid && submitted }" | ||
>Full Name | ||
</label> | ||
<InputText | ||
id="full-name" | ||
v-model="v$.contact_name.$model" | ||
autocomplete="name" | ||
name="fullName" | ||
class="w-full" | ||
/> | ||
<small v-if="v$.contact_name.$invalid && submitted" class="p-error">{{ | ||
v$.contact_name.required.$message | ||
}}</small> | ||
</div> | ||
|
||
<!-- Phone --> | ||
<div class="field mt-5 w-full"> | ||
<label | ||
for="phone" | ||
:class="{ 'p-error': v$.contact_phone.$invalid && submitted }" | ||
>Phone / Mobile | ||
</label> | ||
<InputText | ||
id="phone" | ||
v-model="v$.contact_phone.$model" | ||
autocomplete="phone" | ||
name="phone" | ||
class="w-full" | ||
/> | ||
<small v-if="v$.contact_phone.$invalid && submitted" class="p-error">{{ | ||
v$.contact_phone.required.$message | ||
}}</small> | ||
</div> | ||
|
||
<!-- Tenant Name --> | ||
<div class="field mt-5 w-full"> | ||
<label | ||
for="tenant-name" | ||
:class="{ 'p-error': v$.tenant_name.$invalid && submitted }" | ||
>Tenant Name | ||
</label> | ||
<InputText | ||
id="tenant-name" | ||
v-model="v$.tenant_name.$model" | ||
name="tenant-name" | ||
class="w-full" | ||
/> | ||
<small v-if="v$.tenant_name.$invalid && submitted" class="p-error">{{ | ||
v$.tenant_name.required.$message | ||
}}</small> | ||
</div> | ||
|
||
<!-- Tenant Reason --> | ||
<div class="field mt-5 w-full"> | ||
<label | ||
for="tenant-reason" | ||
:class="{ 'p-error': v$.tenant_reason.$invalid && submitted }" | ||
>Tenant Reason | ||
</label> | ||
<Textarea | ||
id="tenant-reason" | ||
v-model="v$.tenant_reason.$model" | ||
name="tenant-reason" | ||
class="w-full" | ||
:auto-resize="true" | ||
rows="2" | ||
/> | ||
<small v-if="v$.tenant_reason.$invalid && submitted" class="p-error">{{ | ||
v$.tenant_reason.required.$message | ||
}}</small> | ||
</div> | ||
|
||
<Button | ||
type="submit" | ||
class="w-full mt-5" | ||
label="Request" | ||
:disabled="!!loading" | ||
:loading="!!loading" | ||
/> | ||
</form> | ||
</template> | ||
|
||
<script setup lang="ts"> | ||
//Vue | ||
import { ref, reactive } from 'vue'; | ||
// PrimeVue/Validation/etc | ||
import Button from 'primevue/button'; | ||
import InputText from 'primevue/inputtext'; | ||
import Textarea from 'primevue/textarea'; | ||
import { useToast } from 'vue-toastification'; | ||
import { email, required } from '@vuelidate/validators'; | ||
import { useVuelidate } from '@vuelidate/core'; | ||
// State | ||
import { useReservationStore } from '@/store'; | ||
import { storeToRefs } from 'pinia'; | ||
const toast = useToast(); | ||
// Login Form and validation | ||
const formFields = reactive({ | ||
contact_email: '', | ||
contact_name: '', | ||
contact_phone: '', | ||
tenant_name: '', | ||
tenant_reason: '', | ||
}); | ||
const rules = { | ||
contact_email: { required, email }, | ||
contact_name: { required }, | ||
contact_phone: { required }, | ||
tenant_name: { required }, | ||
tenant_reason: { required }, | ||
}; | ||
const v$ = useVuelidate(rules, formFields); | ||
// State setup | ||
const reservationStore = useReservationStore(); | ||
const { loading, reservation } = storeToRefs(useReservationStore()); | ||
// Form submission | ||
const submitted = ref(false); | ||
const handleSubmit = async (isFormValid: boolean) => { | ||
submitted.value = true; | ||
if (!isFormValid) { | ||
return; | ||
} | ||
try { | ||
await reservationStore.makeReservation(formFields); | ||
toast.success(`Your request was received.`); | ||
} catch (err) { | ||
console.error(err); | ||
toast.error(`Failure making request: ${err}`); | ||
} | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { API_PATH } from '@/helpers/constants'; | ||
import axios from 'axios'; | ||
import { defineStore, storeToRefs } from 'pinia'; | ||
import { ref } from 'vue'; | ||
import { useConfigStore } from './configStore'; | ||
|
||
export const useReservationStore = defineStore('reservation', () => { | ||
const { config } = storeToRefs(useConfigStore()); | ||
// A raw api call without using the interceptors from the acapyApiStore | ||
// Needed for the open call to reservation at this point | ||
const api = axios.create({ | ||
baseURL: config.value.frontend.tenantProxyPath, | ||
}); | ||
|
||
// state | ||
const loading: any = ref(false); | ||
const error: any = ref(null); | ||
const reservation: any = ref(null); | ||
|
||
// actions | ||
async function makeReservation(payload: any = {}) { | ||
console.log('> reservationStore.makeReservation'); | ||
error.value = null; | ||
loading.value = true; | ||
console.log(payload); | ||
await api | ||
.post(API_PATH.MULTITENANCY_RESERVATION, payload) | ||
.then((res) => { | ||
console.log(res); | ||
reservation.value = res.data.item; | ||
}) | ||
.catch((err) => { | ||
error.value = err; | ||
console.log(error.value); | ||
}) | ||
.finally(() => { | ||
loading.value = false; | ||
}); | ||
console.log('< reservationStore.makeReservation'); | ||
|
||
if (error.value != null) { | ||
// throw error so $onAction.onError listeners can add their own handler | ||
throw error.value; | ||
} | ||
// return data so $onAction.after listeners can add their own handler | ||
return reservation.value; | ||
} | ||
|
||
return { | ||
reservation, | ||
loading, | ||
error, | ||
makeReservation, | ||
}; | ||
}); | ||
|
||
export default { | ||
useReservationStore, | ||
}; |
Oops, something went wrong.