javascriptjqueryvue.jsvuejs2vue-component

How can I display "Closed" or "Open" based on time in vue js html?


This is my json data to show the Hours of operation of the shop:

{
    "status": true,
    "data": {
        "pid": 1,
        "businessName": "ard",
        "services": "looking for passionate",
        "inventory": [],
        "workHr": "Monday :9:00AM to 5:00PM,Thuesday :9:00AM to 5:00PM,Wednesday :9:00AM to 5:00PM,Tuesday : 9:00AM to 5:00PM,Friday :9:00AM to 5:00PM,Saturday :9:00AM to 5:00PM,Sunday :9:00AM to 5:00PM"
    }
}

My vuejs code is:

<script>
    new Vue({
        el: '#feed' ,
        data: {
            data: [],
        },
        mounted() {
            this.$nextTick(function() {
                var self = this;
                var id = 1;
                console.log(id)
                $.ajax({
                    url: "https://n2s.herokuapp.com/api/post/get/"+{{pid}},
                method: "GET",
                    dataType: "JSON",
                    success: function (e) {
                    if (e.status == 1) {
                        self.data = e.data;
                        console.log(e.data)

                        const workHour = e.data.workHr.split(',').map((val) => {
                            const obj = val.split(':');
                        const time = val.replace(`${obj[0]}:`, '');
                        return {
                            day: obj[0],
                            time,
                        }
                    });
                    }
                    else
                    {
                        console.log('Error occurred');}
                }, error: function(){
                    console.log('Error occurred');
                }
            });
            })
        },
    })
</script>

I display today's hours of operations using the following code:

<div v-for="(item,key) in data.workHr" :key="key">
  <span v-if="new Date().getDay()-1==key">  <img src="/static/assets/img/timer.png">Today :  {{item.time}}</span>    
 </div>

In addition to their hours of operation, I also need to display "Closed" or "Open" based on whether it is within their working hours or not. How can I implement this?


Solution

  • First of all, your JSON schema seems incorrect due to some typo mistake. I fixed the JSON schema and hardcoded it in the code and remove the AJAX call to make the code workable. Hope you can replace it will AJAX call by yourself.

    Explanation

    I have used two libraries to manipulate date/time. First one is momentjs and other one is it's plugin moment-range. Then, I have formatted your dates in JavaScript instead of doing it on template and used range method to calculate the OPENED and CLOSED status. I have also added parseTime function to parse the time for handling AM/PM.

    window['moment-range'].extendMoment(moment);
    
    function parseTime(time, format) {
      var add12 = false;
      if (time.indexOf('PM') > -1) {
        add12 = true;
      }
      time = moment(time.replace('AM', '').replace('PM', ''), 'hh:mm');
      if (add12) {
        time.add(12, 'hours')
      }
      return time;
    }
    
    new Vue({
      el: '#feed',
      data: {
        data: [],
      },
      mounted() {
        this.$nextTick(function() {
          var self = this;
          var id = 1;
          self.today_open = false;
          var e = {
            "status": true,
            "data": {
              "pid": 1,
              "businessName": "ard",
              "services": "looking for passionate",
              "inventory": [],
              "workHr": "Monday :9:00AM to 10:00PM,Tuesday :9:00AM to 5:00PM,Wednesday :9:00AM to 5:00PM,Thursday : 9:00AM to 5:00PM,Friday :9:00AM to 5:00PM,Saturday :9:00AM to 5:00PM,Sunday :9:00AM to 5:00PM"
            }
          }
          self.data = e.data;
          const workHour = e.data.workHr.split(',').map((val) => {
            const obj = val.split(':');
            const time = val.replace(`${obj[0]}:`, '');
            const time_from = time.split('to')[0].trim();
            const time_to = time.split('to')[1].trim();
            var timeWindow = moment.range(parseTime(time_from), parseTime(time_to));
            return {
              day: obj[0],
              time_from: parseTime(time_from).format('hh:mm A'),
              time_to: parseTime(time_to).format('hh:mm A'),
              today_open: timeWindow.contains(new Date())
            }
          });
          self.data.workHr = workHour
        });
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
    <script src="https://npmcdn.com/moment@2.14.1/moment.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/moment-range/3.0.3/moment-range.js"></script>
    
    
    <div id="feed">
      <div v-for="(item,key) in data.workHr" :key="key">
        <span v-if="new Date().getDay()-1==key">  Today :  {{item.time_from}} to {{item.time_to}} <span v-if="item.today_open">OPENED</span><span v-if="!item.today_open">CLOSED</span></span>
      </div>
    </div>