How to Display Opening Hours for Restaurants - P2 - Using Meta Box and Oxygen
Tags: tutorial, customfield, dynamicdata, oxygen
Published: 2023-02-28 02:19:40

In a website for booking restaurants, there will be a lot of different restaurants. Definitely, each restaurant has its own opening hours and you may want to create a section for the opening time for each one. So, in this next part of the series, we’re going to figure out <strong>how to add an opening hours section into the singular page</strong> by <strong>Meta Box</strong> and <strong>Oxygen</strong>.

<!--more-->

This section will be the same as the last ones we created in the <a href="https://metabox.io/display-restaurant-opening-hours-p1-meta-box-gutenberg/">previous post</a>.

<img class="aligncenter" src="https://i.imgur.com/NjSFCse.png" alt="Example of opening hours section" width="1000" height="700" />
<h2>Before Getting Started</h2>
In this case, I want to put the opening hours section for a particular restaurant. And each restaurant including its own information will be displayed on a singular page. So, all the detailed information about the restaurants’ working time will be saved in custom fields stored in the post containing the restaurants’ information.

We’ll display some extra information such as time slots for each day, and we'll use custom fields. So, we need <a href="https://metabox.io/">Meta Box plugin</a> to have a framework to create them. It’s free on <a href="https://wordpress.org/plugins/meta-box/">wordpress.org</a>. We also need additional Meta Box advanced features, which are accessible in the following extensions:
<ul>
 	<li><a href="https://metabox.io/plugins/meta-box-builder/">Meta Box Builder</a>: this premium extension of Meta Box provides an intuitive UI in the back end to create and configure custom fields without using code;</li>
 	<li><a href="https://metabox.io/plugins/meta-box-group/">Meta Box Group</a>: this extension helps to arrange fields into groups;</li>
 	<li><a href="https://metabox.io/plugins/meta-box-conditional-logic/">Meta Box Conditional Logic</a>: this premium extension allows you to create rules to control the display of the fields.</li>
</ul>
Finally, <a href="https://oxygenbuilder.com/">Oxygen Builder</a>. Remember to use the 3.9 version or upper to have the native integration with Meta Box.
<h2>Create a Custom Post Type</h2>
If you read the <a href="https://metabox.io/display-restaurant-opening-hours-p1-meta-box-gutenberg/">previous post</a> in this series, you can skip this step. In the event that you haven’t had a post type yet, just create a new one as usual.

Go to <strong>Meta Box &gt; Post Types</strong>.

<img class="aligncenter" src="https://i.imgur.com/Axbn3XD.png" alt="Create a custom post type" width="1002" height="590" />
<h2>Create Custom Fields</h2>
This step is the same as what I showed in the <a href="https://metabox.io/display-restaurant-opening-hours-p1-meta-box-gutenberg/">previous post</a> about displaying opening hours.

Go to <strong>Meta Box &gt; Custom Fields &gt; Add New</strong> to create a new field group. Then, add custom fields with the structure like this:
<table style="height: 2117px;" width="1170">
<thead>
<tr>
<th><b>Name</b></th>
<th><b>ID</b></th>
<th><b>Type</b></th>
<th><b>Options</b></th>
<th><b>Condition</b></th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="font-weight: 400;">Choose an option</span></td>
<td><span style="font-weight: 400;">choose_an_option</span></td>
<td><span style="font-weight: 400;">select</span></td>
<td><span style="font-weight: 400;">1. all_days_are_the_same</span>

<span style="font-weight: 400;">2. difference_between_weekdays_and_weekend</span>

<span style="font-weight: 400;">3. custom</span></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">All days have the same opening hours</span></td>
<td><span style="font-weight: 400;">all_days_have_the_same_opening_hours</span></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when:</span>

<span style="font-weight: 400;">the </span><i><span style="font-weight: 400;">choose_an_option</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">all_days_are_the_same</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Type of opening hours</span></td>
<td><span style="font-weight: 400;">type_of_opening_hours</span></td>
<td><span style="font-weight: 400;">select</span></td>
<td><span style="font-weight: 400;">1. open_all_day</span>

