JSFiddle - React, Tailwind, and code Playground

by Marvin Ranyaole

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://vuejs.org/js/vue.js"></script>
<script src="https://cdn.rawgit.com/vuejs/vuex/cca2c4b19b7656ea4632d47c39640da68d94c239/dist/vuex.js"></script>
<div id="app">
  <learner v-for="learner in learners" :learner="learner"></learner>
</div>

<template id="learner-template">

  <div class="panel panel-default">
    <div class="panel-heading clearfix">
      <h4>{{learner.firstName}} {{learner.lastName}}</h4>
    </div>

    <div class="panel-body">
      <div class="col-md-12">
        Average: {{learner.average}}
      </div>
    </div>

    <div class="panel-footer clearfix">

      <reaction :learner="learner"></reaction>

    </div>

  </div>

</template>

<template id="reaction-template">

  <button type="button" @click="react" class="btn btn-default btn-circle btn-lg pull-right"> {{reaction}} <i class="glyphicon glyphicon-star"></i></button>


</template>

JavaScript

const store = new Vuex.Store({
  state: {
    learners: [{
        id: 001,
        firstName: "Marvin",
        lastName: "Ranyaole",
        average: 99,
        sponsors: [{
          reaction: "unfollow",
          id: "01"
        }]
      }

    ],
    beneficiaries: [],
  },
  mutations: {
    follow(state, payload) {
 
    		 const learner = state.learners.find(function(learner){

            return learner.id == payload.learnerId;

          })
          
          if(learner.sponsors.length > 0){

              const sponsor = learner.sponsors.find(function(sponsor){

                return sponsor.id == payload.id;

              });

            //this does not update the related component(s)
            sponsor.reaction = "follow";

   
          }else{

            learner.sponsors.push({

              id: details.id,
              reaction: "follow",

            });

      		}

          // this update the related
          state.beneficiaries.push(learner);

      },
      unfollow(state, payload) {
      
      		const learner = state.learners.find(function(learner){

            return learner.id == payload.learnerId;

          })
          
          const sponsor = learner.sponsors.find(function(sponsor){

            return sponsor.id == payload.id;

          })

      		sponsor.reaction = "unfollow";

      			state.beneficiaries.splice(state.beneficiaries.indexOf(learner,1));

      },
  },
  actions: {
    react({
      commit
    }, payload) {

      if (payload.reaction === 'follow') {
        commit('follow', payload)
      } else {
        commit('unfollow', payload)
      }

    }
  }
})


Vue.component('learner', {
  props: ['learner'],
  template: '#learner-template'
});


Vue.component('reaction', {
  props: ['learner'],
  template: '#reaction-template',
  data: {

    total:  parseInt(0),
    reaction: 'Follow',
  },
  
  computed: {

    reaction: {


      get: function() {

        	for(var i=0;...