<div id="app" v-cloak>
    <div class="wrapper">
        <div class="header layout-row">
            <h5 class="time padding">Time</h5>
            <h5 class="activity padding">Activity</h5>
        </div>
        <div class="content">
            <div class="tracker">
                <i class="material-icons">keyboard_arrow_left</i>
            </div>
            <div class="time-tracker">
                <div v-for="interval in intervals" class="time-cell padding">
                    {{interval }}
                </div> 
            </div>
            <draggable @end="onDragEnd" :list="activityList" :options="{group:'people', animation: 150, handle: '.drag-handle'}" class="activities flex">
                <div v-for="activity in activityList" class="activity-cell padding" v-bind:class="activity.color">
                    <a class="waves-effect waves-dark btn-flat drag-handle" @click=""><svg v-bind:class="{'white-fill': activity.color === 'white'}" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"/></svg>
</a> 
                    <span class="col s8" v-bind:class="{'white-text': activity.color !== 'white'}">{{activity.name }}</span>
                    <span class="flex"></span>
                    <a class="waves-effect waves-dark btn-flat" @click="edit(activity)"><i class="material-icons">edit</i></a> 
                </div>
            </draggable> 
        </div>
    </div>
    
    <div id="edit-activity" class="modal">
        <div class="modal-content">
            <h4>Edit Activity</h4>
            <div class="row">
                <div class="input-field col s12">
                    <input id="modelActivityText" type="text" v-model="modalActivity.name" @keyup.enter="closeModal">
                    <label for="modelActivityText">Activity</label> 
                </div>
            </div>
            <div class="row"> 
                <h5 class="col s8">Color Select</h5>
                <div class="col s4 color-select" v-bind:class="modalActivity.color"></div> 
            </div>
            <div class="row">
                <div class="waves-effect red col s4 color-select" @click="changeModalActivityColor('red')"></div>
                <div class="waves-effect purple col s4 color-select" @click="changeModalActivityColor('purple')"></div>
                <div class="waves-effect deep-purple col s4 color-select" @click="changeModalActivityColor('deep-purple')"></div>
                <div class="waves-effect indigo col s4 color-select" @click="changeModalActivityColor('indigo')"></div>
                <div class="waves-effect blue col s4 color-select" @click="changeModalActivityColor('blue')"></div>
                <div class="waves-effect light-blue col s4 color-select" @click="changeModalActivityColor('light-blue')"></div>
                <div class="waves-effect teal col s4 color-select" @click="changeModalActivityColor('teal')"></div>
                <div class="waves-effect green col s4 color-select" @click="changeModalActivityColor('green')"></div>
                <div class="waves-effect orange col s4 color-select" @click="changeModalActivityColor('orange')"></div>
                <div class="waves-effect brown col s4 color-select" @click="changeModalActivityColor('brown')"></div>
                <div class="waves-effect grey col s4 color-select" @click="changeModalActivityColor('grey')"></div>
                <div class="waves-effect blue-grey col s4 color-select" @click="changeModalActivityColor('blue-grey')"></div>
            </div>
        </div>
        <div class="modal-footer">
             <a class="waves-effect waves-dark btn-flat" @click="closeModal">Close</a>
        </div> 
    </div>
</div>
$body-color: rgba(0,0,0,.8);
$app-color: #34495E;
$row-height: 2.5rem;
$borders-color: rgba(0,0,0,.4);

[v-cloak] { display:none; }

div {
    position: relative;
    box-sizing: border-box;
}
html {
    width: 100%;
    height: 100%;
    font-family: Roboto,Lato,sans-serif;
}
body {
    background-color: $body-color;
    margin: 0;
}
#app {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    .content {
        max-height: 90vh;
        overflow: auto;
        display: flex;
        flex-direction: row;
    }
    .wrapper {
        display: flex;
        flex-direction: column;
        background: white;
        margin: auto;
        max-width: 480px;
        width: 100%;
        border-radius: 0.25rem;
        box-shadow: 0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12);
        overflow: hidden;
    }
}

.padding {
    padding: 0.5rem;
}

.layout-row {
    display: flex;
    flex-direction: row;
}
.header {
    color: white;
    background: lighten($app-color, 10%);
    flex-shrink: 0;
    .time {
        width: 100px;
        text-align: center;
        margin: 0;
        border-right: solid 1px $borders-color;
        border-bottom: solid 1px $borders-color;
    }
    .activity {
        flex: 80;
        margin: 0;
        border-bottom: solid 1px $borders-color;
    }
}