<span style="font-weight: 400;">2. close_all_day</span>

<span style="font-weight: 400;">3. by_appointment_only</span>

<span style="font-weight: 400;">4. enter_hours</span></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Choose time slots</span></td>
<td><span style="font-weight: 400;">choose_time_slots</span></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">type_of_opening_hours</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">enter_hours</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Start time</span></td>
<td><span style="font-weight: 400;">start_time</span></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">End time</span></td>
<td><span style="font-weight: 400;">end_time</span></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Weekdays</span></td>
<td><span style="font-weight: 400;">weekdays</span></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">choose_an_opton</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">difference_between_weekdays_and_weekend</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Type of opening hours</span></td>
<td><span style="font-weight: 400;">type_of_opening_hours</span><b>_weekdays</b></td>
<td><span style="font-weight: 400;">select</span></td>
<td><span style="font-weight: 400;">1. open_all_day</span>

<span style="font-weight: 400;">2. close_all_day</span>

<span style="font-weight: 400;">3. by_appointment_only</span>

<span style="font-weight: 400;">4. enter_hours</span></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Choose time slots</span></td>
<td><span style="font-weight: 400;">choose_time_slots</span><b>_weekdays</b></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">type_of_opening_hours_weekdays</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">enter_hours</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Start time</span></td>
<td><span style="font-weight: 400;">start_time</span><b>_weekdays</b></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">End time</span></td>
<td><span style="font-weight: 400;">end_time</span><b>_weekdays</b></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Weekend</span></td>
<td><span style="font-weight: 400;">weekend</span></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">choose_an_opton</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">difference_between_weekdays_and_weekend</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Type of opening hours</span></td>
<td><span style="font-weight: 400;">type_of_opening_hours</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">select</span></td>
<td><span style="font-weight: 400;">1. open_all_day</span>

<span style="font-weight: 400;">2. close_all_day</span>

<span style="font-weight: 400;">3. by_appointment_only</span>

<span style="font-weight: 400;">4. enter_hours</span></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Choose time slots</span></td>
<td><span style="font-weight: 400;">choose_time_slots</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">type_of_opening_hours_weekend</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">enter_hours</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Start time</span></td>
<td><span style="font-weight: 400;">start_time</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">End time</span></td>
<td><span style="font-weight: 400;">end_time</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Monday</span></td>
<td><span style="font-weight: 400;">monday</span></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">choose_an_option</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">custom</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Type of opening hours</span></td>
<td><span style="font-weight: 400;">type_of_opening_hours</span><b>_monday</b></td>
<td><span style="font-weight: 400;">select</span></td>
<td><span style="font-weight: 400;">1. open_all_day</span>

<span style="font-weight: 400;">2. close_all_day</span>

<span style="font-weight: 400;">3. by_appointment_only</span>

<span style="font-weight: 400;">4. enter_hours</span></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Choose time slots</span></td>
<td><span style="font-weight: 400;">choose_time_slots</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">group</span></td>
<td></td>
<td><span style="font-weight: 400;">display only when: the </span><i><span style="font-weight: 400;">type_of_opening_hours_monday</span></i><span style="font-weight: 400;"> field = the </span><i><span style="font-weight: 400;">enter_hours</span></i><span style="font-weight: 400;"> option</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Start time</span></td>
<td><span style="font-weight: 400;">start_time</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">End time</span></td>
<td><span style="font-weight: 400;">end_time</span><b>_weekend</b></td>
<td><span style="font-weight: 400;">time picker</span></td>
<td></td>
<td></td>
</tr>
<tr>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
</tr>
<tr>
<td><span style="font-weight: 400;">Sunday</span></td>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
<td><span style="font-weight: 400;">…</span></td>
</tr>
</tbody>
</table>
As you saw in the table above, the first field is a <strong>Select</strong> field and there are 3 options that I filled in the <strong>Choice</strong> box as below.

<img class="aligncenter" src="https://i.imgur.com/cQKTi1W.png" alt="Fill the information in the Choice box" width="1000" height="646" />

These 3 options will be used to set the display rule of other group fields.

