HAPI Sample - Scheduler - Sample Code for Multiple Slot Selection

Check out the sample code from our live page for booking rooms.


CSS

    <link href="/plugins/slick/slick.css" rel="stylesheet" />
    <link href="/plugins/slick/slick-theme.css" rel="stylesheet" />
    <style>
        @media(max-width: 480px) {
            .ui-update .max-scheduler-width {
                max-width: 100px;
                overflow: hidden;
            }
        }

        .ui-update .th_time {
            font-size: 10px;
        }

        .ui-update .bookedBlock {
            width: 60px;
            overflow: hidden;
            font-size: 9px;
            max-height: 24px;
            height: 24px;
            padding: 0px;
        }

        .ui-update .timeSlot.notavailable, .ui-update .timeSlot.notavailable:hover {
            background-color: #888888;
            cursor: not-allowed;
        }

        ::-webkit-scrollbar-thumb {
            background-color: rgba(0,0,0,.24);
        }

        ::-webkit-scrollbar {
            -webkit-appearance: inherit;
            width: 8px;
        }

        .ui-update .wrapper {
            padding-top: 1em;
            padding-bottom: 1em;
        }

        .ui-update .portal-bg {
            background-color: #FFF;
        }

        .ui-update .days,
        .ui-update .timeTableWrapper {
            position: relative;
            width: 100%;
            height: 100%;
            display: inline-block;
        }

        .ui-update .input_inline {
            display: inline-block;
            width: auto;
        }

        .ui-update .input_inline {
            width: 40%;
        }

        #timeSelect .txt {
            margin: 0 8px;
        }

        #timeSelect h5,
        #locationSelect h5 {
            display: block;
        }

        .ui-update .days table {
            border-collapse: separate;
            border-spacing: 0.5em;
        }

        .ui-update .days td {
            background-color: #fff;
            padding: 8px;
            cursor: pointer;
            padding: 0.5em 1em;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }

            .ui-update .days td * {
                display: block;
                text-align: center;
            }

            .ui-update .days td.selected {
                box-shadow: 0 0 5px #77A331;
                z-index: 5;
            }

                .ui-update .days td.selected .hdg,
                .ui-update .days td.selected .hdg_1,
                .ui-update .days td.selected .hdg_6,
                .ui-update .days td.selected .txt,
                .ui-update .days td.selected .txt_minuscule {
                    color: #77A331;
                }

        .ui-update .times,
        .ui-update .bookSlot {
            display: none;
        }

        .ui-update .timeTableWrapper table {
            float: left;
        }

        .ui-update th {
            padding: 5px;
            height: 35px;
        }

        .ui-update td {
            padding: 5px;
            margin: 0;
            white-space: nowrap;
        }

        .ui-update .timeTableWrapper .right,
        .ui-update .days .scheduleDaysWrapper {
            overflow: auto;
        }

        .ui-update th {
            text-align: center;
        }

        .ui-update .headCol th,
        .ui-update .headCol td {
            padding-right: 10px;
        }

        .ui-update .headCol tr {
            height: 35px;
            border-right: 1px solid #f0f0f0;
            border-bottom: 1px solid #f0f0f0;
        }

        .ui-update .timeSlot {
            text-align: center;
            border: 1px solid #EEEEEE;
            cursor: pointer;
            transition: 150ms all ease-in-out;
            -webkit-touch-callout: none;
            -webkit-user-select: none;
            -khtml-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            white-space: nowrap;
            min-width: 75px;
            height: 35px;
        }

            .ui-update .timeSlot:hover {
                background-color: #fbfbfb;
            }

        .ui-update .booked {
            background-color: #FEEEEB;
            border-color: #FEEEEB;
            cursor: not-allowed;
        }

            .ui-update .booked:hover {
                background-color: #FEEEEB;
                border-color: #FEEEEB;
                cursor: not-allowed;
            }

        .ui-update .blocked {
            background-color: #eefeeb;
            border-color: #eefeeb;
            cursor: not-allowed;
        }

            .ui-update .blocked:hover {
                background-color: #eefeeb;
                border-color: #eefeeb;
                cursor: not-allowed;
            }

        .ui-update .times table .selected {
            background-color: #c2d631;
            border-color: #c2d631;
        }

            .ui-update .times table .selected:hover {
                background-color: #c2d631;
            }
    </style>

