Menu Form

The menu mock up for Tacofino

by James Doyle

HTML

<h3>New Menu</h3>
<form action="" method="" enctype="multipart/form-data">
  <div class="nested" v-for="m in menu">
    <label for="">
      <strong>Main Category (time or group)</strong>
      <input type="text" v-model="m.main_category">
    </label>
    <p><strong>Special</strong></p>
    <div class="nested" v-for="special in m.specials">
      <p><strong>Special {{ $index + 1 }}</strong></p>
      <label for="">
        Day
        <input type="text" v-model="special.day">
      </label>
      <label for="">
        Name
        <input type="text" v-model="special.name" v-uppercase="special.name">
      </label>
      <label for="">
        Description
        <input type="text" v-model="special.description">
      </label>
      <button type="button" v-if="m.specials.length > 1 && $index > 0" v-on:click.prevent="deleteFromArray(m.specials, $index)">Delete {{ $index + 1 }}</button>
    </div>
    <button type="button" v-on:click.prevent="addSpecial(m.specials)">Add Special</button>
    <p><strong>Menu Items</strong></p>
    <div class="nested" v-for="item in m.items">
      <p><strong>Group {{ $index + 1 }}</strong></p>
      <label for="">
        Food Group
        <input type="text" v-model="item.food_group">
      </label>
      <div class="nested" v-for="line in item.items">
        <p><strong>Item {{ $index + 1 }}</strong></p>
        <label for="">
          Name
          <input type="text" v-model="line.name" v-uppercase="line.name">
        </label>
        <label for="">
          Description
          <input type="text" v-model="line.description">
        </label>
        <label for="">
          Price
          <input type="number" v-model="line.price" min="1" max="99">
        </label>
        <label>
          Has Addons
          <input type="checkbox" value="1" v-model="line.has_addons">
          <br>
          <textarea placeholder="Item 3" rows="3" v-if="line.has_addons" v-model="line.addons"></textarea>
        </label>
        <button...

SCSS

.nested {
  border: 2px solid #CCC;
  margin-top: -2px;
  padding: 1rem 0.5rem;
  .nested {
    background: rgba(0,0,0,0.04);
  }
}

label {
  display: inline-block;
  width: 100%;
  margin: 0.5rem 0;
}

input[type="text"] {
  width: 300px;
}

textarea {
  width: 300px;
  border: 1px solid #CCC;
  resize: vertical;
}

JavaScript

Vue.config.debug = true;

Vue.directive('uppercase', {
  twoWay: true,
  bind: function() {
    this.handler = function() {
      this.set(this.el.value.toUpperCase());
    }.bind(this);
    this.el.addEventListener('input', this.handler);
  },
  unbind: function() {
    this.el.removeEventListener('input', this.handler);
  }
});

var app = new Vue({
  el: 'body',
  data: {
    menu: [{
      main_category: 'Lunch',
      specials: [{
        day: "Today’s Lunch Special",
        name: "FRIED CHICKEN TACO",
        description: "soy, sesame, salsa fresca, wakame, ginger, wasabi mayo"
      }],
      items: [{
        food_group: "Appetizers",
        items: [{
          name: "FRIED CHICKEN TACO",
          description: "",
          price: 5,
          has_addons: false,
          addons: ""
        }]
      }, {
        food_group: "Tacos",
        items: [{
          name: "FISH",
          description: "crispy ling cod, cabbage, chipotle mayo, salsa fresca",
          price: 6,
          has_addons: true,
          addons: "Guac 2\nExtra Sauce 2"
        }]
      }]
    }]
  },
  methods: {
    addMenuCategory: function() {
      var scaffold = {
        main_category: 'New Category',
        specials: [{
          day: "New Special",
          name: "",
          description: ""
        }],
        items: [{
          food_group: "Food Group",
          items: [{
            name: "MENU ITEM",
            description: "",
            price: 0,
            has_addons: false,
            addons: ""
          }]
        }]
      };
      this.menu.push(scaffold);
    },
    addMenuItem: function(items) {
      var scaffold = {
        food_group: "Food Group",
        items: [{
          name: "MENU ITEM",
          description: "",
          price: 0,
          has_addons: false,
          addons: ""
        }]
      };
      items.push(scaffold);
    },
    deleteFromArray: function(arr, index) {
      arr.splice(index, 1);
    },
    addSpecial:...