To set conditions to groups, for example, with the <strong>All days have the same opening hours</strong> group. Go to the <strong>Advanced</strong> tab, and then set the rule in the <strong>Conditional Logic</strong> section like this:

<img class="aligncenter" src="https://i.imgur.com/LFwZofk.png" alt="Set the rule in the Conditional Logic" width="1000" height="647" />

This rule means this group will be displayed when the <strong>Choose an Option</strong> field is selected as <strong>All days have the same opening hours</strong> option which has the value is <strong>all_days_are_the_same</strong>.

Similarly, if the <strong>Choose an Option</strong> field is chosen as the <strong>Difference between weekdays and weekend</strong> option, all the subfields of the <strong>Weekdays</strong> and <strong>Weekend</strong> group will be displayed. Or if the <strong>Choose an Option</strong> field is selected as the <strong>Custom</strong> option, the group fields for every day in a week will be shown up. That’s the concept of how to create fields.

<img class="aligncenter" src="https://i.imgur.com/giCpWKz.png" alt="Concept of how to create fields" width="1000" height="653" />

<img class="aligncenter" src="https://i.imgur.com/jnj7F10.png" alt="All the subfields of the Weekdays and Weekend group will be displayed" width="1000" height="653" />

In each group field, I also have subfields with the same structure.

The <strong>Type of Opening Hours</strong> field is select field. I have 4 options in the <strong>Choice</strong> box:
<ul>
 	<li>Open All day;</li>
 	<li>Close All day;</li>
 	<li>By Appointment Only;</li>
 	<li>Enter Hours.</li>
</ul>
<img class="aligncenter" src="https://i.imgur.com/qxDVyAH.png" alt="Fill in the information in the Choice box" width="1000" height="529" />

The second subfield is a Group field named Choose Time Slots. Inside it, there are two subfields: <strong>Start Time</strong> and <strong>End Time</strong>.

If the restaurant has multiple opening hours, you can choose <strong>Enter Hours</strong> to display the <strong>Start Time</strong> and <strong>End Time</strong> field in the <strong>Choose Time Slots</strong> group. So, I will set the rule for this group like this:

<img class="aligncenter" src="https://i.imgur.com/XmK1LWE.png" alt="Set the rule for the group field" width="1000" height="626" />

In case the restaurant opens in multiple time slots, we’ll need this group to be cloneable. So, I tick this box as below:

<img class="aligncenter" src="https://i.imgur.com/9JYVLp9.png" alt="Set the group to be cloneable" width="1000" height="415" />

After creating all the fields, go to the <strong>Settings</strong> tab of the field group, choose <strong>Location</strong> as <strong>Post Type</strong>, and select <strong>Restaurant</strong> to apply these fields to this post type.

<img class="aligncenter" src="https://i.imgur.com/jpmKrvm.png" alt="Set Location for the created fields" width="1000" height="399" />

Publish this field group and go to the post editor in <strong>Restaurant</strong>, you will see the custom fields here.

<img class="aligncenter" src="https://i.imgur.com/E9vxsR5.gif" alt="The created fields appear in the Post editor" width="1000" height="562" />

They work exactly like the rule we set.
<h2>Display the Fields’ Value</h2>
We’ll display the opening hours section using Oxygen. If you’ve had a template created by Oxygen for the Restaurant singular page, just go and edit it.

In the event you haven't had one, go to <strong>Oxygen &gt; Template &gt; Add New Template</strong> to create a new one.

<img class="aligncenter" src="https://i.imgur.com/ESq9hMo.png" alt="Create a new template" width="1000" height="560" />

Here, I’ve already had it. So, I just click <strong>Edit with Oxygen</strong>.

Next, add a new <strong>Div</strong> component.

<img class="aligncenter" src="https://i.imgur.com/dZSFZnz.png" alt="Add a new Div component" width="1000" height="561" />

In this practice, it includes some complex conditions to choose which fields will be got the value from. However, Oxygen hasn’t supported logic to choose which field yet, we need to use code in this practice. So, I will add a <strong>Code Block</strong> component.

<img class="aligncenter" src="https://i.imgur.com/okuDlLE.png" alt="Add a Code Block component" width="1000" height="654" />