HTML
(please note this is currently in ASP.NET but you can replace all with HAPI)

            <section class="component">
                <div class="component-content">

                    <div class="split split_alignBtm split_collapseOnMobile">
                        <h2 class="hdg hdg_4">Make a Reservation <%if scheduleItems.Count = 1 %>for <%=scheduleItems.Item(0).schedule_item %><%end if %></h2>
                        <!--#include file="/include/includeLoginUpdate.aspx"-->
                    </div>
                    <%if scheduleItems.Count = 1 Then %>
                    <%=scheduleItems(0).schedule_item_description %>
                    <% End if %>
                </div>
            </section>
            <section class="component">
                <div class="component-content">
                    <div class="box mix-box_outlined">
                        <div class="box-bd box-bd_inflated vr vr_x28">
                            <asp:PlaceHolder runat="server" ID="pnlSlots" Visible="false">
                                <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x6">Select a Date</h2>
                                <ul id="dateSlider" class="scheduleDays">
                                    <% Dim availSlots As Integer = 0 %>
                                    <% for i As Integer = 0 To DateDiff(DateInterval.Day, from_date, to_date) %>
                                    <% availSlots = slots.FindAll(Function(x) x.slot_start >= Convert.ToDateTime(String.Format("{0:d}", from_date.AddDays(i)) & " 12:00 AM") And x.slot_end <= Convert.ToDateTime(String.Format("{0:d}", from_date.AddDays(i)) & " 11:59 PM") And x.isAvailable).Count %>
                                    <li id="<%=String.Format("{0:MMddyyyy}", from_date.AddDays(i)) %>" data-fulldate="<%=String.Format("{0:MMMM dd yyyy}", from_date.AddDays(i)) %>">
                                        <button class="cardBtn">
                                            <span class="cardBtn-bd">
                                                <span class="cardBtn-txt cardBtn-txt_label">
                                                    <span><%=from_date.AddDays(i).ToString("dddd") %></span><br />
                                                    <span><%=MonthName(Month(from_date.AddDays(i))) %></span>
                                                    <span><%=Year(from_date.AddDays(i)) %></span>
                                                </span>
                                                <span class="cardBtn-txt cardBtn-txt_digit"><%=Day(from_date.AddDays(i)) %></span>
                                            </span>
                                            <span class="cardBtn-ft cardBtn-ft_alignRight">
                                                <span class="cardBtn-txt">
                                                    <span data-pv-element="total_slots"><%=IIf(availSlots = 0, "No", availSlots) %></span> spot<%=People_Vine___Portal.functions.returnPlural(availSlots) %> available
                                                </span>
                                            </span>
                                        </button>
                                    </li>
                                    <% next %>
                                </ul>
                                <div class="times vr vr_x8">
                                    <!-- Populate each day of slots, using the data-for to populate the day so that when you click on a day above, it opens the correct slots-->
                                    <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x3">Make Selection: <em id="selectDate"></em></h2>
                                    <div id="timeTable">
                                    </div>
                                    <% for i As Integer = 0 To DateDiff(DateInterval.Day, from_date, to_date) %>
                                    <% curDate = from_date.AddDays(i) %>
                                    <div data-for="<%=String.Format("{0:MMddyyyy}", curDate) %>" class="slotList" style="display: none;">
                                        <!-- Populates date MMMMddyyyy-->

                                        <div class="timeTableWrapper">
                                            <div class="headCol">
                                                <table>
                                                    <thead>
                                                        <th class="txt mix-txt_bold">Reserving</th>
                                                    </thead>
                                                    <tbody>
                                                        <!-- Each room gets populated as a separated row to allow the "scroll over" effect-->
                                                        <% For each si As People_Vine___Portal.api.scheduler.wi_schedule_item In scheduleItems %>
                                                        <tr>
                                                            <td class="txt mix-txt_bold max-scheduler-width">
                                                                <%=si.schedule_item %>
                                                                <%--<% If si.category_no > 0 Then %>
                                                                <br /><span class="label label-info"><%=si.category_name %></span>
                                                                <% end if %>--%>
                                                            </td>
                                                        </tr>
                                                        <% next %>
                                                    </tbody>
                                                </table>
                                            </div>
                                            <div class="right">
                                                <table>
                                                    <thead>
                                                        <!-- All times in the series get populated here as headers-->
                                                        <% tempEarliestTime = earliestTime %>
                                                        <% While tempEarliestTime < latestTime %>
                                                        <th class="th_time" id="<%=String.Format("{0:t}", tempEarliestTime) %>"><%=String.Format("{0:t}", tempEarliestTime) %></th>
                                                        <% tempEarliestTime = tempEarliestTime.AddMinutes(incrementMinutes) %>
                                                        <% end while %>
                                                    </thead>
                                                    <tbody>
                                                        <!-- Each room gets it's own row, and if booked, add class 'booked' to it-->
                                                        <!-- Start date can be in any format becauase it is not rendered on the page-->
                                                        <!-- startTime & endTime need to be in hh:mm because they get updated to the page -->
                                                        <% For each sc As People_Vine___Portal.api.scheduler.wi_schedule_item In scheduleItems %>
                                                        <tr data-room="<%=sc.schedule_item %>">
                                                            <!-- Need to loop through all slots and then if exists put block -->
                                                            <% tempEarliestTime = earliestTime %>
                                                            <% While tempEarliestTime < latestTime %>
                                                            <% curDate = Convert.ToDateTime(String.Format("{0:d}", curDate) & " " & String.Format("{0:t}", tempEarliestTime)) %>
                                                            <% slot = slots.Find(Function(x) x.slot_start >= curDate And x.slot_end <= curDate.AddMinutes(sc.block_duration) And x.schedule_item_no = sc.schedule_item_no) %>
                                                            <% if slot Is Nothing Then %>
                                                            <td class="timeSlot notavailable booked">&nbsp;</td>
                                                            <% else %>
                                                            <td data-fee="<%=slot.slot_fee %>" data-room="<%=sc.schedule_item %>" data-starttime="<%=String.Format("{0:t}", slot.slot_start) %>" data-endtime="<%=String.Format("{0:t}", slot.slot_end) %>" data-startdate="<%=String.Format("{0:d}", slot.slot_start) %>" data-duration="<%=sc.block_duration %>" data-roomno="<%=sc.schedule_item_no %>" data-slotno="<%=slot.schedule_slot_no %>" class="timeSlot <%=IIf(slot.isAvailable, IIf(sc.canBook, "", "blocked"), "booked") %>" <%=IIf(Not slot.isAvailable And sc.canBook And sc.visibility <> "public", "title=""" & slot.customer.company_name & " (" & slot.customer.first_name & ")""", "") %>>
                                                                <% If Not slot.isAvailable And sc.canBook And sc.visibility <> "public" And slot.customer.customer_no > 0 Then %>
                                                                <div class="bookedBlock">
                                                                    <%=slot.customer.company_name %><br />
                                                                    <%=slot.customer.first_name %>&nbsp; <%=IIf(slot.customer.last_name.Length > 1, Left(slot.customer.last_name, 1), "") %>
                                                                </div>
                                                                <% else %>
                                                                <% if slot.slot_fee > 0 Then %>
                                                                <%=String.Format("{0:c}", slot.slot_fee) %>
                                                                <% else %>
                                                                        &nbsp;
                                                                    <% end if %>
                                                                <% end if %>
                                                            </td>
                                                            <% end if %>
                                                            <% tempEarliestTime = tempEarliestTime.AddMinutes(incrementMinutes) %>
                                                            <% end while %>
                                                        </tr>
                                                        <% next %>
                                                    </tbody>
                                                </table>
                                            </div>
                                        </div>
                                    </div>
                                    <% Next %>
                                </div>
                                <div class="bookSlot" id="bookSlot">
                                    <h1 class="hdg hdg_5">Confirm Selection:</h1>
                                    <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x3"><em><span id="dateSelection">January 1st, 2016</span> <span id="roomName">Example Room</span> <span id="roomStartTime">12:00PM</span> – <span id="roomEndTime">12:30PM</span></em> <span id="roomCost">$0.00</span></h2>
                                    <ul class="split split_alignBtm split_collapseOnMobile split_basisRight">
                                        <li>
                                            <span class="txt txt_feature">Please confirm the date, time and item you are booking is accurate.  On the next step, you will be taken to confirm your reservation.</span>
                                        </li>
                                        <li>
                                            <a href="/reservation" class="btn btn_hasIcon" id="bookNowBtn" onclick="myApp.showPleaseWait();">Continue<svg class="icon"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/media/svg/defs.svg#icon_caretRightHeavy"></use></svg>
                                            </a>
                                        </li>
                                    </ul>
                                </div>
                            </asp:PlaceHolder>
                            <asp:PlaceHolder runat="server" ID="pnlNoSlots" Visible="false">
                                <h2 class="hdg hdg_4">Sorry, we don't currently have any availability at this time.</h2>
                            </asp:PlaceHolder>
                        </div>
                    </div>
                </div>
            </section>
            <section class="component component_loose">
                <div class="component-content">
                    <div class="box mix-box_outlined">
                        <div class="box-bd box-bd_inflated">
                            <div class="split split_basisRight split_collapseOnMobile">
                                <h3 class="hdg hdg_6 mix-hdg_brandCallout">When booking, keep in mind these restrictions:</h3>
                                <div>
                                    <%if scheduleItems.Count = 1 Then %>
                                    <% if scheduleItems(0).time_between > 0 Or scheduleItems(0).max_blocks > 0 Then %>
                                    <ul class="blocks blocks_4to3to2to1 blocks_equalHeight">
                                        <% if scheduleItems(0).time_between > 0 Then %>
                                        <li>
                                            <a class="cardBtn">
                                                <span class="cardBtn-bd">
                                                    <span class="cardBtn-txt cardBtn-txt_label">Time Between<br />
                                                        Reservations
                                                    </span>
                                                    <span class="cardBtn-txt cardBtn-txt_digit"><%=IIf(scheduleItems(0).time_between > 1440, scheduleItems(0).time_between / 1440, IIf(scheduleItems(0).time_between > 60, scheduleItems(0).time_between / 60, scheduleItems(0).time_between)) %></span> <small><%=IIf(scheduleItems(0).time_between > 1440, "days", IIf(scheduleItems(0).time_between > 60, "hours", "minutes")) %></small>
                                                </span>
                                            </a>
                                        </li>
                                        <% End if %>
                                        <% If scheduleItems(0).max_blocks > 0 Then %>
                                        <li>
                                            <a class="cardBtn">
                                                <span class="cardBtn-bd">
                                                    <span class="cardBtn-txt cardBtn-txt_label">Max Slots<br />
                                                        Per Booking
                                                    </span>
                                                    <span class="cardBtn-txt cardBtn-txt_digit"><%=scheduleItems(0).max_blocks %></span>
                                                    <small><%=IIf(scheduleItems(0).block_duration > 1440, scheduleItems(0).block_duration / 1440, IIf(scheduleItems(0).block_duration > 60, scheduleItems(0).block_duration / 60, scheduleItems(0).block_duration)) %> minutes each</small>
                                                </span>
                                            </a>
                                        </li>
                                        <% end if %>
                                    </ul>
                                    <% else %>

                                    <% End if %>
                                    <% else %>
                                    <ul class="blocks blocks_4to3to2to1 blocks_equalHeight">
                                        <% If maxSlots > 0 Then %>
                                        <li>
                                            <a class="cardBtn">
                                                <span class="cardBtn-bd">
                                                    <span class="cardBtn-txt cardBtn-txt_label">Max Slots<br />
                                                        Per Booking
                                                    </span>
                                                    <span class="cardBtn-txt cardBtn-txt_digit"><%=maxSlots %></span>
                                                    <small><%=IIf(incrementMinutes > 1440, incrementMinutes / 1440, IIf(incrementMinutes > 60, incrementMinutes / 60, incrementMinutes)) %> minutes each</small>
                                                </span>
                                            </a>
                                        </li>
                                        <% end if %>
                                    </ul>
                                    <% End if %>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </section>
            <section class="component component_loose">
                <div class="component-content">

                    <div class="box mix-box_outlined">
                        <div class="box-bd box-bd_inflated vr">
                            <h2 class="hdg hdg_6 mix-hdg_dark vr-override_x6">Filter</h2>
                            <ul class="gridList">
                                <li class="gridList-item gridList-item_7of16 gridList-item_tight" style="<%=iif(request("type") = "calendar", "display:none;", "")%>">
                                    <ul class="gridList-item-subGroup">
                                        <li>
                                            <span class="fieldset">
                                                <label class="fieldset-label fieldset-label_isHidden" for="<%=sfrom_date.ClientID %>">start date</label>
                                                <span class="fieldset-input">
                                                    <asp:TextBox runat="server" ID="sfrom_date" placeholder="MM/DD/YYYY" CssClass="js-datepicker" />
                                                </span>
                                            </span>
                                        </li>
                                        <li>
                                            <span class="fieldset">
                                                <label class="fieldset-label fieldset-label_isHidden" for="<%=sto_date.ClientID %>">end date</label>
                                                <span class="fieldset-input">
                                                    <asp:TextBox runat="server" ID="sto_date" placeholder="MM/DD/YYYY" CssClass="js-datepicker" />
                                                </span>
                                            </span>
                                        </li>
                                    </ul>
                                </li>
                                <li class="gridList-item gridList-item_7of16 gridList-item_tight">
                                    <span class="fieldset">
                                        <label class="fieldset-label" for="<%=schedule_item_no.ClientID %>">or filter</label>
                                        <span class="fieldset-input">
                                            <asp:DropDownList runat="server" ID="schedule_item_no" />
                                        </span>
                                    </span>
                                </li>
                                <li class="gridList-item gridList-item_2of16 gridList-item_tight">
                                    <span class="fieldset">
                                        <label class="fieldset-label">&nbsp;</label>
                                        <asp:Button runat="server" ID="btnsub" Text="Apply" CssClass="btn mix-btn_stretch" OnClick="btnsub_Click" OnClientClick="myApp.showPleaseWait();" />

                                    </span>
                                </li>
                                <li class="gridList-item" style="<%=iif(request("type") = "calendar", "display:none;", "")%>">
                                    <asp:RadioButtonList runat="server" ID="filterDate" CssClass="hList tick tick_bubble" RepeatLayout="UnorderedList" AutoPostBack="true" OnSelectedIndexChanged="filterDate_SelectedIndexChanged">
                                        <asp:ListItem Value="today">Today</asp:ListItem>
                                        <asp:ListItem Value="tomorrow">Tomorrow</asp:ListItem>
                                        <asp:ListItem Value="this week">This Week</asp:ListItem>
                                        <asp:ListItem Value="next week">Next Week</asp:ListItem>
                                    </asp:RadioButtonList>
                                </li>
                            </ul>
                        </div>
                    </div>
                </div>
            </section>

