
/* /room/static/src/room_booking/room_booking_form/room_booking_form.js */
odoo.define('@room/room_booking/room_booking_form/room_booking_form',['@web/core/utils/scrolling','@odoo/owl'],function(require){'use strict';let __exports={};const{scrollTo}=require("@web/core/utils/scrolling");const{Component,onWillUpdateProps,useEffect,useRef,useState}=require("@odoo/owl");const RoomBookingForm=__exports.RoomBookingForm=class RoomBookingForm extends Component{static template="room.RoomBookingForm";static props={createBooking:Function,bookings:Object,bookingToEdit:{type:Object,optional:true},cancel:Function,editBooking:Function,bookingName:{type:String,optional:true},};setup(){this.root=useRef("root");this.state=useState({selectedDay:this.props.bookingToEdit?luxon.DateTime.max(this.props.bookingToEdit.interval.start.startOf("day"),this.today,):this.today,bookingStart:this.props.bookingToEdit?luxon.DateTime.max(this.props.bookingToEdit.interval.start,luxon.DateTime.now()):undefined,bookingEnd:this.props.bookingToEdit?.interval.end,bookingName:this.props.bookingToEdit?.name||this.props.bookingName,});onWillUpdateProps((nextProps)=>{if(nextProps.bookingToEdit!==this.props.bookingToEdit){this.state.selectedDay=luxon.DateTime.max(nextProps.bookingToEdit.interval.start.startOf("day"),this.today,);this.state.bookingStart=luxon.DateTime.max(nextProps.bookingToEdit.interval.start,luxon.DateTime.now(),);this.state.bookingEnd=nextProps.bookingToEdit.interval.end;this.state.bookingName=nextProps.bookingToEdit.name;}});useEffect(()=>{const slot=this.root.el.querySelector(`#slot${
                        this.state.bookingStart?.startOf("day").equals(this.state.selectedDay)
                            ? this.state.bookingStart.toFormat("HHmm")
                            : "0800"
                    }`,);if(slot){scrollTo(slot,{isAnchor:true});}},()=>[this.state.selectedDay],);}
get dayFormat(){return{weekday:"short",day:"numeric"};}
get durationFormat(){return"h:mm";}
get monthFormat(){return{year:"numeric",month:"long"};}
get timeFormat(){return luxon.DateTime.TIME_SIMPLE;}
get bookingsByDate(){return this.props.bookings.reduce((bookingsByDate,booking)=>{if(this.props.bookingToEdit?.id===booking.id){return bookingsByDate;}
const intervals=[];let{start,end}=booking.interval;if(start.startOf("day").equals(end.startOf("day"))){intervals.push(booking.interval);}else{while(start.startOf("day")<end.startOf("day")){const nextDay=start.plus({days:1}).startOf("day");intervals.push(luxon.Interval.fromDateTimes(start,nextDay));start=nextDay;}
intervals.push(luxon.Interval.fromDateTimes(start,end));}
for(const interval of intervals){const date=interval.start.toISODate();if(!(date in bookingsByDate)){bookingsByDate[date]=[];}
bookingsByDate[date].push(interval);}
return bookingsByDate;},{});}
get formattedMonth(){return this.weekInterval.toLocaleString(this.monthFormat);}
get slots(){const intervals=[];const isToday=this.state.selectedDay.equals(this.today);if(isToday){let firstSlotTime=luxon.DateTime.now();if(this.state.bookingStart&&this.state.bookingStart<firstSlotTime){firstSlotTime=this.state.bookingStart;}
intervals.push(luxon.Interval.fromDateTimes(firstSlotTime,firstSlotTime.plus({minutes:30-(firstSlotTime.minute%30)}).startOf("minute"),),);}
const remainingInterval=luxon.Interval.fromDateTimes(intervals[0]?.end||this.state.selectedDay,this.state.selectedDay.plus({day:1}),);intervals.push(...remainingInterval.splitBy({minutes:30}));const bookings=this.bookingsByDate[this.state.selectedDay.toISODate()]||[];let bookingIdx=0;let isBooked=false;let isInSelectedInterval=false;let canBeEndDate=false;if(this.props.bookingToEdit&&this.props.bookingToEdit.interval.start<this.state.selectedDay&&this.props.bookingToEdit.interval.end>this.state.selectedDay){isInSelectedInterval=true;canBeEndDate=true;}
const slots=[];for(const interval of intervals){const slot={start:interval.start,isInSelectedInterval,canBeEndDate,};if(this.state.bookingEnd&&interval.contains(this.state.bookingEnd)){isInSelectedInterval=false;}else if(this.state.bookingStart&&interval.contains(this.state.bookingStart)){slot.isInSelectedInterval=true;canBeEndDate=true;isInSelectedInterval=Boolean(this.state.bookingEnd);}else if(canBeEndDate&&!isInSelectedInterval){slot.description=interval.start.diff(this.state.bookingStart).toFormat(this.durationFormat);}
if(bookings[bookingIdx]?.overlaps(interval)&&!isBooked){isBooked=true;canBeEndDate=false;}
slot.isBooked=isBooked;if(isBooked&&interval.end>=bookings[bookingIdx].end){isBooked=false;bookingIdx++;}
slots.push(slot);}
if(this.state.bookingStart&&canBeEndDate){const midnight=this.state.selectedDay.plus({day:1});const isEnd=this.state.bookingEnd?.equals(midnight);slots.push({start:midnight,canBeEndDate,isInSelectedInterval:isEnd,description:isEnd?false:midnight.diff(this.state.bookingStart).toFormat(this.durationFormat),});}
return slots;}
get today(){return luxon.DateTime.now().startOf("day");}
get weekInterval(){return luxon.Interval.fromDateTimes(this.state.selectedDay.startOf("week"),this.state.selectedDay.endOf("week"),);}
get weekIntervalDays(){return this.weekInterval.splitBy({day:1});}
confirm(){if(this.props.bookingToEdit){this.props.editBooking(this.props.bookingToEdit.id,this.state.bookingName,this.props.bookingToEdit.interval.start<luxon.DateTime.now()&&this.state.bookingStart<luxon.DateTime.now()?this.props.bookingToEdit.interval.start:this.state.bookingStart,this.state.bookingEnd,);}else{this.props.createBooking(this.state.bookingName,this.state.bookingStart,this.state.bookingEnd,);}}
onNextWeekClick(){this.state.selectedDay=this.state.selectedDay.plus({week:1});}
onPreviousWeekClick(){const day=this.state.selectedDay.minus({week:1});this.state.selectedDay=day<this.today?this.today:day;}
onSlotClick(slot){if(!this.state.bookingStart){if(!slot.isBooked){this.state.bookingStart=slot.start;}}else{if(slot.start.equals(this.state.bookingStart)){this.state.bookingStart=null;this.state.bookingEnd=null;}else if(slot.canBeEndDate){if(this.state.bookingEnd&&slot.start.equals(this.state.bookingEnd)){this.state.bookingEnd=null;}else{this.state.bookingEnd=slot.start;}}else if(!slot.isBooked){if(!slot.start.hasSame(this.state.bookingStart,"day")||slot.start>this.state.bookingStart||this.bookingsByDate[this.state.selectedDay.toISODate()]?.some((booking)=>booking.overlaps(luxon.Interval.fromDateTimes(slot.start,this.state.bookingStart),),)){this.state.bookingEnd=null;}
this.state.bookingStart=slot.start;}}}}
return __exports;});;

