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'
})