.time-tracker {
    height: 100%;
}

.tracker {
    color: black;
    border-bottom: dotted 4px black;
    position: absolute;
    height: 2px;
    width: 96%;
    top: 70%;
    right: 0;
    z-index: 1;
    i {
        font-size: 40px;
        position: absolute;
        left: -28px;
        transform: translateY(-18px);
    }
}

.time-cell {
    width: 100px;
    color: white;
    background: $app-color;
    text-align: center;
    height: $row-height;
}

.activity-cell {
    .btn-flat {
        padding: 0 0.5rem;
    }
    height: $row-height;
    border: none;
    border-bottom: solid 1px $borders-color;
    display: flex;
    align-items: center;
    background: black;
    a.drag-handle {
        color: black;
        cursor: grab;
        margin-right: 0.5rem;
        height: 24px;
        width: 24px;
        padding: 0;
        svg {
            height: 100%;
            fill: white;
        }
        svg.white-fill {
            fill: black;
        }
    }
}

.color-select {
    height: 50px;
    transform: scale3d(.95,.85,1);
    box-shadow: 0 4px 5px 0 rgba(0,0,0,0.14),0 1px 10px 0 rgba(0,0,0,0.12),0 2px 4px -1px rgba(0,0,0,0.3);
}

.flex {
    flex:1;
}

@media only screen and (max-width: 500px) {
    #app {
        margin: 0.5rem;
        .wrapper {
            height: 100vh;
        }
        .content {
            flex: 1;
            max-height: none;
        }
    }
}
View Compiled
$(document).ready(function() {
    $('.modal').modal();
});

var save = function(data) {
    window.localStorage.setItem('save', JSON.stringify(data));
};

var app = new Vue({
    el: '#app',
    data: {
        modalActivity: {},
        intervals:[ ],
        activityList: []
    },
    watch: {
        modalActivity: {
            handler: function(val, oldVal) {
                this.activityList.forEach(function(activity) {
                    if (activity.name === this.modalActivity.name) {
                        this.modalActivity.color = activity.color;
                    }
                }, this);
                save(this.activityList);
            }, deep: true
        }
    },
    methods: {
        onDragEnd: function() {
            save(this.activityList);
        },
        edit: function(activity, event) {
            this.modalActivity = activity;
            $('#edit-activity').modal('open');
            $('#modelActivityText').get(0).focus();
            $('.modal label').addClass('active');
        },
        closeModal: function() {
            $('#edit-activity').modal('close');
        },
        changeModalActivityColor: function(color) {
            this.modalActivity.color = color;
            this.activityList.forEach(function(activity) {
                if (activity.name === this.modalActivity.name) {
                    activity.color = color;
                }
            }, this);
        }
    },
    created: function() {
        window.setInterval(function() {
            var currentTime = new Date();
            var height = 0;
            $('.time-tracker').children().each(function() {
                height += $(this).outerHeight();
            });
            var heightPercent = ( currentTime.getHours()*60+currentTime.getMinutes() )  / (24*60);
            $('.tracker').css('top', heightPercent*height + 'px');
            console.log(height, heightPercent);
        }, 1000);

        
        var date = new Date();
        for(var i = 0;i<24;i++) {
            date.setHours(i);
            date.setMinutes(0);
            var text = date.toLocaleString('en-US', { minute: 'numeric', hour: 'numeric', hour12: true });
            this.intervals.push(text);
        }
        try {
            this.activityList = JSON.parse(window.localStorage.getItem('save')) || [];
        } catch (e) {
            console.error(e);
            this.activityList = [];
        }

        if (this.activityList.length > 4) {
            return;
        }
        for(var i = 0;i<24;i++) {
            this.activityList.push({
                name: 'Empty',
                color: 'white'
            })
        }
    }
});

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/css/materialize.min.css
  2. https://cdn.rawgit.com/FortAwesome/Font-Awesome/master/css/font-awesome.min.css
  3. https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic
  4. https://fonts.googleapis.com/icon?family=Material+Icons

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js
  2. https://cdn.rawgit.com/vuejs/vue/dev/dist/vue.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.8/js/materialize.min.js
  4. https://cdn.rawgit.com/RubaXa/Sortable/master/Sortable.min.js
  5. https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/15.0.0/vuedraggable.min.js