/* /room/static/src/room_booking/room_booking_remaining_time.js */
odoo.define('@room/room_booking/room_booking_remaining_time',['@room/room_booking/useInterval','@odoo/owl'],function(require){'use strict';let __exports={};const{useInterval}=require("@room/room_booking/useInterval");const{Component,onWillUpdateProps,useState,xml}=require("@odoo/owl");const RoomBookingRemainingTime=__exports.RoomBookingRemainingTime=class RoomBookingRemainingTime extends Component{static template=xml`
        <div class="o_room_remaining_time rounded py-3 bg-black-25 display-4 text-center text-white"
             t-out="state.remainingTime.toFormat('hh:mm:ss')"/>
    `;static props={endTime:{type:Object},};setup(){this.state=useState({remainingTime:this.props.endTime.diffNow()});useInterval(()=>{const remainingTime=this.props.endTime.diffNow();if(remainingTime>=0){this.state.remainingTime=remainingTime;}},1000);onWillUpdateProps((nextProps)=>{this.state.remainingTime=nextProps.endTime.diffNow();});}}
return __exports;});;

/* /room/static/src/room_booking/room_booking_view/room_booking_view.js */
odoo.define('@room/room_booking/room_booking_view/room_booking_view',['@web/core/l10n/translation','@web/core/browser/browser','@web/core/browser/feature_detection','@web/core/confirmation_dialog/confirmation_dialog','@web/core/l10n/dates','@web/core/network/rpc','@web/core/utils/urls','@web/core/registry','@room/room_booking/room_booking_form/room_booking_form','@room/room_booking/room_booking_remaining_time','@room/room_booking/room_display_time','@room/room_booking/useInterval','@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{browser}=require("@web/core/browser/browser");const{isDisplayStandalone}=require("@web/core/browser/feature_detection");const{ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const{deserializeDateTime,serializeDateTime}=require("@web/core/l10n/dates");const{rpc}=require("@web/core/network/rpc");const{redirect}=require("@web/core/utils/urls");const{registry}=require("@web/core/registry");const{RoomBookingForm}=require("@room/room_booking/room_booking_form/room_booking_form");const{RoomBookingRemainingTime}=require("@room/room_booking/room_booking_remaining_time");const{RoomDisplayTime}=require("@room/room_booking/room_display_time");const{useInterval}=require("@room/room_booking/useInterval");const{useService}=require("@web/core/utils/hooks");const{Component,markup,onWillStart,onWillUnmount,useExternalListener,useState,}=require("@odoo/owl");const INACTIVITY_TIMEOUT=120000;function formatServerBooking(booking){return{id:booking.id,name:booking.name,interval:luxon.Interval.fromDateTimes(deserializeDateTime(booking.start_datetime),deserializeDateTime(booking.stop_datetime),),};}
const RoomBookingView=__exports.RoomBookingView=class RoomBookingView extends Component{static components={RoomBookingForm,RoomBookingRemainingTime,RoomDisplayTime,};static template="room.RoomBookingView";static props={accessToken:String,bookableBgColor:String,bookedBgColor:String,description:String,id:Number,name:String,};setup(){this.manageRoomUrl=`/room/${this.props.accessToken}`;this.pwaService=useService("pwa");this.state=useState({bookings:[],bookingName:undefined,bookingToEdit:undefined,currentBooking:null,currentDate:this.now.startOf("day"),scheduleBooking:false,scheduleBookingQuickCreate:false,showInstallPwaButton:!isDisplayStandalone()&&this.pwaService.isSupportedOnBrowser,});this.busService=this.env.services.bus_service;this.busService.addChannel("room_booking#"+this.props.accessToken);this.busService.subscribe(`room#${this.props.id}/booking/create`,(bookings)=>bookings.forEach((booking)=>this.addBooking(formatServerBooking(booking))),);this.busService.subscribe(`room#${this.props.id}/booking/delete`,(bookings)=>bookings.forEach((booking)=>this.removeBooking(booking.id)),);this.busService.subscribe(`room#${this.props.id}/booking/update`,(bookings)=>bookings.forEach((booking)=>this.udpateBooking(formatServerBooking(booking))),);this.busService.subscribe(`room#${this.props.id}/reload`,(url)=>redirect(url));this.notificationService=useService("notification");this.dialogService=useService("dialog");this.ui=useService("ui");onWillStart(this.loadBookings);useInterval(this.refreshBookingView.bind(this),1000);["pointerdown","keydown"].forEach((event)=>useExternalListener(window,event,()=>{browser.clearTimeout(this.inactivityTimer);this.inactivityTimer=browser.setTimeout(()=>{this.resetBookingForm();},INACTIVITY_TIMEOUT);}),);onWillUnmount(()=>browser.clearTimeout(this.inactivityTimer));}
get timeFormat(){return luxon.DateTime.TIME_SIMPLE;}
get dateFormat(){return luxon.DateTime.DATE_HUGE;}
get bgColor(){return((this.state.currentBooking?this.props.bookedBgColor:this.props.bookableBgColor)+"DD");}
get nextBooking(){return this.state.currentBooking?this.state.bookings[1]:this.state.bookings[0];}
get now(){return luxon.DateTime.now();}
get roomDescription(){return markup(this.props.description);}
deleteBooking(bookingId){this.dialogService.add(ConfirmationDialog,{body:_t("Are you sure you want to delete this booking?"),confirmLabel:_t("Delete"),confirm:()=>rpc(`${this.manageRoomUrl}/booking/${bookingId}/delete`),cancel:()=>{},});}
async editBooking(bookingId,name,start,end){this.ui.block();await rpc(`${this.manageRoomUrl}/booking/${bookingId}/update`,{name,start_datetime:serializeDateTime(start),stop_datetime:serializeDateTime(end),});this.removeBooking(bookingId);this.addBooking({id:bookingId,interval:luxon.Interval.fromDateTimes(start,end),name,});this.ui.unblock();this.resetBookingForm();}
endCurrentBooking(){this.dialogService.add(ConfirmationDialog,{body:_t("Are you sure you want to end the current booking ?"),confirmLabel:_t("End Booking"),confirm:()=>{const{id,name,interval}=this.state.currentBooking;this.editBooking(id,name,interval.start,this.now);},cancel:()=>{},});}
installPwa(){browser.open(`/scoped_app?app_id=room&path=${encodeURIComponent(browser.location.pathname.slice(1))}&app_name=${encodeURIComponent(this.props.name)}`,);}
async loadBookings(){const bookings=await rpc(`${this.manageRoomUrl}/get_existing_bookings`);for(const booking of bookings){this.addBooking(formatServerBooking(booking));}
this.refreshBookingView();}
quickCreateBooking(duration){this.scheduleBooking(this.state.bookingName,this.now,this.now.plus({minutes:duration}),);}
refreshBookingView(){if(this.state.currentBooking?.interval.end<this.now){this.removeBooking(this.state.currentBooking.id);}
const currentBooking=this.state.bookings[0]?.interval.start<this.now?this.state.bookings[0]:null;if(this.state.currentBooking?.interval.end!==currentBooking?.interval.end){this.state.currentBooking=currentBooking;}
if(this.state.currentDate.day!==this.now.startOf("day").day){this.state.currentDate=this.now.startOf("day");}}
resetBookingForm(){this.state.scheduleBooking=false;this.state.scheduleBookingQuickCreate=false;this.state.bookingToEdit=undefined;this.state.bookingName=undefined;}
async scheduleBooking(name,start,end){name=name||_t("Public Booking");this.ui.block();const bookingId=await rpc(`${this.manageRoomUrl}/booking/create`,{name,start_datetime:serializeDateTime(start),stop_datetime:serializeDateTime(end),});this.addBooking({id:bookingId,interval:luxon.Interval.fromDateTimes(start,end),name,});this.ui.unblock();this.resetBookingForm();}
addBooking(newBooking){if(this.state.bookings.map((booking)=>booking.id).includes(newBooking.id)||newBooking.interval.end<this.now){return;}
const newBookingInsertIdx=this.state.bookings.findIndex((booking)=>booking.interval.start>newBooking.interval.start,);if(newBookingInsertIdx===-1){this.state.bookings.push(newBooking);}else{this.state.bookings.splice(newBookingInsertIdx,0,newBooking);}
if(newBooking.interval.start<this.now){this.refreshBookingView();}}
removeBooking(bookingId){const bookingIdx=this.state.bookings.findIndex((booking)=>booking.id===bookingId);if(bookingIdx!==-1){this.state.bookings.splice(bookingIdx,1);if(this.state.currentBooking?.id===bookingId){this.refreshBookingView();}}
if(this.state.bookingToEdit?.id===bookingId&&!this.ui.isBlocked){this.resetBookingForm();this.notificationService.add(_t("The booking you were editing has been updated or deleted."),);}}
udpateBooking(booking){this.removeBooking(booking.id);this.addBooking(booking);}}
registry.category("public_components").add("room.room_booking_view",RoomBookingView);return __exports;});;