Then, choose the <strong>PHP&amp;HTML</strong> and you will see a space to add code.

<img class="aligncenter" src="https://i.imgur.com/7JpbFqf.png" alt="Choose the PHP&amp;HTML" width="1000" height="654" />

<img class="aligncenter" src="https://i.imgur.com/XQMZTC7.png" alt="There will be a space to add code" width="1000" height="763" />

The code is quite long, so I put it in my Github <a href="https://github.com/wpmetabox/tutorials/blob/master/display-opening-hours-with-Oxygen/template.php">here</a>. You can refer to it for more details. The code is divided into several parts to get corresponding group data. Because of the same concept in all parts, I’ll explain a typical part to be more clear about the logic.
<pre>&lt;?php $options = rwmb_meta( 'choose_an_option' ); ?&gt;
&lt;?php if ( $options == "all_days_are_the_same" ): ?&gt;
    &lt;?php $same_days = rwmb_meta( 'all_days_have_the_same_opening_hours' ); ?&gt;
        &lt;?php $same_days_option = $same_days['type_of_opening_hours']; ?&gt;
        &lt;?php $choose_time_slots = $same_days['choose_time_slots'] ?&gt;
        &lt;?php if ( $same_days_option == "enter_hours" ): ?&gt;
            &lt;?php foreach ( $choose_time_slots as $time_slots ): ?&gt;
                &lt;?php echo $time_slots['start_time'] ?&gt;
                &lt;?php echo $time_slots['end_time'] ?&gt;
            &lt;?php endforeach; ?&gt;
        &lt;?php else: ?&gt;
            &lt;?php 
            $select_field = isset( $same_days['type_of_opening_hours'] ) ? $same_days['type_of_opening_hours'] : '';
            $group_field = rwmb_get_field_settings( 'all_days_have_the_same_opening_hours' );
            foreach ( $group_field['fields'] as $field ) {
                if ( empty( $field['options'] ) ) {
                    continue;
                }
            ?&gt;
            &lt;?php if($field['options'][$select_field]): ?&gt;
                &lt;?= $field['options'][$select_field]; ?&gt;
            &lt;?php endif; ?&gt;
            &lt;?php <i><span style="font-weight: 400;">} </span></i><i><span style="font-weight: 400;">?&gt;
        &lt;?php endif; ?&gt;</span></i></pre>
Let’s get through each line with me.
<pre>&lt;?php $options = rwmb_meta( 'choose_an_option' ); ?&gt;</pre>
I created a variable to get the value of the field <strong>Choose an Option</strong> which has the <strong>ID</strong> is <em>choose_an_option</em>. We will create a condition based on the returned value to decide which fields will be got the value from.
<pre>&lt;?php if ( $options == "all_days_are_the_same" ): ?&gt;
&lt;?php $same_days = rwmb_meta( 'all_days_have_the_same_opening_hours' ); ?&gt;</pre>
If the returned value is the first option, we will get the value of <strong>All days have the same opening hours</strong> group.
<pre>&lt;?php $same_days_option = $same_days['type_of_opening_hours']; ?&gt;
&lt;?php $choose_time_slots = $same_days['choose_time_slots'] ?&gt;</pre>
I also have 2 following variables that obtain the value of two fields: <strong>Type of Opening Hour</strong> and <strong>Choose Time Slots</strong>. They are the subfields of the <strong>All days have the same opening hours</strong> group.

Since the <strong>Type of Opening Hour</strong> is a <strong>Select</strong> field with some options as the image below, based on the returned value of this field, we’ll get value from the <strong>Choose Time Slots</strong> group or not.
<pre>&lt;?php if ( $same_days_option == "enter_hours" ): ?&gt;
    &lt;?php foreach ( $choose_time_slots as $time_slots ): ?&gt;
        &lt;?php echo $time_slots['start_time'] ?&gt;
        &lt;?php echo $time_slots['end_time'] ?&gt;
    &lt;?php endforeach; ?&gt;</pre>