Javascript

    <script>window.jQuery || document.write('<script src="/assets/jQuery/default/jquery.min.js">\x3C/script>')</script>
    <script src="/scripts/vendor/fullcalendar/moment.min.js"></script>
    <script src="/plugins/slick/slick.min.js"></script>
    <script src="/scripts/components/schedulerMulti.js"></script>
    <script>
        //JS init for slider (init is for reference only - page is not loading Slick Slider plugin: http://kenwheeler.github.io/slick/)
        var MAX_SLOTS = 10 //make dynamic based on available schedulers;
        var loadSlick = function () {
            var selector = '#dateSlider';
            var config = {
                centerPadding: '60px',
                slidesToShow: 7,
                arrows: true,
                infinite: false,
                responsive: [
                    {
                        breakpoint: 979,
                        settings: {
                            slidesToShow: 7
                        }
                    },
                    {
                        breakpoint: 767,
                        settings: {
                            slidesToShow: 3
                        }
                    },
                    {
                        breakpoint: 480,
                        settings: {
                            slidesToShow: 1
                        }
                    }
                ]
            };
            $(selector).slick(config);
        };

        $(document).ready(function () {
            //new DatepickerHelper('.js-datepicker', { setDate: new Date(), minDate: new Date(1900, 1, 1) });
            var Sch = scheduler(MAX_SLOTS);
            Sch.init();
            loadSlick();

            $("#sfrom_date").datepicker({
                defaultDate: "+1d",
                changeMonth: false,
                numberOfMonths: 3,
                minDate: "+0d",
                maxDate: "+360d",
                onClose: function (selectedDate) {
                    $("#sto_date.ClientID").datepicker("option", "minDate", selectedDate);
                }
            });
            $("#sto_date").datepicker({
                defaultDate: "+3d",
                changeMonth: false,
                numberOfMonths: 3,
                minDate: "+1d",
                maxDate: "+360d",
                onClose: function (selectedDate) {
                    $("#sfrom_date").datepicker("option", "maxDate", selectedDate);
                }
            });
        });
    </script>

