Ojorrones y Tazamorras

by Marcos F

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://fonts.googleapis.com/css?family=Roboto"></script>
<div id="app">
  <div class="conv">
    <div class="node" v-if="conv.text.length">
      <div class="image">
        <img :src="conv.char.avatar">
      </div>
      <div class="wrapper">
        <h3>{{conv.char.name}}</h3>
        <p>
          {{conv.char.bio}}
        </p>
        <transition name="transition-text">
          <div v-if="show.text">
            <div class="text" v-html="conv.text"></div>
            <ul class="options">
              <li v-for="option in conv.options" @click="option._command">{{option.text}}</li>
            </ul>
          </div>
        </transition>
      </div>
    </div>
    <transition name="transition-text">
      <div class="item-new" v-if="show.item">
        <h3><strong>{{show.item.name}}</strong> added</h3>
      </div>
    </transition>
  </div>
</div>

CSS

html {
  font-size: 80%;
}

body {
  margin: 0;
  background: #424863;
  color: white;
  font-family: 'Roboto', sans-serif;
}

ul {
  list-style: none;
  display: flex;
  margin: 0;
  padding: 0;
}

li {
  background: white;
  color: #2e354c;
  padding: 4px 10px;
  cursor: pointer;
  cursor: pointer;
  border-radius: 2px;
}

li+li {
  margin-left: 10px;
}

#app {
  padding: 10px;
}

.node {
  display: flex;
  background: #2e354c;
  padding: 16px;
  border-radius: 4px;
}

.node .image {
  width: 60px;
}

.node .image img {
  width: 100%;
  box-shadow: 0 2px 0 0 rgba(30, 34, 59, 0.5);
  border-radius: 4px;
}

.node .wrapper {
  padding-left: 20px;
	width: calc(100% - 80px);
}

.node .wrapper h3 {
  font-size: 1rem;
  padding: 0;
  margin: 0;
}

.node .wrapper p {
  padding: 0;
  margin: 0;
  font-size: 0.9rem;
  color: #979aa6;
}

.node .wrapper .text {
  padding: 10px 0;
  font-size: 1.2rem;
}

.item-new {
  display: inline-block;
  background: #eaeaea;
  color: #666;
  padding: 10px 16px;
  margin-top: 10px;
  border-radius: 4px;
}

.item-new h3 {
  font-size: 1rem;
  padding: 0;
  margin: 0;
}

.item-new h3 strong {
  color: #333;
}

.transition-text-enter-active {
  transition: all 1s ease;
}

.transition-text-enter {
  opacity: 0;
  transform: translateY(20px);
}

.transition-text-enter-to {
  opacity: 1;
  transform: translateY(0);
}

.transition-text-leave-active {
  transition: all .2s ease;
}

.transition-text-leave {
  opacity: 1;
  transform: translateY(0);
}

.transition-text-leave-to {
  opacity: 0;
  transform: translateY(20px);
}

JavaScript

var _vue = new Vue({
  el: '#app',
  data: {
    chars: {},
    inventory: {},
    conv: {
      char: false,
      text: '',
      options: []
    },
    show: {
      text: false,
      item: false
    }
  },
  mounted: function() {
    /* INI-Here goes the chars */
    this.char_create({
      'name': 'anorak',
      'avatar': 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQzLhaCL4X9MH1FzZhsiq_jpd4--l0SLPNyYg&usqp=CAU',
      'bio': 'abrigrate que hace fresco'
    });
    this.char_create({
      'name': 'el ano del calabozo',
      'avatar': 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRfue2_Pgq5Fo9W42jcEi9H_Jrg2HohRTGHtA&usqp=CAU',
      'bio': 'el apretón definitivo'
    });
    /* END-Here goes the chars */

    /* INI-Here goes the logic */
    this.char_say('anorak', 'es peligroso ir solo ...', [{
      'text': 'Coger espada',
      'command': () => {
        this.item_give({
          'name': 'Espada alargada'
        });
        return this.char_say('anorak', 'bien hecho');
      }
    }]).then((text) => {
      return this.char_say('anorak', 'algo más? que no se te olvide nada', [{
        'text': 'Coger una muda por si acaso',
        'command': () => {
          this.item_give({
            'name': 'Calzoncillos espaciales'
          });
          return this.char_say('anorak', 'En marcha');
        }
      }, {
        'text': 'Nunca llevé ropa interior',
        'command': () => {
          return this.char_say('anorak', 'En marcha');
        }
      }]);
    }).then((text) => {
      return this.char_say('anorak', 'Algo se mueve entre los arbustos');
    }).then((text) => {
      return this.char_say('el ano del calabozo', 'Eh!, idos a molestar a otra parte');
    });
    /* END-Here goes the logic */
  },
  methods: {
    char_create: function(charOB) {
      this.$set(this.chars, charOB.name, charOB);
    },
    char_say: function(name, text, options) {
      return new Promise((resolve, reject) => {
        if (!(name in...