JSFiddle - React, Tailwind, and code Playground

by samonela

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.1/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.3.1/vuex.min.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.1.3/firebase-database.js"></script>
<div id="app" class="container">
  <list-messages></list-messages>
  <add-message></add-message>
</div>

<template id="list-messages">
  <ul class="list-messages">
    <li v-for="message in messages">
      <span>{{message.time}}</span> {{ message.text }}
    </li>
  </ul>
</template>

<template id="add-message">
  <div class="add-message">
    <label for="message">Add new:</label>
    <input id="message" @keyup.enter="sendMsg" v-model="message">
    <button @click="sendMsg">Send</button>
  </div>
</template>

CSS

html, body {
  margin: 0;
  height: 100%;
}
.container {
  min-height: 100%;
  position: relative;
}
.list-messages {
  position: absolute;
  box-sizing: border-box;
  width: 100%;
  top: 10px;
  margin: 0;
  padding: 10px;
  list-style: none;
}
.list-messages span {
  color: lightblue;
}
.add-message {
  text-align: center;
  position: absolute;
  width: 100%;
  bottom: 10px;
}

JavaScript

(function() {
var uid = null

var firebaseConfig = {
  apiKey: "AIzaSyDGYiab8xoIXIgbFSmLSwXubNL2T3Rr6AQ",
  authDomain: "first-steps-6abb2.firebaseapp.com",
  databaseURL: "https://first-steps-6abb2.firebaseio.com"
}

var store = new Vuex.Store({
  state: {
    messages: []
  },
  mutations: {
    addMessage (state, message) {
      state.messages.push(message)
      if (state.messages.length > 10) {
        state.messages.shift()
      }
    }
  }
})

var listMessages = {
  template: '#list-messages',
  data () {
    return {
      messages: this.$store.state.messages
    }
  }
}

var addMessage = {
  template: '#add-message',
  data () {
    return {
      message: ''
    }
  },
  methods: {
    sendMsg () {
      messages.push().set({
        uid: uid,
        content: this.message,
        timestamp: firebase.database.ServerValue.TIMESTAMP
      })
      this.message = ''
    }
  }
}

firebase.initializeApp(firebaseConfig)
firebase.auth().signInAnonymously()
firebase.auth().onAuthStateChanged(function (user) {
  if (user) { uid = user.uid }
})

new Vue({
  el: '#app',
  store,
  components: {
    'list-messages': listMessages,
    'add-message': addMessage
  }
})

var db = firebase.database()
var messages = db.ref('messages')
var query = messages.orderByChild('timestamp').limitToLast(10)

query.on('child_added', function (data) {
  store.commit('addMessage', {
    uid: data.val().uid,
    text: data.val().content,
    time: moment(data.val().timestamp).format('hh:mm:ss')
  })
})
})();