If the returned value of the <strong>Type of Opening Hour</strong> field is <strong>Enter hours</strong>, we’ll display the value from the <strong>Choose Time Slots</strong> group field with its subfields: <strong>Start Time</strong> and <strong>End Time</strong> fields. Since the <strong>Choose Time Slots</strong> group is cloneable, we have a loop here.
<pre>&lt;?php 
$select_field = isset( $same_days['type_of_opening_hours'] ) ? $same_days['type_of_opening_hours'] : '';
$group_field = rwmb_get_field_settings( 'all_days_have_the_same_opening_hours' );
    foreach ( $group_field['fields'] as $field ) {
        if ( empty( $field['options'] ) ) {
            continue;
        }
?&gt;
    &lt;?php if($field['options'][$select_field]): ?&gt;
        &lt;?= $field['options'][$select_field]; ?&gt;
    &lt;?php endif; ?&gt;
&lt;?php } ?&gt;</pre>
For other options in the <strong>Type of opening hours</strong> field, the above is used to display the label of that selected option.

That's the end of the first section, corresponding to the first option of the <strong>Choose an Option</strong> field.

If separate days have different opening hours, call the values from the remaining groups.
The structure of those groups is the same as the <strong>All days have the same opening hours</strong> group, so just simply follow the same logic in the code.

This section on the page is now displayed like this because this code is for getting data from custom fields only.

<img class="aligncenter" src="https://i.imgur.com/Ky5uvnC.png" alt="The section of the page will displayed like this" width="1000" height="735" />

To have the display with some other texts as the demo, I’ll add some heading, div tags and class for easier styling later. I’ve uploaded the code on <a href="https://github.com/wpmetabox/tutorials/blob/master/display-opening-hours-with-Oxygen/template.php">Github</a>, you can refer to it.

Now, all the time slots with some additional texts are shown in the section already.

<img class="aligncenter" src="https://i.imgur.com/GAkDggx.png" alt="All the time slots with some additional texts are shown" width="1000" height="757" />

However, it doesn’t look as beautiful as I want. So, I will add some CSS to style this section in the next step.
<h2>Style the Section</h2>
For styling, you can go back to the Oxygen visual builder and style each component if any.
In this case, I‘ll add some CSS by going to <strong>Manage &gt; Stylesheet</strong> and <strong>Add Stylesheet</strong>.

<img class="aligncenter" src="https://i.imgur.com/0y9yroz.gif" alt="Style the Section" width="1000" height="562" />
This is the CSS that I’ve used:
<pre>.container.detail-restaurant .opening-hours {
max-width: 300px;
margin: 0 auto;
width: 100%;
}

.container.detail-restaurant .opening-hours h2 {
margin: 0 0 10px;
text-align: center;
border: 4px solid rgba(231,57,72,.85);
border-right: 0;
border-left: 0;
}

.container.detail-restaurant .detail-schedule .date-time {
display: flex;
width: 100%;
justify-content: space-between;
flex-wrap: wrap;
align-items: baseline;
}

.container.detail-restaurant .detail-schedule .date-time .hour .starting-hour:after{
content: '-';
margin: 0 5px;
}

.container.detail-restaurant .detail-schedule .date-time .hour .time-slot {
display: flex;
}

.container.detail-restaurant .detail-schedule .date-time .date {
font-weight: 700;
font-size: 15px;
}

.container.detail-restaurant .detail-schedule {
display: flex;
flex-wrap: wrap;
justify-content: center;
border-bottom: 4px solid rgba(231,57,72,.85);
padding-bottom: 10px;
}

</pre>
Let’s see how the opening hour section displays on the frontend. It’s much more beautiful, isn't it?

<img class="aligncenter" src="https://i.imgur.com/NjSFCse.png" alt="The final result" width="1000" height="700" />

To refer to all the code that I used, you can visit here.
<h2>Last Words</h2>
We’ve gone through all the procedures to display the Opening Hours section using Meta Box plugin and Oxygen Builder. Try it out and let us know how it goes in the comment section. If you have projects using Meta Box and Gutenberg, refer to our <a href="https://metabox.io/display-restaurant-opening-hours-p1-meta-box-gutenberg/">prior post</a> in this series. Or if you have any tutorial suggestions, feel free to leave a comment. Thank you for reading. Best of luck!