%PDF- %PDF-
Direktori : /home/forge/takeaseat.eco-n-tech.co.uk/pages/account/ |
Current File : //home/forge/takeaseat.eco-n-tech.co.uk/pages/account/availability.vue |
<template> <div class="page-wrapper"> <PageHeader classObject='bg-pink'> <img class="relative z-20 mb-8" src="~assets/images/logo-white-small.svg" alt="Takeaseat" /> <span class="font-bold uppercase text-xl">Account</span> <h1 class="relative z-20 text-5xl lg:text-7xl font-bold m-0">Availability</h1> <AccountProgressBar slug="availability" /> <div class="page-header-bottom"> <AccountNav /> </div> </PageHeader> <Block title="Availability" description="Select the times you have available for bookings. You can do this in one-hour slots (recommended) or select a block of time i.e. 9-12. If you get a non-Take a seat booking, you will have to delete the block and add the times you have available. Keep your availability up to date to ensure you receive bookings." width="max-w-6xl"> <v-calendar class="custom-calendar max-w-full" :masks="masks" :attributes="attributes" :min-date="new Date()" disable-page-swipe is-expanded> <template v-slot:day-content="{ day, attributes }"> <div class="h-full" v-if="new Date(day.id) >= new Date()"> <div class="flex flex-col h-full z-10 overflow-hidden"> <span class="day-label text-sm text-gray-900">{{ day.day }}</span> <div class="flex-grow overflow-y-auto overflow-x-auto"> <div v-for="(attr, key) in attributes" :key="key"> <div class="relative text-xs leading-tight rounded-sm p-1 mt-0 mb-1 cursor-pointer" :class="attr.customData.class"> <button class="absolute top-1 right-1" @click="removeAvailability(attr.customData.id)"> <svg class="w-4 h-4 text-white hover:text-red transition" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> </svg> <span class="sr-only">Delete</span> </button> <span class="block">{{ attr.customData.title }}</span> </div> </div> <button @click="openAvailabilityPopup(day)" class="p-1 w-full flex items-center text-xs text-black transition text-opacity-50 hover:text-opacity-100" type="button"> <span>Add Availability</span> <svg class="w-4 h-4" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6" /> </svg> </button> </div> </div> </div> </template> </v-calendar> <t-modal v-model="form.open" :header="'Add Availability for '+$moment(form.date).format('DD/MM/Y')"> <ValidationObserver ref="availabilityForm"> <t-input-group label="Available From"> <ValidationProvider rules="required" name="available_from" v-slot="{ errors }"> <input class="form-control" v-model="form.available_from" type="time" id="available_form" name="available_form" value="09:00" /> <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span> </ValidationProvider> </t-input-group> <t-input-group label="Available To"> <ValidationProvider rules="required|hourAfter:@available_from" name="available_to" v-slot="{ errors }"> <input class="form-control" v-model="form.available_to" type="time" id="available_to" name="available_to" value="17:00" /> <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span> </ValidationProvider> </t-input-group> <t-input-group label="Session Types"> <ValidationProvider rules="required" name="session_types" v-slot="{ errors }"> <t-checkbox-group v-model="form.session_types" name="session_types" valueAttribute="id" textAttribute="name" :options="session_types"></t-checkbox-group> <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span> </ValidationProvider> </t-input-group> <t-input-group v-if="form.session_types.includes(3)" label="In Person Address"> <ValidationProvider rules="required" name="address" v-slot="{ errors }"> <t-select v-model="form.address_id" valueAttribute="id" textAttribute="formatted" :options="addresses" placeholder="Select address..." /> <span class="field-invalid" v-if="errors[0]">{{ errors[0] }}</span> </ValidationProvider> </t-input-group> </ValidationObserver> <template v-slot:footer> <div class="flex justify-between"> <button class="btn btn-small btn-primary" @click="form.open = false" type="button">Cancel</button> <button @click="addAvailability" class="btn btn-small btn-primary" type="button"> <span v-if="working == false">Add Availability</span> <span class="flex items-center justify-center" v-else> <svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"> <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle> <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path> </svg> <span>Adding</span> </span> </button> </div> </template> </t-modal> </Block> </div> </template> <script> export default { middleware: ['auth', 'therapist'], head () { return { titleTemplate: 'Availability | %s', } }, data() { return { timer: null, working: false, masks: { weekdays: 'WWW', }, attributes: [], addresses: [], session_types: [], slot_increments: [], form: { open: false, date: null, available_from: '09:00', available_to: '10:00', address_id: null, session_types: [] } }; }, async asyncData ({ app }) { const data = await app.$axios.$get('/account/availability') return { attributes: data.availability, session_types: data.session_types, addresses: data.addresses } }, methods: { async addAvailability() { this.$refs.availabilityForm.validate().then(success => { if (!success) { return; } this.saveAvailability(); }) }, openAvailabilityPopup(day) { this.form.open = true; this.form.date = day.id; }, async removeAvailability(id) { await this.$axios.$post('/account/availability/delete/'+id).then((response) => { this.$axios.$get('/account/availability').then((response) => { this.attributes = response.availability; }); }).catch((error) => { this.$toast.error(error).goAway(1000); }) }, async saveAvailability() { this.working = true; await this.$axios.$post('/account/availability/create', this.form).then((response) => { this.working = false; this.form.open = false this.$axios.$get('/account/availability').then((response) => { this.attributes = response.availability }); }).catch((error) => { this.working = false; this.$toast.error(error.response.data).goAway(1000); this.$refs.availabilityForm.setErrors(error.response.data.errors); }) }, }, watch: { 'form.available_from': function (val) { let from = val.replace(":00", ""); let to = parseInt(from) + 1; let formattedFrom = from+':00'; let formattedTo = to < 10 ? '0'+to+':00' : to+':00'; if(val.includes(":00") && parseInt(from) > 0) { this.form.available_from = formattedFrom; this.form.available_to = formattedTo; } } } } </script> <style lang="postcss" scoped> ::-webkit-scrollbar { width: 0px; } ::-webkit-scrollbar-track { display: none; } /deep/ .custom-calendar.vc-container { --day-border: 1px solid #ccc; --day-border-highlight: 1px solid #ccc; --day-width: 90px; --day-height: 150px; --weekday-bg: #f8fafc; --weekday-border: 1px solid #eaeaea; border-radius: 15px; overflow: hidden; width: 100%; & .vc-header { background-color: #fff; padding: 10px 0; } & .vc-weeks { padding: 0; overflow-x: auto; } & .vc-weekday { background-color: var(--weekday-bg); border-bottom: var(--weekday-border); border-top: var(--weekday-border); padding: 5px 0; } & .vc-day { padding: 0 5px 3px 5px; text-align: left; height: var(--day-height); min-width: var(--day-width); background-color: white; &.weekday-1, &.weekday-7 { background-color: #eff8ff; } &:not(.on-bottom) { border-bottom: var(--day-border); &.weekday-1 { border-bottom: var(--day-border-highlight); } } &:not(.on-right) { border-right: var(--day-border); } } & .vc-day-dots { margin-bottom: 5px; } } </style>