/* /room/static/src/room_booking/room_display_time.js */
odoo.define('@room/room_booking/room_display_time',['@room/room_booking/useInterval','@odoo/owl'],function(require){'use strict';let __exports={};const{useInterval}=require("@room/room_booking/useInterval");const{Component,useState,xml}=require("@odoo/owl");const RoomDisplayTime=__exports.RoomDisplayTime=class RoomDisplayTime extends Component{static template=xml`<div class="d-flex flex-column justify-content-center"><span class="display-6" t-out="state.currentTime.toFormat('T')"/><span class="smaller" t-out="state.currentTime.toFormat('DDDD')"/></div>`;static props={};setup(){this.state=useState({currentTime:luxon.DateTime.now()});useInterval(()=>(this.state.currentTime=luxon.DateTime.now()),1000);}}
return __exports;});;

/* /room/static/src/room_booking/useInterval.js */
odoo.define('@room/room_booking/useInterval',['@web/core/browser/browser','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{onMounted,onWillUnmount}=require("@odoo/owl");__exports.useInterval=useInterval;function useInterval(callback,duration){let interval;onMounted(()=>(interval=browser.setInterval(callback,duration)));onWillUnmount(()=>browser.clearInterval(interval));}
return __exports;});

                    /*******************************************
                    *  Templates                               *
                    *******************************************/

                    odoo.define("room.assets_room_booking.bundle.xml", ["@web/core/templates"], function(require) {
                        "use strict";
                        const { checkPrimaryTemplateParents, registerTemplate, registerTemplateExtension } = require("@web/core/templates");
                        /* room.assets_room_booking */
                        registerTemplate("room.RoomBookingForm", `/room/static/src/room_booking/room_booking_form/room_booking_form.xml`, `<t t-name="room.RoomBookingForm" xml:space="preserve">
        <div class="o_room_scheduler d-flex flex-column h-100 bg-light" t-ref="root">
            <div class="bg-white z-1 shadow-sm">
                <div class="d-flex flex-column-reverse flex-sm-row justify-content-between align-items-center gap-3 p-3 pb-0">
                    <div class="input-group">
                        <span class="input-group-text">
                            <i class="fa fa-sticky-note-o"/>
                        </span>
                        <input t-model.lazy.trim="state.bookingName" placeholder="Booking Name" class="form-control flex-grow-1"/>
                    </div>
                    <span class="flex-shrink-0" t-out="formattedMonth"/>
                </div>
                <div class="d-flex gap-1 border-bottom p-3 overflow-auto">
                    <button t-on-click="onPreviousWeekClick" class="btn btn-sm btn-secondary py-1 px-2" t-att-disabled="today &gt; weekInterval.start">
                        <i class="oi oi-chevron-left" title="Previous Week"/>
                    </button>
                    <t t-foreach="weekIntervalDays" t-as="day" t-key="day.start.toFormat('d')">
                        <button class="btn btn-sm flex-grow-1 py-1 px-2" t-att-class="{                                 'btn-primary': day.start.equals(state.selectedDay),                                 'btn-secondary': !day.start.equals(state.selectedDay),                                 'opacity-25': today &gt; day.start                             }" t-att-disabled="today &gt; day.start" t-on-click="() =&gt; this.state.selectedDay = day.start">
                            <t t-out="day.start.toLocaleString(dayFormat)"/>
                        </button>
                    </t>
                    <button t-on-click="onNextWeekClick" class="btn btn-sm btn-secondary py-1 px-2">
                        <i class="oi oi-lg oi-chevron-right my-auto" title="Next Week"/>
                    </button>
                </div>
            </div>
            <div class="d-flex flex-column flex-fill bg-100 overflow-auto">
                <div class="container-fluid flex-grow-1 p-3 overflow-auto">
                    <div class="o_room_scheduler_slots row row-cols-4 row-cols-lg-6 flex-grow-1 g-1">

                        <t t-foreach="slots" t-as="slot" t-key="slot.start.toISOTime()">
                            <div class="col d-flex position-relative" t-att-id="'slot' + slot.start.toFormat('HHmm')" t-on-click="() =&gt; this.onSlotClick(slot)">
                                <div class="d-flex flex-column justify-content-center align-items-center w-100 rounded bg-gradient" t-att-class="slot.isInSelectedInterval ? 'text-bg-primary' : slot.canBeEndDate ? 'text-bg-success  bg-opacity-50' : slot.isBooked ? 'bg-secondary text-muted opacity-25' : 'bg-success bg-opacity-25 text-success'">
                                    <div t-out="slot.start.toLocaleString(timeFormat)"/>
                                    <div t-if="slot.description" class="badge position-absolute bottom-0 start-50 translate-middle rounded-pill bg-dark">
                                        <i class="fa fa-clock-o me-1"/>
                                        <span t-out="slot.description"/>
                                    </div>
                                </div>
                            </div>
                        </t>
                    </div>
                </div>
            </div>
            <div class="d-flex gap-3 border-top border-bottom p-3 bg-white">
                <button class="btn btn-secondary btn-lg flex-grow-1" t-on-click="props.cancel">
                    Discard
                </button>
                <button t-if="state.bookingEnd" class="btn btn-primary btn-lg flex-grow-1" t-on-click="confirm">
                    <t t-if="props.bookingToEdit">
                        Update Meeting
                    </t>
                    <t t-else="">
                        Add
                    </t>
                </button>
            </div>
        </div>
    </t>
`);
registerTemplate("room.RoomBookingView", `/room/static/src/room_booking/room_booking_view/room_booking_view.xml`, `<t t-name="room.RoomBookingView" xml:space="preserve">
        <div class="row d-flex g-0 h-lg-100 bg-white">
            <div class="o_room_booking_main col-lg-8 col-xl-9 position-relative d-flex flex-column h-lg-100 overflow-lg-auto">
                <t t-if="state.scheduleBooking or state.bookingToEdit">
                    <RoomBookingForm bookings="state.bookings" createBooking.bind="scheduleBooking" cancel.bind="resetBookingForm" editBooking.bind="editBooking" bookingName="state.bookingName" bookingToEdit="state.bookingToEdit"/>
                </t>
                <div t-else="" class="d-flex flex-column flex-grow-1 justify-content-between gap-5 p-3 text-white fs-2" t-attf-style="background-image: linear-gradient(#{bgColor}, #{bgColor}), url('#{manageRoomUrl}/background')">
                    <span class="position-absolute top-0 start-0 w-100 h-100 bg-gradient"/>
                    <div class="o_room_top position-relative text-end">
                        <RoomDisplayTime/>
                    </div>
                    <div class="position-relative d-flex flex-fill flex-column align-items-center justify-content-around gap-3 w-100">
                        <t t-if="!state.currentBooking">
                            <t t-if="state.scheduleBookingQuickCreate">
                                <h1 class="text-white">Booking Now</h1>
                                <div>
                                    <input t-if="!nextBooking || nextBooking.interval.start &gt; now.plus({minutes: 15})" t-model.lazy.trim="state.bookingName" class="form-control bg-white fs-4" placeholder="Booking Name"/>
                                    <div class="d-flex justify-content-center gap-3 my-3">
                                        <button class="btn btn-dark btn-lg flex-grow-1 rounded-pill px-3 px-lg-5" t-if="!nextBooking || nextBooking.interval.start &gt; now.plus({minutes: 15})" t-on-click="() =&gt; this.quickCreateBooking(15)">
                                            15 min
                                        </button>
                                        <div t-else="" class="d-flex flex-column align-items-center gap-2 p-3 fs-6">
                                            <i class="fa fa-warning fa-2x"/>
                                            The next booking is starting soon.
                                        </div>
                                        <button class="btn btn-dark btn-lg flex-grow-1 rounded-pill px-3 px-lg-5" t-if="!nextBooking || nextBooking.interval.start &gt; now.plus({minutes: 30})" t-on-click="() =&gt; this.quickCreateBooking(30)">
                                            30 min
                                        </button>
                                        <button class="btn btn-dark btn-lg flex-grow-1 rounded-pill px-3 px-lg-5" t-if="!nextBooking || nextBooking.interval.start &gt; now.plus({minutes: 60})" t-on-click="() =&gt; this.quickCreateBooking(60)">
                                            1 hour
                                        </button>
                                    </div>
                                    <div t-if="!nextBooking" class="d-flex mt-3 w-100">
                                        <span class="flex-grow-1 align-self-center border"/>
                                        <span class="mx-3 fs-6 text-uppercase">Or</span>
                                        <span class="flex-grow-1 align-self-center border"/>
                                    </div>
                                </div>
                            </t>
                            <t t-else="">
                                <div class="d-flex flex-column align-items-center">
                                    <i class="fa fa-check-circle fa-3x"/>
                                    <h1 class="mb-0 text-uppercase fw-bold display-3 text-white">Available</h1>
                                </div>
                            </t>
                        </t>
                        <t t-else="">
                            <div class="d-flex flex-column align-items-center">
                                <i class="fa fa-calendar-times-o fa-3x"/>
                                <h1 class="mb-0 text-uppercase fw-bold display-3 text-white">Booked</h1>
                                <span t-out="state.currentBooking.name" class="fs-5 opacity-75"/>
                            </div>
                            <RoomBookingRemainingTime endTime="state.currentBooking.interval.end"/>
                        </t>
                        <div class="d-flex flex-column flex-xl-row gap-4">
                            <button t-if="state.currentBooking" class="btn btn-lg btn-dark d-flex justify-content-center align-items-center gap-3 rounded-pill py-lg-3 px-3 px-lg-5" t-on-click="endCurrentBooking">
                                End Booking
                                <i class="fa fa-times-circle"/>
                            </button>
                            <button t-elif="!state.scheduleBookingQuickCreate" class="btn btn-dark btn-lg d-flex justify-content-center align-items-center gap-3 rounded-pill py-lg-3 px-3 px-lg-5" t-on-click="() =&gt; this.state.scheduleBookingQuickCreate = true">
                                Start now
                                <i class="fa fa-rocket"/>
                            </button>
                            <button class="btn btn-light btn-lg d-flex justify-content-center align-items-center gap-3 rounded-pill py-lg-3 px-3 px-lg-5" t-on-click="() =&gt; this.state.scheduleBooking = true">
                                Add a Booking
                                <i class="fa fa-calendar-plus-o"/>
                            </button>
                        </div>
                    </div>
                    <div class="o_room_bottom position-relative d-flex gap-3 w-100" t-if="state.scheduleBookingQuickCreate">
                        <button class="btn btn-lg flex-grow-1 bg-dark bg-opacity-25 text-white" t-on-click="resetBookingForm">
                            Discard
                        </button>
                    </div>
                </div>
            </div>
            <div class="o_room_sidebar col-lg-4 col-xl-3 position-relative border-start bg-100">
                <t t-call="room.RoomBookingSidebar"/>
            </div>
        </div>
    </t>

    `);
registerTemplate("room.RoomBookingSidebar", `/room/static/src/room_booking/room_booking_view/room_booking_view.xml`, `<t t-name="room.RoomBookingSidebar" xml:space="preserve">
        <div class="position-lg-absolute top-0 start-0 end-0 bottom-0 d-flex flex-column justify-content-between h-100 p-3">

            <div class="my-2 border-bottom">
                <h4 t-out="props.name"/>
                <div class="mb-3 text-muted" t-if="props.description" t-out="roomDescription"/>
            </div>
            <div t-if="state.bookings.length === 0" class="d-flex justify-content-center flex-column flex-fill py-3 text-center">
                <h5>No Bookings Planned</h5>
                <span class="text-muted">This room is as free as a fish in a sea of endless possibilities</span>
            </div>
            <div t-else="" class="flex-fill pt-1 overflow-auto">

                <h6 class="mt-3 text-capitalize" t-out="state.currentDate.toRelativeCalendar()"/>
                <div class="list-group">
                    <t t-set="previous_date" t-value="state.currentDate"/>
                    <t t-foreach="state.bookings" t-as="booking" t-key="booking.id">
                        <t t-if="booking.interval.start.startOf('day') &gt; previous_date">
                            <div t-if="booking_first" class="text-center text-muted">
                                No Bookings for Today
                            </div>
                            <h6 class="mt-4 mb-2" t-out="booking.interval.start.toLocaleString(dateFormat)"/>
                            <t t-set="previous_date" t-value="booking.interval.start.startOf('day')"/>
                        </t>
                        <div class="list-group-item list-group-item-action d-flex justify-content-between align-items-start cursor-pointer" t-att-class="state.bookingToEdit?.id === booking.id ? 'active' : ''" t-on-click="() =&gt; state.bookingToEdit = {...booking}">
                            <div class="text-break">
                                <div class="d-flex align-items-center">
                                    <span t-out="booking.interval.start.toLocaleString(timeFormat)"/>
                                    <i class="oi oi-arrow-right mx-1 smaller text-muted"/>
                                    <span t-out="booking.interval.end.toLocaleString(timeFormat)"/>
                                </div>
                                <div class="smaller" t-out="booking.name"/>
                            </div>
                            <button class="btn btn-link btn-dark me-n3 mt-n2 p-3 lh-1 smaller" t-on-click.stop="() =&gt; this.deleteBooking(booking.id)">
                                <i class="fa fa-trash"/>
                            </button>
                        </div>
                    </t>
                </div>
            </div>
            <div t-if="state.showInstallPwaButton" class="d-flex justify-content-center bg-200 mx-n3 mb-n3 p-2">
                <button class="btn btn-primary" t-on-click="installPwa">Install Application</button>
                <button class="btn btn-link position-absolute end-0" t-on-click="() =&gt; state.showInstallPwaButton = false">
                    <i class="oi oi-close"/>
                </button>
            </div>
        </div>
    </t>
`);
                    });