Additional Help Tutorials

Find more ways to grow on PeopleVine.

The Ultimate Agency Tool - Import a Folder of Snippets Directly into the Drag and Drop Builder

Instead of taking the time to copy and paste the HTML, enter a title and take a screenshot, you can now drag and drop folders full of HTML snippets and we'll set them up, categorize them and add a screenshot of the rendered snippet.

Posted June 22, 2019

Improved Transaction Email with Option to Download as PDF

We have made it easier to send someone a transaction receipt by including an out-of-the-box template and a new option to download as a PDF.

Posted June 18, 2019

Make Your Order Receipts Member Friendly

You now have better control over the items that show up on an order receipt in your member portal.

Posted June 18, 2019

Sell Memberships with Credits that are Used When Booking an Appointment

You can setup a membership program that allows a member up to x amount of appointments per month. If they exceed that amount, we'll re-bill them for another month of x amount of appointments that lasts a full billing cycle.

Posted June 17, 2019

Use the PeopleVine Point of eXperience (POX) App to Check In Your Members

The PeopleVine POX app provides you with a front of the house tool to streamline the member check-in process.

Posted June 11, 2019

When Sending Email Newsletters You Can Include a Message Preview

Grab people’s attention by adding a text preview for your email newsletter.

Posted June 11, 2019

