JSFiddle - React, Tailwind, and code Playground

by denniswaltermartinez

HTML

<div id="app">
  <week></week>
</div>

SCSS

*,
*:before,
*:after {
  box-sizing: inherit;
}

html {
  box-sizing: border-box;
  font-size: 62.5%;
}

body {
  font-family: Arial;
  font-size: 1.4rem;
  padding: 2rem;
  background: #f1f3f5;
  color: #495057;
}

.week {
  width: 100%;
  display: flex;
}

.day {
  display: flex;
  flex-direction: column;
  flex-basis: 20%;
  padding: 2rem;
  background: #eee;
}

.day-name {
  margin-bottom: 2rem;
}

.events {
  flex-grow: 1;
}

.event {
  padding: 1rem;
  background: #4dadf7;
  color: white;
  cursor: move;
  
  &:not(:last-child) {
    margin-bottom: 1rem;
  }
}

[droppable] {
  border: 0.1rem dashed gray
}

JavaScript

// Event bus
const bus = new Vue()

Vue.component('week', {
	data: () => ({
  	days: {
      monday: [
      	'Soccer Practice',
        'Go to the Zoo'
      ],
      tuesday: [],
      wednesday: [],
      thursday: ['Gaming'],
      friday: [],
      saturday: [],
      sunday: []
    }
  }),
  methods: {
  	update(previousDay, newDay, event) {
      const events = [...this.days[previousDay]]
      const index = events.findIndex(e => e === event)
      
      events.splice(index, 1)
      
      this.days[previousDay] = [...events]
      this.days[newDay] = [...this.days[newDay], event]
    }
  },
  mounted() {
  	bus.$on('update',this.update)
  },
	template: `
  	<div class="week">
    	<day v-for="[name, events], index in Object.entries(this.days)" :key="index" :name="name" :events="events">{{ name }}</day>
    </div>
  `
})

Vue.component('day', {
	props: ['name', 'events'],
  data: () => ({
  	draggedFrom: ''
  }),
  methods: {
  	onDrop(e) {
			console.log(e)
    	const { day } = e.target.dataset
      const droppedText = e.dataTransfer.getData('text')
      const previousDay = e.dataTransfer.getData('day')
      
      // Bug if target is anything but UL
      bus.$emit('update', previousDay, day, droppedText)
    },
    
    onDragOver(e) {
    	// e.dataTransfer.dropEffect = 'move'
    }
  },
	template: `
  	<div class="day">
    	<h5 class="day-name">{{ name }}</h5>
      
      <ul class="events" @dragover.prevent="onDragOver" @drop="onDrop" :data-day="name">
      	<event v-for="event, index in events" :key="index" :text="event" :day="name"></event>
      </ul>
    </div>
  `
})

Vue.component('event', {
	props: ['day', 'text'],
  methods: {
  	onDragStart(e) {
    	e.dataTransfer.setData('text', this.text)
      e.dataTransfer.setData('day', this.day)
    	e.dropEffect = 'move'
    }
  },
	template: `
  	<li class="event" draggable @dragstart="onDragStart">
    	<span>{{ text }}</span>
    </li>
  `
})

new Vue({
	el: '#app'
})