Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

talel's avatar
Level 16

Dailey schedule time-grid/timeline view

Hello All!

I am working on a new project where there is a daily schedule with a time-grid view. An example of what it looks like:

The way I got it to work right now is as follow:

 <Calendar :events="this.events" :from="8" :to="22" />
...

<script>
    import Calendar from '../Calendar/Show.vue'

    export default {
        components: {
            Calendar,
        },
        data() {
            return {
                events: [
                    {
                        title: 'Event title',
                        content: '08:00-09:15',
                        start: '2021-06-27T08:00:00-04:00',
                        end: '2021-06-27T09:15:00-04:00',
                    },
                ],
            }
        },
    }
</script>

In the Calendar component I create a range of hours based on the from and to props, and for each, I create an Hours component and for each event I check the start time if matching an hour on the Hours component to push the event data into it.

            <Hours v-for="(hour, index) in hours" :time="hour" />

...

        created: function () {
            this.moment = extendMoment(Moment)
            let day_range = this.moment.range(
                this.moment().startOf('day').hours(this.from),
                this.moment().startOf('day').hours(this.to)
            )
            this.hours = Array.from(day_range.by('hours', { step: 1 }))

this.events.forEach((e) => {
                this.hours.forEach((time) => {
                    if (Moment(time).isSame(e.start)) {
                        if (typeof time.data == 'undefined') {
                            time.data = { 0: e }
                        } else {
                            let index = Object.keys(time.data).length
                            time.data[index++] = e
                        }
                    }
                })
            })

As well, I have the "now" indicator which show the current time. It just check how many hours past since the beginning of the day and do a weird calculation for a margin-top value for the style attribute on the indicator div .

currentTime: function () {
                let inHours = Number(this.moment().diff(this.moment().startOf('day').hours(this.from), 'hours'))
                let inMinutes = Number(this.moment().format('m'))
                return 'margin-top:' + (inHours * 62 + inMinutes + 48).toFixed(2) + 'px;'
            },

I am looking for a smart way for all of that, what I got right now is just the easiest way I could get it to work..I am looking to refactor it or more correctly looking for the right way I should go about it.

Thank you in advance for every idea and suggestion, Tal

0 likes
1 reply
bobbybouwmann's avatar

If you look for example at Google Calendar they basically have one div that displays the calendar. This div is relative. For each item on the calendar, they have a calculation to place it absolutely on the div using top and left. This way you can easily output a line on any pixel you want, also you can more easily work with half hours and quarters.

Calculations even become easier when you set the height between an hour to a fixed size of for example 20 pixels. Now you know that if something is 4 hours from now you simply can do 4 * 20 which is the top of the div of the item.

Please or to participate in this conversation.