Reporting Dashboard - Quick Access to Top Used Reporting Tools

See a centralized view of all reports available across the various components in PeopleVine.

Posted June 10, 2019

Customer Demographics Dashboard - See Age and Gender Stats for Your People + Members

Get a breakdown of the gender and age group your people and members fall into.

Posted June 10, 2019

Event Registrations, Schedule Bookings and Accepting Offers Are Now 1-Click

When someone clicks on the call to action when booking a room, appointment, registering for an event or accepting an offer, the item will immediately be added to the user's account if they are logged in.

Posted June 6, 2019

Configuring Your Payment Processor's Thresholds

Your credit card processor may have additional controls to manage fraud. Follow these steps to ensure billing transactions aren't blocked.

Posted June 3, 2019

Void and Reverse a Transaction that was Held for Review but Declined

Did your payment processor hold a transaction for review that failed? Follow these steps to reverse the actions.

Posted June 3, 2019

POS Integration - Aloha Overview for Member Experience (Card on File, House Credits, Loyalty and more)

Check out this article for an overview (and links to other articles) on how to use your Aloha and PeopleVine integration.

Posted May 29, 2019

See When Your Members/Subscribers Update their Payment on File

In an effort to help ensure you're subscriptions/memberships are being paid for, you can sort and see data related to their payment on file.

Posted May 28, 2019

How to set up a drop ship notification

Learn how to set up an email notification to be sent to a drop ship fulfillment partner when a product order is placed.

Posted May 28, 2019

HAPI Sample - Account Subscription Page

You can customize the /account/subscription/# page with the following HAPI sample.

Posted May 24, 2019

© PeopleVine 2019. Powered by PeopleVine. Terms of use | Privacy & cookies