(function () {
  'use strict';

  var _Root = {};

  _Root.attrs = {};

  _Root.allowFileDrop = function(cb){
    _Root.attrs.ondragover = function(e){
      e.preventDefault();
      };
    _Root.attrs.ondrop = function(e){
      e.preventDefault();  // don't open the file in the browser
      var files = [];
      
      // some browsers use `.items` and some use `.files`, so check for both:
      if (e.dataTransfer.items) {
        for (var i = 0; i < e.dataTransfer.items.length; i++) {
          if (e.dataTransfer.items[i].kind === 'file') {  // If dropped items aren't files, reject them
            files.push( e.dataTransfer.items[i].getAsFile() );
            }
          }
        }
      else {
        for (var i = 0; i < e.dataTransfer.files.length; i++) {
          files.push( e.dataTransfer.files[i] );
          }
        }
      for(var i=0, file=null; i<files.length; i++){
        file = files[i];
        cb(file);
        //console.log(file.name);
        }
      };
    };

  _Root.unallowFileDrop = function(){
    _Root.attrs.ondragover = null;
    _Root.attrs.ondrop = null;
    };

  var _Home = {};

  _Home.carousel_images = [
    {src: 'images/carousel1-960.jpg', description: 'Stylish Frames'},
    {src: 'images/carousel2-960.jpg', description: 'Piazza Optical'},
    {src: 'images/carousel3-960.jpg', description: 'Professional Optical Equipment'}
    ];

  var Carousel = function(){
  return {
  view: function(vnode){
    var images = vnode.attrs.images;
    var name = vnode.attrs.name;
    
    return m('.carousel', [
      images.map(function(image,index){
        return m('input.carousel-locator', {
          id: 'slide-'+index,
          type: 'radio',
          name: name,
          hidden: true,
          checked: (index===0 ? true : false)
          });
        }),
      m('.carousel-container', images.map(function(image, index){
        var prev_index = (index === 0 ? images.length-1 : index-1);
        var next_index = (index === images.length-1 ? 0 : index+1);
        return m('figure.carousel-item', [
          m('label.item-prev.btn.btn-action.btn-large', {
            "for": 'slide-'+prev_index
            }, [
              m('i.icon.icon-arrow-left')
              ]),
          m('label.item-next.btn.btn-action.btn-large', {
            "for": 'slide-'+next_index
            }, [
              m('i.icon.icon-arrow-right')
              ]),
          m('img.img-responsive.rounded', {
            src: image.src,
            alt: image.description
            })
          ]);
        })),
      m('.carousel-nav', images.map(function(image, index){
        return m('label.nav-item.text-hide.c-hand',{
          "for": 'slide-'+index 
          }, index.toString());
        })),
      ]);
  }
  };
  };

  var Home = function(){
    return {
      view: function(vnode){
        return m('.home', [
          //m('h1', "Piazza Optical Home Page"),
          m(Carousel, {images: _Home.carousel_images, name: 'home-carousel'})
          ]);
        }
      };
    };

  var AboutUs = function(){
    return {
      view: function(vnode){
        return m('.about-us', [
          m('h1.text-center', "About Us"),
          m('p', "Welcome to Piazza Optical, your number one source for all your optical needs. From frames and lenses to lab equipment and accessories, we are here to provide you with all these supplies while giving you personalized attention and customer service.  We're dedicated to making available products that rank the very best in the latest trends in frames and sunglasses, with a focus on quality of materials and craftsmanship at the lowest cost to aid you and your store/practice in achieving the most profits."),
          m('p', "Founded in 1995, Piazza Optical has come a long way from its beginnings in a tiny office in North Miami, FL. When we first started out, our passion for fashion forward frames became an obsession and drove us to scour the best factories of the world in our industry, and gave us the pillars to become a leader in the optical supplies business without losing the personal touch, highlighting honesty and integrity which sets us apart from the competition far and near. Such is the base of our company, and our honesty towards and respect for our customers is what keeps our worldwide  following at the top after all these years."),
          m('p', "We hope you enjoy our products as much as we enjoy offering them to you. If you have any questions or comments, please don't hesitate to contact us!"),
          m('p',''),
          m('p', "Bienvenidos a Piazza Optical la principal distribuidora de armazones ópticas, lentes oftálmicas y equipos de consultorio y de laboratorio. Estamos aquí para proveer a ópticas, distribuidores y oftalmólogos muchos de los artículos relacionados con su establecimiento, brindando a cada cliente atención personalizada y servicio al cliente. Estamos dedicados a poner a su disposición artículos ópticos de la más alta gama en las últimas tendencias de la moda en armazones y gafas de sol, poniendo especial enfoque en la calidad de materiales y mano de obra al menor costo para promover mayores ganancias para Ud. y su óptica."),
          m('p', "Fundada en 1995, Piazza Optical ha logrado una larga trayectoria desde nuestros comienzos en aquella modesta oficina en North Miami, FL. Desde el principio, nuestra pasión por la moda en óptica se tornó en una obsesión y nos impulsó a buscar y establecer una firme relación con las mejores fábricas de la industria, lo cual es el pilar para convertirnos en líderes en el ramo sin por ello perder el toque personal, permitiendonos brillar en honestidad e integridad que nos diferencia de la competencia lejana y cercana. Tal es la base de nuestra empresa, ya que nuestra honestidad y respeto por nuestros clientes es lo que hace que éstos se mantengan fieles a nuestra compañía despues de tantos años."),
          m('p', "Deseamos que disfruten de nuestros productos de la misma manera que nosotros disfrutamos ponerlos a vuestra disposición. Si tienen algún comentario o pregunta, por favor no duden en contactarnos!")
          ]);
        }
      };
    };

  var Events = function(){
    return {
      view: function(vnode){
        return m('.events', [
          m('h1.text-center', "Upcoming Events")
          ]);
        }
      };
    };

  var Policies = function(){
  return {
  view: function(vnode){
  return m('.policies', [
    m('h1.text-center', 'Policies'),
    m('h2', 'General Policies'),
    m('p', "All items are thoroughly inspected prior to shipping to insure customer receives a proper product."),
    m('p', "Warranty is limited to manufacturer’s defects only. Returned pieces will be inspected to determine eligibility for warranty."),
    m('p', "Our exclusive labels have 1 year manufacturer defect warranty from purchase date, not from dispensing date."),
    m('p', "Designer Brand names closeouts are only guaranteed for exchange in the unlikely event the piece is shipped defective (within 7 days of purchase)."),
    m('p', "Designer Brand names regular collections have 1 year warranty for manufacturers’ defects from the date of purchase."),
    m('p', "These prices are for online purchases only."),
    m('p', "Not all items available at all times."),
    m('h2', 'Refund Policy'),
    m('p', ''),
    m('h2', 'Privacy Policy'),
    m('p', '')
    ]);
  }};
  };

  var ContactUs = function(){
  return {
  view: function(vnode){
    return m('.contactus', [
      m('h1.text-center', 'Contact Us'),
      m('h3', ['Phone ', m('small', 'Customer Service & General Inquiries')]),
      m('p', '(305)-818-6786'),
      m('h3', 'Email'),
      m('p', 'silvano@piazzaoptical.com'),
      m('h3', 'Hours'),
      m('p', 'Mon-Fri 9:00-5:30'),
      m('h3', 'Address'),
      m('p', [
        '8200 NW 27th. Street',
        m('br'),
        'Suite 105',
        m('br'),
        'Miami, FL  33122'
        ])
      ]);
  }
  };
  };

  var _Message$1 = {};

  _Message$1.messages = [];

  _Message$1.add = function(type, msg_text){
    var msg = {type: type, text: msg_text};
    _Message$1.messages.push(msg);
    };

  _Message$1.addSuccess = function(msg_text){
    _Message$1.add('success', msg_text);
    };
    
  _Message$1.addNotification = function(msg_text){
    _Message$1.add('notification', msg_text);
    };

  _Message$1.addError = function(msg_text){
    _Message$1.add('error', msg_text);
    };

  _Message$1.remove = function(index){
    _Message$1.messages.splice(index,1);
    };

  var isUndefined = function(x){
    return typeof(x)==="undefined";
    };

  function isArray(x){
    return Array.isArray(x);
    }

  var remove = function(arr, pred){
    var len = arr.length;
    for(var i=0; i<len; i++){
      if(pred(arr[i], i)){
        arr.splice(i,1);
        break;
      }
    }
  };

  var removeByIndex = function(arr, i){
    arr.splice(i,1);
  };

  var _Cart = {};

  _Cart.updateQuantityOfItem = function(item, quantity){
    /*
    var possible_lineitem = _Cart.lineItemOfItem(item);  // _Cart.current.lineitems.find(function(lineitem){ return lineitem.item.id === item.id; });
    if(isUndefined(possible_lineitem)){
      possible_lineitem = _LineItem.createFromItem(item); 
      // possible_lineitem = _Cart.add(item);
      }
    possible_lineitem.quantity = quantity;
    */
    return m.request({
      method: 'POST',
      url: '/cgi/updateitemquantityincart',
      body: {
        session_hash: _User.session_hash,
        item_id: item.id,
        quantity: quantity
        }
      })
    .then(function(res){
      if(res.success === true){
        res.lineitems.forEach(function(lineitem, index){
          lineitem.item_id = _DB.integrate(lineitem.item_id).id; // at first item_id has the actual object, which we integrate into _DB, but then we set it to the ID as is expected
          res.lineitems[index] = _DB.integrate(lineitem).id;
          });
        _Cart.current.lineitem_ids = res.lineitems; // at this point, res.lineitems contains only IDs
        }
      else{
        _Message$1.addError("There was an error adding to cart.");
        }
      });
    };
  _Cart.removeLineItemOfItem = function(item){
    // TODO: do this on server-side, and return updated cart record with updated lineitem_ids
    remove(_Cart.current.lineitem_ids, function(lineitem_id){ return lineitem_id === item.id; });
    };
  _Cart.removeLineItem = function(index){
    // TODO: do this on server-side, and return updated cart record with updated lineitem_ids
    removeByIndex(_Cart.current.lineitem_ids, index);
    };
  _Cart.lineItemOfItem = function(item){
    if(_Cart.current !== null){
      return _DB.getRecord(  _Cart.current.lineitem_ids.find(function(lineitem_id){ return _DB.getRecord(lineitem_id).item_id === item.id; })  );
      }
    };

  _Cart.placeOrder = function(){
    m.request({
      method: 'POST', 
      url: '/cgi/placeorder', 
      body: {
        session_hash: _User.session_hash
        }})
    .then(function(res){
      if(res.success){
        _Message$1.addNotification("Order #"+ res.order_id +" Received!");
        _Cart.current = res.new_cart_record;
        _Cart.current.lineitem_ids = [];
        _DB.integrate(_Cart.current);
        }
      });
    };

  _Cart.current = null; //_Cart.new();

  var _DB$1 = {};

  _DB$1.records = {};

  _DB$1.insertRecord = function(record, type, structure){
    if(!isUndefined(type)){  record.type = type;  }
    var record_copy = _DB$1.copyAndTransform(record, structure);  // make a copy in case the record has references to other objects, possibly circular
    // TODO: Figure-out what to do for image, which has long `src_base64` property, so it must be stored in a file, with a mere reference in the DB. Also, upon creation the automatically makes thumbnails and updates the record accordingly, which is not possible to trigger.
    return m.request({
        method: 'POST',
        url: '/cgi/insertrecord',
        body: {
          session_hash: _User.session_hash,
          record: record_copy
          }
        })
      .then(function(res){
        if(res.success === true){
          record.id = res.id;
          _DB$1.integrate(record);
          }
        });
    };

  _DB$1.getRecord = function(id){
    return _DB$1.records[id];
    };

  _DB$1.removeRecord = function(record){
    delete _DB$1.records[record.id];
    // TODO: make a call to server too? This is called by _Item.deleteImage, which itself calls the server anyway because deleting an image has special logic
    };

  _DB$1.integrate = function(new_record){
    // check if record "exists" by id:
    if(_DB$1.records.hasOwnProperty(new_record.id)){
      // if it does exist, update its properties
      var old_record = _DB$1.records[new_record.id];
      Object.keys(new_record).forEach(function(key){
        old_record[key] = new_record[key];
        });
      }
    else{
      // if it doesn't exist, make it
      _DB$1.records[new_record.id] = new_record;
      }
    return _DB$1.records[new_record.id]; // in case we want the latest version of the record; see _OpenOrders for an example
    };

  _DB$1.integrateAll = function(new_records){
    new_records.forEach(function(new_record, i){  // TODO: ensure this is best behavior e.g. cart.lineitems; we want the latest lineitem list, with the proper things removed and added, not only added and none removed
      new_records[i] = _DB$1.integrate(new_record);
      });
    return new_records;
    };
  _DB$1.integrateAllReturnIds = function(new_records){
    new_records.forEach(function(new_record, i){  // TODO: ensure this is best behavior e.g. cart.lineitems; we want the latest lineitem list, with the proper things removed and added, not only added and none removed
      new_records[i] = _DB$1.integrate(new_record).id;
      });
    return new_records;
    };


  // determines whether to replace the whole array, or append to the existsing array, etc.
  _DB$1.integrateArray = function(record_id, property, new_array){
    
    };

  /*
   schema = {
    id: 'copy',
    brand: 'copy',
    item: 'replace-with-id',  // only get the id of the record, don't copy it
    item2: {
      id: 'copy',   // automatically makes separate top-level record for item2, and sets `record.item2 = item2`
      brand: 'copy'
      },
    lineitems: [
      'list',  // shows that this is a list
      {                     // this is the substructure of each element in the list
        id: 'copy',         // if substructure is left-out, then it's a list of scalars
        quantity: 'copy'    // if substructure == 'replace-with-id', it's a list of records, but only ids are transferred
        }
      ]
    }
   */
  _DB$1.getOne = function(id, type, structure){
    return m.request({
      method: 'POST',
      url: '/cgi/getone',
      body: {
        session_hash: _User.session_hash,
        id: id,
        type: type,
        structure: structure
        }
      })
    .then(function(res){
      if(res.success === true){
        _DB$1.integrate(res.record);
        }
      });
    };

  /* // exclude: big security problem, since record permissions aren't individualized; an attacker could just send an empty `structure` and get the whole DB
  _DB.getAll = function(filter, structure){
    return m.request({
      method: 'POST',
      url: '/cgi/getall',
      body: {
        session_hash: _User.session_hash,
        filter: filter,
        structure: structure
        }
      })
    .then(function(res){
      if(res.success === true){
        if(!isArray(res.records)){ res.records = []; }  // the JSON encoder sends an empty array as an object instead of array
        res.records.forEach(_DB.integrate);
        }
      });
    }
    */

  _DB$1.setProperty = function(record, key, value){
    var old_value = record[key];
    record[key] = value;
    return m.request({
      method: 'POST',
      url: '/cgi/setproperty',
      body: {
        session_hash: _User.session_hash,
        record_id: record.id,
        record_type: record.type,
        key: key,
        value: value
        }
      })
    .then(function(res){
      if(res.success === true){
        return value;
        }
      else{
        record[key] = old_value;
        _Message.addError('There was an error updating '+record.type+' #'+record.id+'.');
        return old_value;
        }
      });
    };

  _DB$1.copyAndTransform = function(record, structure){
    var record_copy = {};
    Object.keys(structure).forEach(function(key){
      var operation = structure[key];
      if(operation === 'copy'){
        record_copy[key] = record[key];
        }
      else if(operation === 'replace-with-id'){
        record_copy[key] = record[key].id;
        }
      });
    return record_copy;
    };

  var _User = {};

  _User.guest = {tier: 'silver'};
  _User.current = _User.guest;

  _User.session_hash = null;

  _User.isGold = function(){
    return _User.current.tier === 'gold';
    };

  _User.isLoggedIn = function(){
    return !(_User.current === _User.guest);
    };

  _User.isGuest = function(){
    return (_User.current === _User.guest);
    };

  _User.isAdmin = function(){
    return (_User.current.is_admin);
    };

  _User.attemptLogin = function(username, password){
    m.request({
      method: 'POST',
      url: '/cgi/attemptlogin', 
      body: { username: username, password: password }
      })
    .then(function(res){
      if(res.success === true){
        var user = res.user;
        _User.current = user;
        _User.session_hash = res.session_hash;
        _Message$1.addNotification("Welcome, "+user.firstname+"!");
        
        if(!isArray(res.cart.lineitem_ids)){
          res.cart.lineitem_ids = [];
          }
        res.cart.lineitem_ids.forEach(function(lineitem, index){
          lineitem.item_id = _DB$1.integrate(lineitem.item_id).id;
          res.cart.lineitem_ids[index] = _DB$1.integrate(lineitem).id;
          });
        _Cart.current = _DB$1.integrate(res.cart);
        
        return _Cart.current;
        }
      else{
        _Message$1.addError("Wrong Username/Password!");
        //return false;
        }
      });
    };

  _User.logout = function(){
    m.request({
      method: 'POST',
      url: '/cgi/logout', 
      body: { session_hash: _User.session_hash }
      })
    .then(function(res){
      if(res.success === true){
        _User.current = _User.guest;
        _User.session_hash = null;
        _Cart.current = null;
        _Message$1.addNotification("Logged out!");
        _Navigation.component = Home;
        _Navigation.attrs = null;
        }
      else{
        _Message$1.addError("Couldn't log out for some reason...");
        }
      });
    };

  var removeElement = function(arr, el){
    var len = arr.length;
    for(var i=0; i<len; i++){
      if(arr[i] === el){
        arr.splice(i,1);
        break;
      }
    }
  };

  //import filterCollection from "./lodash-es/filter.js";

  var _Item$1 = {};

  _Item$1.collection = [];

  _Item$1.priceOf = function(item){
    if(isUndefined(item.price_user)){
      if(_User.isGold()){
        return item.price_gold;
        }
      else{
        return item.price_silver;
        }
      }
    else{
      return item.price_user;
      }
    };

  /*
   Rationale for model-specific accessors like this, instead of directly using the general `_DB` module:
   Each model, whether for reads or writes on the server, may have special logic.
   For example, items. If a user isn't logged-in, only certain brands may be returned by the server.
   Another example, images. When a new image record is inserted into the DB, it saves the binary image data to a file, makes thumbnails, and saves the files' paths in the record, and returns the entire record to the client to update the path info.
   These can be accomplished by having a very smart client `_DB` module, which can direct each individual step on the server (e.g. make thumbnail, save to file, etc.).
   However, it's dangerous for a client to have the ability to "send code" to the server. The logic should reside on the server, only invoked by the client.
   Another problem with this is that it would require a lot of round-trips -- one for each step. 
   Another problem is that it's harder to implement atomic modifications. For example, if making a thumbnail fails, the entire image record is discarded from the DB. (This isn't actually the desired behavior, this is just for illustration.)
   In conclusion, we've opted for model-specific getters/setters, both on client and on server.
   
   However, the model-specific logic on both ends should still make sure to integrate data they receive into the DB, to keep all data in one place, and not have a bunch of copies of data with the same 'id' but different properties.
   */
  _Item$1.getItems = function(filter){
    return m.request({
      method:"POST",
      url:"/cgi/itemsbyfilter",
      body: {
        session_hash: _User.session_hash,
        filter:filter
        }})
    .then(function(res){
      if(res.success === true){
        // the server encodes an empty set as an Object instead of Array, so we have to detect it:
        if(!isArray(res.items)){
          res.items = [];
          }
        res.items.forEach(function(item, index){
          if(!isArray(item.image_ids)){
            item.image_ids = [];
            }
          _DB.integrateAllReturnIds(item.image_ids); // converts objects to ids in-place
          res.items[index] = _DB.integrate(item);  // TODO: ensure all integrations are captured and return, as this is, so everything refers to the same record in the DB
          });
        return res.items;
        }
      });
    };

  _Item$1.getFullItemInfo = function(item){
    return m.request({
      method:"POST",
      url:"/cgi/fulliteminfo",
      body: {
        item_id: item.id
        }})
    .then(function(res){
      var item = _DB.integrate(res.item);
      return item;
      });
    };

  _Item$1.searchByString = function(search_string){
    return m.request({
      method:"POST",
      url:"/cgi/itemsbystring",
      body: {
        session_hash: _User.session_hash,
        search_string: search_string
        }});
    };

  _Item$1.addImage = function(item, image){
    var image_index = item.image_ids.push(image) - 1;
    return m.request({
      method:"POST",
      url:"/cgi/addimagetoitem",
      body: {
        session_hash: _User.session_hash,
        item_id: item.id,
        image_base64: image.src_base64,
        original_filename: image.original_filename
        },
      config: function(xhr){
        image.is_uploading = true;
        image.progress = 0;
        xhr.addEventListener('progress', function(e){
          image.progress = e.loaded / e.total;
          });
        }
      })
    .then(function(res){
      delete image.is_uploading;
      delete image.progress;
      if(res.success === true){
        _Message$1.addSuccess("Uploaded "+image.original_filename);
        // At this point, `image` is still not its own record in `_DB`
        // `image` has a large `src_base64` property, whereas `res.image` has a bunch of properties which were set by the server, namely the paths to the different thumbnails of the image, and the original
        // Therefore, we choose to integrate `res.image` into `_DB`, and simply attach
        item.image_ids[image_index] = res.image.id;
        res.image = _DB.integrate(res.image);
        return res.image;
        }
      else{
        res.errors.forEach(function(err){
          _Message$1.addError("Error uploading "+image.original_filename+": "+err);
          });
        }
      });
    };

  _Item$1.loadImages = function(item){
    return m.request({
      method:"POST",
      url:"/cgi/itemimages",
      body: {
        session_hash: _User.session_hash,
        item_id: item.id
        }})
    .then(function(res){
      if(res.success === true){
        var images;
        if(isArray(res.images)){
          images = _DB.integrateAll(res.images);
          item.image_ids = res.images.map(function(i){ return i.id; });
          }
        else{
          item.image_ids = [];
          images = [];
          }
        return images;
        }
      else{
        res.errors.forEach(function(err){
          _Message$1.addError("Error uploading "+image.original_filename+": "+err);
          });
        }
      });
    };

  _Item$1.deleteImage = function(item, image){
    removeElement(item.image_ids, image.id);
    _DB.removeRecord(image);
    return m.request({
      method:"POST",
      url:"/cgi/deleteitemimage",
      body: {
        session_hash: _User.session_hash,
        item_id: item.id,
        image_id: image.id
        }});
    };

  var _Modal = {};

  _Modal.component = null;
  _Modal.attrs = null;
  _Modal.show = function(component, attrs){
    _Modal.component = component;
    _Modal.attrs = attrs;
    };
  _Modal.close = function(){
    _Modal.component = null;
    _Modal.attrs = null;
    };

  var _File = {};

  _File.readAsBase64 = function(file){
    var reader = new FileReader();
    
    return new Promise(function(resolve, reject){
      reader.onerror = function(){
        reader.abort();
        reject('Problem reading file.');
        };
      reader.onload = function(){
        resolve(reader.result);
        };
      reader.readAsDataURL(file);
      });
    };

  var _Image = {};

  _Image.placeholder_img_180_path = './images/placeholder-180x180.png';
  _Image.placeholder_img_960_path = './images/placeholder-960x720.png';

  // Make a temporary Image instance (for use before it's uploaded); it cannot and should not be attached to item.image_ids. Once it's uploaded, the server returns a proper Image record, which can be attached to item.image_ids.
  _Image.newFromFile = function(file){
    var image = {};
    image.original_filename = file.name;  // TODO: extract only filename without the path
    return _File.readAsBase64(file)
      .then(function(src_base64){
        image.src_base64 = src_base64;
        return image;
        });
    };

  /*
  _Image.upload = function(image){
    return m.request({
      method: "POST",
      url: "/cgi/newimage",
      body: {
        session_hash: _User.session_hash,
        image_base64: image.src_base64,
        original_filename: image.original_filename
        }
      });
    };
  */

  _Image.addToItem = function(image, item){
    return _Item.addImage(item, image);
    };

  _Image.thumbnailPath = function(image, size){
    var thumbnail_id = image['thumbnail_'+size+'_id'];
    if(isUndefined(thumbnail_id)){
      return _Image['placeholder_img_'+size+'_path']
      }
    else{
      return '/thumbnailsdb/'+thumbnail_id+'.png';
      }
    };

  //import _LargeImage from './_LargeImage.js';

  var _chosen_image = {
    item: null,
    chosen_image: null
    };

  var ItemModalView = function(){
  return {
  view: function(vnode){
  var item = vnode.attrs.item;
  if(_chosen_image.item !== item){
    _chosen_image.item = item;
    _chosen_image.chosen_image = item.image_ids[0];
    }
  var chosen_image = _chosen_image.chosen_image;
  var thumbnail_path = ( chosen_image ? _Image.thumbnailPath(_DB.getRecord(chosen_image), '960') : false );
  /*
  return [
    m('.modal-header', [
      m('a.btn.btn-clear.float-right', {'aria-label':"Close", onclick: function(){ _Modal.close(); }}),
      m('.modal-title.h4', item.name)
      ]),
    m('.modal-body', [
      m("img.img-responsive", {src: thumbnail_path || _Image.placeholder_img_960_path })
      ]),
    m('.modal-footer', [
      m('div', '$'+_Item.priceOf(item)),
      m('button.btn.btn-primary', 'Add to Cart')
      ])
    ];
    */
  return m('.item-modal-view', [
    m('a.btn.btn-clear.float-right', {'aria-label':"Close", onclick: function(){ _Modal.close(); }}),
    m('.h4.text-center', item.name),
    m("img.img-responsive", {
      src: thumbnail_path || _Image.placeholder_img_960_path,
      onclick: function(e){
        e.stopPropagation();
        if(thumbnail_path !== false){
          window.open(_Image.thumbnailPath(_DB.getRecord(chosen_image), 'original'), '_blank');
          }
        //_LargeImage.src = (thumbnail_path ? _Image.thumbnailPath(_DB.getRecord(item.image_ids[0]), 'original') : null);
        }
      }),
    m('.form-group.text-center',
      item.image_ids.map(function(image_id){
        return m('label.form-radio.label-sm.form-inline', [
          m('input.input-sm', {
            type:'radio', 
            name: item.id.toString()+'modal', // to distinguish from 'ItemListingEntry' radio buttons
            value: image_id, // is this converted to string?
            checked: chosen_image===image_id,
            onchange: function(e){
              _chosen_image.chosen_image = image_id;
              }
            }),
          m('i.form-icon',"")
          ]);
        })
      ),
    m('ul', [
      m('li', 'Color: '+item.color+' ('+item.color_description+')'),
      m('li', 'Size: '+(item.size || 'N/A')),
      m('li', 'Material: '+(item.material || 'N/A'))
      ]),
    m('p', item.description_short),
    ( _User.isLoggedIn() ? [
      m('div', '$'+_Item$1.priceOf(item) ),
      m('button.btn.btn-primary', 'Add to Cart')
      ]
      : null )
    ]);
  }
  };
  };

  var toNumber = function(x){
    return Number(x);
    };

  var isNumber = function(x){
    return !isNaN(x);
    };

  //var ItemListingEntry = require('./ItemListingEntry');

  function ItemListingEntry(initialVnode) {
    return {
      view: function(vnode) {
        var item = vnode.attrs.item;
        var index = vnode.attrs.index;
        var chosen_images = vnode.attrs.chosen_images;
        var chosen_image = chosen_images[index];
        var lineitem = _Cart.lineItemOfItem(item);
        var thumbnail_path = ( chosen_image ? _Image.thumbnailPath(_DB$1.getRecord(chosen_image), '180') : false );
        return m('.column.col-3.col-md-6.col-xs-12.mt-2', [
                  m(".card.c-hand", {
                      onclick: function(e){
                        _Item$1.getFullItemInfo(item).then(function(){
                          _Modal.show(ItemModalView, {item: item});
                          });
                        }
                      },[
                    m('.card-image.p-centered',[
                      (item.image_ids.length === 0
                        ?
                        m("img.img-responsive", {src: _Image.placeholder_img_180_path })
                        :
                        [
                          m("img.img-responsive", {src: thumbnail_path }),
                          m('.form-group.text-center',
                            item.image_ids.map(function(image_id){
                              return m('label.form-radio.label-sm.form-inline', [
                                m('input.input-sm', {
                                  type:'radio', 
                                  name: item.id.toString(),
                                  value: image_id, // is this converted to string?
                                  checked: chosen_image===image_id,
                                  onchange: function(e){
                                    chosen_images[index] = image_id;
                                    e.stopPropagation();
                                    }
                                  }),
                                m('i.form-icon',{onclick:function(e){
                                    chosen_images[index] = image_id;
                                    e.stopPropagation(); // So a modal box doesn't open-up
                                    return false; // I don't know why I need this in addition to stopPropagation().
                                    }
                                  },"")
                                ])
                              })
                            )
                          ]
                        )
                      ]),
                    m('.card-header', [
                      m(".card-title.h6.text-ellipsis", item.name),
                      m(".card-subtitle.text-gray", item.color),
                      ]),
                    (_User.isGuest() ? null : [
                      m('card-body',[
                        m(".price", '$'+_Item$1.priceOf(item)),
                        ]),
                      m('card-footer', [
                          m("input[type=text].form-input.text-center.c-auto", {
                            onchange: function(e){
                                        var new_quantity = toNumber(e.target.value);
                                        if(new_quantity === 0){
                                          _Cart.removeByItem(item);
                                          }
                                        else if(!isNumber(new_quantity)){
                                          //console.log("Qty. is not a number.");
                                          _Message$1.addError("Quantity '"+new_quantity+"' is not a number.");
                                          }
                                        else{
                                          _Cart.updateQuantityOfItem(item, new_quantity);
                                          }
                                        },
                            onfocus: function(e){e.target.select();},
                            onclick: function(e){ e.stopPropagation(); },
                            value: (isUndefined(lineitem) ? 0 : lineitem.quantity)
                            })
                          ])
                        ])
                    ])
        ]);
      }
    }
  }

  function ItemListing(initialVnode) {
    var chosen_images = {
      items: null,
      chosen_images: []
      };
    return {
      view: function(vnode) {
        //var items = _Item.filter(vnode.attrs.filter);
        //var items = _Item.collection;
        var items = vnode.attrs.items;
        if(items.length === 0){
          return m('h5', 'Please contact us directly to order.');
          }
        if(chosen_images.items !== items){
          chosen_images.chosen_images = items.map(function(item){
            return item.image_ids[0];
            });
          chosen_images.items = items;
          }
        return m(".columns", items.map(function(item, i){ 
            return m(ItemListingEntry, {item:item, index: i, chosen_images: chosen_images.chosen_images})
            }));
      }
    }
  }

  //import ItemFilter from './ItemFilter.js';

  function cmp_fn(a,b){
    var A = (a.model+a.color).toUpperCase(); // ignore upper and lowercase
    var B = (b.model+b.color).toUpperCase(); // ignore upper and lowercase
    if (A < B) {
      return -1;
      }
    else if (A > B) {
      return 1;
      }
    else{ // names must be equal
      return 0;
      }
    }

  function ItemBrowser(initialVnode) {
    return {
      view: function(vnode) {
        var items = vnode.attrs.items;
        items.sort(cmp_fn);
        return m(".item-browser.container", [
          //m(ItemFilter),
          m(ItemListing, {items: items})
          ]);
      }
    }
  }

  var _CollectionsList = {};

  _CollectionsList.house_brands = [
    'Kadima',
    'Kapricci',
    'BubbleGum',
    'Primmera'
    ];
  _CollectionsList.designer_brands = [
    //'Kadima',
    //'Kapricci',
    //'BubbleGum',
    //'Primmera',
    'Adidas',
    'Armani Exchange',
    'Bvlgari',
    'Burberry',
    'Calvin Klein',
    'Carolina Herrera',
    'Carrera',
    'Christian Dior',
    'Coach',
    'Converse',
    'Diesel',
    'Dolce Gabbana',
    'Emporio Armani',
    'Ermenegildo Zegna',
    'Escada',
    'Fendi',
    'Fila',
    'Furla',
    'Gant',
    'Giorgio Armani',
    'Gucci',
    'Guess',
    'Harley Davidson',
    'Hugo Boss',
    'Just Cavalli',
    'Kenneth Cole Reaction',
    'Kenneth Cole New York',
    'Lacoste',
    'Michael Kors',
    'Mont Blanc',
    'Nike',
    'Nina Ricci',
    'Oakley',
    'Persol',
    'Prada',
    'Prada Sport',
    'Puma',
    'Ray Ban',
    'Roberto Cavalli',
    'Salvatore Ferragamo',
    'Silhouette',
    'Skechers',
    'Timberland',
    'Tom Ford',
    'Tommy Hilfiger',
    'Tory Burch',
    'Tous',
    'Valentino',
    'Versace',
    'Vogue'
    ];

  var CollectionsList = function(){
  return {view: function(vnode){
    var brands = _CollectionsList.house_brands;
    return m('.container', [
      m('.columns', [
        m('.column.col-12', [
          m('h1.text-center', 'Collections')
          ])
        ]),
      m('.columns', brands.map(function(brand){
        return m('.column.col-4.col-md-6.col-xs-12.mt-1', [
          m('.card.c-hand', {onclick: function(e){
              //var item_browser_attrs = {};
              //item_browser_attrs.items = [];
              _Item$1.getItems({brand:brand}).then(function(items){
                //item_browser_attrs.items = items;
                _Navigation.navigateTo(ItemBrowser, {items: items});
                });
              }},[
            m('.card-header', [
              m('.card-title.h3.text-center', brand)
              ])
            ])
          ]);
          }
        ))
      ]);
  }};
  };

  var DesignerCollectionsList = function(){
  return {view: function(vnode){
    var brands = _CollectionsList.designer_brands;
    return m('.container', [
      m('.columns', [
        m('.column.col-12', [
          m('h1.text-center', 'Designer Collections')
          ])
        ]),
      _User.isGuest() ? m('.columns', [m('.column.col-12', 'Please Sign-In to See Designer Brands')]) : 
      m('.columns', brands.map(function(brand){
        return m('.column.col-4.col-md-6.col-xs-12.mt-1', [
          m('.card.c-hand', {onclick: function(e){
              //var item_browser_attrs = {};
              //item_browser_attrs.items = [];
              _Item$1.getItems({brand:brand}).then(function(items){
                //item_browser_attrs.items = items;
                _Navigation.navigateTo(ItemBrowser, {items: items});
                });
              }},[
            m('.card-header', [
              m('.card-title.h3.text-center', brand)
              ])
            ])
          ]);
          }
        ))
      ]);
  }};
  };

  var _Equipment = {};

  _Equipment.items = [];

  var Equipment = function(){
  return {
  view: function(){
  return m('.equipment', [
    m('h1.text-center','Equipment'),
    m(ItemBrowser, {items: _Equipment.items})
    ]);
  }
  };
  };

  var _Accessories = {};

  _Accessories.items = [];

  var Accessories = function(){
  return {
  view: function(){
  return m('.equipment', [
    m('h1.text-center','Accessories'),
    m(ItemBrowser, {items: _Accessories.items})
    ]);
  }
  };
  };

  var _OpenOrders = {};

  _OpenOrders.orders = [];

  _OpenOrders.getOpenOrders = function(){
    return m.request({
      method: 'POST',
      url: '/cgi/listopenorders',
      body: {
        session_hash: _User.session_hash
        }
      })
    .then(function(res){
      if(res.success === true){
        if(!isArray(res.orders)){
          res.orders = [];
          }
        _OpenOrders.orders = res.orders;
        _OpenOrders.orders.forEach(function(order){
          order.user_id = _DB$1.integrate(order.user_id).id;
          _DB$1.integrate(order);
          });
        return _OpenOrders.orders;
        }
      else{
        res.errors.forEach(function(err){
          _Message$1.addError("Error getting open Orders: "+err);
          });
        }
      });
    };

  _OpenOrders.loadOrder = function(order){
    return m.request({
      method: 'POST',
      url: '/cgi/loadorder',
      body: {
        session_hash: _User.session_hash,
        order_id: order.id
        }
      })
    .then(function(res){
      if(res.success === true){
        order = res.order;
        order.cart_id.lineitem_ids.forEach(function(lineitem){
          lineitem.item_id = _DB$1.integrate(lineitem.item_id).id;
          });
        _DB$1.integrateAllReturnIds(order.cart_id.lineitem_ids); // integrateAll modifies the Array in-place, so no need for '='
        order.cart_id = _DB$1.integrate(order.cart_id).id;
        order = _DB$1.integrate(res.order);
        
        return order;
        }
      else{
        res.errors.forEach(function(err){
          _Message$1.addError("Error loading Order #"+order.id+": "+err);
          });
        }
      });
    };

  var OrderView = function(){
  return {
  view: function(vnode){
  var order = vnode.attrs.order;
  var user = _DB$1.getRecord(order.user_id);
  var cart = _DB$1.getRecord(order.cart_id);
  var lineitems = cart.lineitem_ids.map(_DB$1.getRecord);
  var cart_total = 0;
  return m('.order-view', [
    m('h1', [
      'Order #'+order.id,
      m('small', 'Ordered On: '+order.date_ordered)
      ]),
    m('p', user.store+' ('+user.firstname+' '+user.lastname+')'),
    ( order.status === 'open'
      ?
        m('button.btn.btn-primary',{onclick: function(e){
          _DB$1.setProperty(order, 'status', 'closed');
          }},'Close Order')
      :
        m('button.btn.btn-primary',{onclick: function(e){
          _DB$1.setProperty(order, 'status', 'open');
          }},'Re-open Order')
      ),
    m('.steps', [
      m('ul.step', [
        m('li.step-item'+(order.progress==='ordered'?'.active':''), [
          m('a.tooltip', {
            href:'#',
            'data-tooltip':'Customer Placed Order on '+order.date_ordered,
            onclick: function(e){
              e.preventDefault();
              e.stopPropagation();
              _DB$1.setProperty(order, 'progress', 'ordered');
              }
            }, 'Ordered')
          ]),
        m('li.step-item'+(order.progress==='picked'?'.active':''), [
          m('a.tooltip', {
            href:'#',
            'data-tooltip':'Piazza Picked the Order',
            onclick: function(e){
              e.preventDefault();
              e.stopPropagation();
              _DB$1.setProperty(order, 'progress', 'picked');
              }
            }, 'Picked')
          ]),
        m('li.step-item'+(order.progress==='shipped'?'.active':''), [
          m('a.tooltip', {
            href:'#',
            'data-tooltip':'Piazza Shipped the Order',
            onclick: function(e){
              e.preventDefault();
              e.stopPropagation();
              _DB$1.setProperty(order, 'progress', 'shipped');
              }
            }, 'Shipped')
          ]),
        m('li.step-item'+(order.progress==='paid'?'.active':''), [
          m('a.tooltip', {
            href:'#', 
            'data-tooltip':'Customer Paid for the Order in Full',
            onclick: function(e){
              e.preventDefault();
              e.stopPropagation();
              _DB$1.setProperty(order, 'progress', 'paid');
              }
            }, 'Paid')
          ])
        ])
      ]),
    m('.items', [
      m('table.table.table-striped.table-hover', [
        m('thead', [
          m('tr', [
            m('th', 'Item'),
            m('th', 'Quantity'),
            m('th', 'Price'),
            m('th', 'Subtotal')
            ])
          ]),
        m('tbody', lineitems.map(function(lineitem){
          var subtotal = lineitem.quantity*lineitem.price;
          cart_total += subtotal;
          return m('tr', [
            m('td', _DB$1.getRecord(lineitem.item_id).name),
            m('td', lineitem.quantity),
            m('td', '$'+lineitem.price),
            m('td', '$'+subtotal)
            ]);
          }))
        ]),
      m('h6', "Grand Total: $"+cart_total)
      ])
    ]);
  }
  };
  };

  var OpenOrders = function(){
  return {
  view: function(vnode){
  return m('.open-orders', [
    m('h2', 'Open Orders'),
    m('button.btn.refresh-application-button',{onclick: function(){
                _OpenOrders.getOpenOrders();
                }},[m('i.icon.icon-refresh'), 'Refresh']),
    m('.order-list', 
      m('table.table.table-striped.table-hover', [
        m('thead', [
          m('tr', [
            m('th', 'Customer'),
            m('th', 'Date Ordered'),
            m('th', 'Order Number')
            ])
          ]),
        m('tbody',
            _OpenOrders.orders.map(function(order){
              var user = _DB$1.getRecord(order.user_id);
              var company_name = user.store || 'No Company: User#'+user.id;
              var date_ordered = order.date_ordered;
              var order_number = order.id;
              return m('tr', {onclick: function(e){
                      e.stopPropagation();
                      _OpenOrders.loadOrder(order).then(function(order){
                        _Navigation.navigateTo(OrderView, {order: order});
                        });
                      }},[
                m('td', company_name),
                m('td', date_ordered),
                m('td', order_number)
                ])
              })
            )
        ])
      )
    ]);
  }
  };
  };

  var util = {};

  util.remove = function(arr, el){
    var i=0;
    while(arr[i] !== el){ i++; }
    arr.splice(i,1);
    };

  var _Admin = {};

  _Admin.page = OpenOrders;

  _Admin.open_applications = [];

  _Admin.getOpenApplications = function(){
    return m.request({
      method:'POST', 
      url: '/cgi/listnewuserapplications',
      body: {
        session_hash: _User.session_hash
        }
      })
    .then(function(res){
      if(res.success === true){
        _Admin.open_applications = res.open_applications;
        // the server encodes an empty set as an Object instead of Array, so we have to detect it:
        if(typeof _Admin.open_applications.length === 'undefined'){
          _Admin.open_applications = [];
          }
        }
      });
    };

  _Admin.acceptApplication = function(a){
    return m.request({
      method:'POST', 
      url: '/cgi/acceptnewuserapplication',
      body: {
        session_hash: _User.session_hash,
        application_id: a.id,
        password: a.password
        }
      })
    .then(function(res){
      if(res.success === true){
        util.remove(_Admin.open_applications, a); // TODO: maybe get whole new list of open application IDs, instead of assuming the only change was this one. What if two admins are signed-on to two computers, each knocking-off open applications?
        }
      });
    };

  function ApplicationManager(ivnode){
  return { view: function(vnode){
    return m('.application-manager',[
              m('h2', 'Open Applications'),
              m('button.btn.refresh-application-button',{onclick: function(){
                _Admin.getOpenApplications();
                }},[m('i.icon.icon-refresh'), 'Refresh']),
              m('ul.open-application-list', _Admin.open_applications.map(function(a){
                return m('li', [
                  m('.name', a.salutation+' '+a.firstname+' '+a.lastname+ '('+a.position+' @ '+a.store+')'),
                  m('.info', a.practice_type+' (Office: '+a.phone_office+', Cell: '+a.phone_cell+', Email: '+a.email+')'),
                  m('.address', a.address),
                  m('input[type=text][placeholder=Password].application',{
                    onchange: function(e){ a.password = e.target.value; },
                    value: a.password
                    }),
                  m('button.btn.btn-success.accept-application-button', {onclick: function(){
                    _Admin.acceptApplication(a);
                    }}, 'Accept'),
                  m('button.btn.btn-error.accept-application-button', {onclick: function(){
                    _Admin.declineApplication(a);
                    }}, 'Decline')
                  ]);
                }))
      ]);
  }}}

  var ItemChooser = function(){
  var search_term = '';
  var results = [];
  var chosen_item = null;
  return {
  view: function(vnode){
    var onchoose = vnode.attrs.onchoose;
    return m('.item-search', [
      m('input[type=text][placeholder=Model]', {
        onchange: function(e){
          search_term = e.target.value;
          results = [];
          if(search_term !== ''){
            _Item$1.searchByString(search_term)
              .then(function(res){
                if(res.success === true){
                  if(isArray(res.results)){ // empty list comes back as `{}` from server instead of `[]`
                    results = res.results;
                    }
                  else{
                    results = [];
                    }
                  }
                });
              }
          },
        value: search_term
        }),
      m('table.table.table-striped.table-hover.results', [
        m('thead', [
          m('tr', [
            m('th', 'Brand'),
            m('th', 'Model'),
            m('th', 'Color')
            ])
          ]),
        m('tbody',
            results.map(function(item){
              var active_class = (chosen_item === item ? '.active' : '');
              return m('tr'+active_class, {
                  onclick: function(e){
                    e.stopPropagation();
                    chosen_item = item;
                    onchoose(item);
                    }
                  },[
                m('td', item.brand),
                m('td', item.model),
                m('td', item.color)
                ])
              })
            )
        ]
      )
    ]);
  }
  };
  };

  function isObject(x){
    return (typeof x === 'object');
    }

  function ItemImageController(ivnode){
  return { view: function(vnode){
    var item = vnode.attrs.item;
    if(item === null){
      return m('.msg', 'No item chosen.');
      }
    if(typeof item.image_ids === 'undefined'){ item.image_ids=[]; }
    var images = item.image_ids.map(function(image_id){
      if(isObject(image_id)){
        return image_id;
        }
      else{
        return _DB$1.getRecord(image_id);
        }
      }); 
    var no_images = (images.length === 0);
    return m('.item-image-controller.bg-secondary', {
          ondragover: function(e){
            e.preventDefault();
            },
          ondrop: function(e){
            e.preventDefault();  // don't open the file in the browser
            var files = [];
            
            // some browsers use `.items` and some use `.files`, so check for both:
            if (e.dataTransfer.items) {
              for (var i = 0; i < e.dataTransfer.items.length; i++) {
                if (e.dataTransfer.items[i].kind === 'file') {  // If dropped items aren't files, reject them
                  files.push( e.dataTransfer.items[i].getAsFile() );
                  }
                }
              }
            else {
              for (var i = 0; i < e.dataTransfer.files.length; i++) {
                files.push( e.dataTransfer.files[i] );
                }
              }
            for(var i=0; i<files.length; i++){
              _Image.newFromFile(files[i]).then(function(image){
                _Item$1.addImage(item, image).then(m.redraw);
                });
              }
            m.redraw();
            }
          }, [
      m('.container.image-list', [
        m('.columns',
                  no_images ? [m('.column.col-12', 'Drop Images Here')] : images.map(function(image){
                    return m('.column.col-4', [
                      m('.card.c-hand', {onclick: function(){ _LargeImage.src = (image.thumbnail_original_id ? '/thumbnailsdb/'+image.thumbnail_original_id+'.png' : image.src_base64); }},[
                        m('figure', [
                          m('img.img-responsive', {src: (image.thumbnail_180_id ? _Image.thumbnailPath(image, '180') : image.src_base64) }),
                          m('figcaption', image.original_filename)
                          ]),
                        m('button.btn.btn-clear.delete', {onclick: function(e){
                          e.stopPropagation();
                          _Item$1.deleteImage(item, image);
                          }},'Delete'),
                        (image.is_uploading ? m('progress.progress',{value: image.progress, max: 1.0}) : null)
                        ])
                      ]);
                    })
          )
        ])
      ]);
  }}}

  function ItemImageUploader(){
  var item = null;
  return {
  view: function(){
    return m('.item-image-uploader', [
      m('h2', 'Upload Images to Items'),
      m('.container', [
        m('.columns', [
          m('.column.col-6', [
            m(ItemChooser, {onchoose: function(_item){
                    item = _item;
                    _Item$1.loadImages(item);
                    }})
            ]),
          m('.column.col-6', [
            m(ItemImageController, {item: item})
            ])
          ])
        ])
      ]);
  }
  };
  }

  var _FrameAdmin = {};

  _FrameAdmin.search_term = '';
  _FrameAdmin.working_frames = [];
  _FrameAdmin.results_frames = [];

  _FrameAdmin.search_onchange_handler = function(e){
              _FrameAdmin.search_term = e.target.value;
              _FrameAdmin.results_frames = [];
              if(_FrameAdmin.search_term !== ''){
                //return _Item.searchByString(_FrameAdmin.search_term)
                return m.request({
                    method: 'POST',
                    url: '/cgi/framesbystring',
                    body: {
                      session_hash: _User.session_hash,
                      search_string: _FrameAdmin.search_term
                      }
                    })
                  .then(function(res){
                    if(res.success === true){
                      if(isArray(res.results)){ // empty list comes back as `{}` from server instead of `[]`
                        _FrameAdmin.results_frames = res.results;
                        }
                      else{
                        _FrameAdmin.results_frames = [];
                        }
                      return _FrameAdmin.results_frames;
                      }
                    });
                  }
              };

  _FrameAdmin.add_button_onclick_handler = function(e){
    var loading_placeholder = {loading: true};
    loading_placeholder.index = _FrameAdmin.working_frames.push(loading_placeholder);
    return m.request({
      method: 'POST',
      url: '/cgi/createnewframe',
      body: {
        session_hash: _User.session_hash
        }
      }).then(function(res){
        if(res.success === true){
          _DB.integrate(res.new_frame);
          _FrameAdmin.working_frames[loading_placeholder.index] = res.new_frame;
          //_FrameAdmin.working_frames.push({idname: '', brand: '', model: '', color: '', color_description: '', description_short: '', size: '', material: '', price_silver: 0.00, price_gold: 0.00});
          }
        });
    };

  _FrameAdmin.clear_button_onclick_handler = function(e){
    _FrameAdmin.working_frames = [];
    };

  var _FrameAdminListItem = {};

  _FrameAdminListItem.update = function(frame, property, value){
    var properties_to_update = {};
    properties_to_update[property] = value;
    return m.request({
      method: 'POST',
      url: '/cgi/updateitem',
      body: {
        session_hash: _User.session_hash,
        item_id: frame.id,
        properties_to_update: properties_to_update
        }
      })
    .then(function(res){
      if(res.success === true){
        frame[property] = value;
        }
      });
    };

  _FrameAdminListItem.delete = function(frame, collection, index_in_collection){
    return m.request({
      method: 'POST',
      url: '/cgi/deleteitem',
      body: {
        session_hash: _User.session_hash,
        item_id: frame.id
        }
      })
    .then(function(res){
      if(res.success === true){
        _DB.removeRecord(frame);
        collection.splice(index_in_collection, 1);
        }
      });
    };

  var FrameAdminListItem = function(){
  return {
  view: function(vnode){
    var frame = vnode.attrs.frame;
    var collection = vnode.attrs.collection;
    var index_in_collection = vnode.attrs.index_in_collection;
    if(frame.loading === true){
      return m('tr', [
        m('td', {colspan: 11}, [
          m('.loading-lg')
          ])
        ]);
      }
    else{
      return m('tr', [
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'name', e.target.value);
            }, value: frame.name})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'brand', e.target.value);
            }, value: frame.brand})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'model', e.target.value);
            }, value: frame.model})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'color', e.target.value);
            }, value: frame.color})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'color_description', e.target.value);
            }, value: frame.color_description})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'description_short', e.target.value);
            }, value: frame.description_short})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'size', e.target.value);
            }, value: frame.size})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            _FrameAdminListItem.update(frame, 'material', e.target.value);
            }, value: frame.material})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            var price = Number(e.target.value);
            if(price !== NaN){
              _FrameAdminListItem.update(frame, 'price_silver', price);
              }
            }, value: frame.price_silver})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            var price = Number(e.target.value);
            if(price !== NaN){
              _FrameAdminListItem.update(frame, 'price_gold', price);
              }
            }, value: frame.price_gold})
          ]),
        m('td', [
          m('input', {type:'text', onchange: function(e){
            var inventory = Number(e.target.value);
            if(inventory !== NaN){
              _FrameAdminListItem.update(frame, 'inventory', inventory);
              }
            }, value: frame.inventory})
          ]),
        m('td', [
          m('button.btn.btn-action.btn-primary.s-circle', {onclick: function(e){
            _FrameAdminListItem.delete(frame, collection, index_in_collection);
            }}, [m('i.icon.icon-delete')])
          ])
        ]);
      }
  }
  };
  };

  var FrameAdmin = function(){
  return {
  view: function(){
  var results_frames = _FrameAdmin.results_frames;
  var working_frames = _FrameAdmin.working_frames;
  return m('.frame-listing', [
        m('h4', 'Frame Editor'),
        m('.search', [
          m('input[type=text][placeholder=Model]', {
            onchange: _FrameAdmin.search_onchange_handler,
            value: _FrameAdmin.search_term
            })
          ]),
        m('table.table.table-striped', [
          m('thead', [
            m('tr', [
              m('th', 'Name'),
              m('th', 'Brand'),
              m('th', 'Model'),
              m('th', 'Color Code'),
              m('th', 'Color Description'),
              m('th', 'Description (Short)'),
              m('th', 'Size'),
              m('th', 'Material'),
              m('th', 'Price (Silver)'),
              m('th', 'Price (Gold)'),
              m('th', 'Inventory'),
              m('th', 'Delete')
              ])
            ]),
          m('tbody', [
            m('tr', [
              m('td.text-center', {colspan: 11}, [
                m('button.btn.btn-primary.btn-lg.btn-block', {onclick: _FrameAdmin.add_button_onclick_handler}, [
                  m('i.icon.icon-plus'),
                  ' Add ',
                  m('i.icon.icon-plus')
                  ])
                ])
              ]),
            working_frames.map(function(frame, i){
              return m(FrameAdminListItem, {frame: frame, collection: working_frames, index_in_collection: i});
              }),
            m('tr', [
              m('td.text-center', {colspan: 11}, [
                m('button.btn.btn-primary.btn-lg.btn-block', {onclick: _FrameAdmin.clear_button_onclick_handler}, [
                  m('i.icon.icon-refresh'),
                  ' Clear'
                  ])
                ])
              ]),
            results_frames.map(function(frame, i){
              return m(FrameAdminListItem, {frame: frame, collection: results_frames, index_in_collection: i});
              })
            ])
          ])
        ]);
  }
  };
  };

  //import _Image from './_Image.js';

  var c = function(page){
    return (_Admin.page === page ? '.active' : '')
    };

  var Admin = function(){
    return {
      view: function(vnode){
        return m('.admin',[
                  m('h1.text-center','Admin'),
                  m('ul.tab.tab-block.c-hand', [
                    m('li.tab-item'+c(OpenOrders), {
                        onclick: function(){ _Admin.page = OpenOrders; }
                        }, [
                      m('a', 'Orders')
                      ]),
                    m('li.tab-item'+c(ApplicationManager), {
                        onclick: function(){ _Admin.page = ApplicationManager; }
                        }, [
                      m('a', 'Account Applications')
                      ]),
                    m('li.tab-item'+c(FrameAdmin), {
                        onclick: function(){ _Admin.page = FrameAdmin; }
                        }, [
                      m('a', 'Frames')
                      ]),
                    m('li.tab-item'+c(ItemImageUploader), {
                        onclick: function(){ _Admin.page = ItemImageUploader; }
                        }, [
                      m('a', 'Image Upload')
                      ])
                    ]),
                  m(_Admin.page)
                  ])
        }
      };
    };

  function UnderConstruction(initialVnode) {
    return {
      view: function(vnode) {
        return m('h1.text-center.under-construction', 'Under Construction!');
        }
      }
    }

  var _Navigation = {};

  _Navigation.is_hidden = true;

  _Navigation.component = Home;
  _Navigation.attrs = null;

  _Navigation.navigateTo = function(component, attrs){
    _Navigation.component = component;
    _Navigation.attrs = attrs;
    };

  _Navigation.navigateToFunction = function(component, attrs){
    return function(e){
      _Navigation.component = component;
      _Navigation.attrs = attrs;
      };
    };

  _Navigation.menu = [
    {label: "Home", component: Home, attrs: null, children: [], run: null, restricted: false},
    {label: "About Us", component: AboutUs, attrs: null, children: [], run: null, restricted: false},
    {label: "Events", component: Events, attrs: null, children: [
      //{label: "Upcoming Trade Shows", component: Events, attrs: null, children: [], run: null, restricted: false}
      ], run: null, restricted: false},
    {label: "Collections", component: CollectionsList, attrs: null, children: [], run: null},
    {label: "Designer Collections", component: DesignerCollectionsList, attrs: null, children: [], run: null},
    //{label: "Lenses", component: LensBrowser, attrs: null, children: [], run: null, restricted: false},
    {label: "Lenses", component: UnderConstruction, attrs: null, children: [], run: null, restricted: false},
    {label: "Equipment", component: Equipment, attrs: null, children: [], run: function(){
                                  _Equipment.items=[];
                                  _Item$1.getItems({subtype:'equipment'})
                                    .then(function(items){ _Equipment.items=items; });
                                  }, restricted: false},
    {label: "Accessories", component: Accessories, attrs: null, children: [], run: function(){
                                  _Accessories.items=[];
                                  _Item$1.getItems({subtype:'accessory'})
                                    .then(function(items){ _Accessories.items=items; });
                                  }, restricted: false},
    {label: "Contact Us", component: ContactUs, attrs: null, children: [], run: null, restricted: false},
    {label: "Policies", component: Policies, attrs: null, children: [], run: null, restricted: false},
    {label: "Admin", component: Admin, attrs: null, children: [], run: null, restricted: 'admin'}
    ];

  var MenuItem = function(){
  return { view: function(vnode){
    var menuitem = vnode.attrs.menuitem;
    var attrs = {};
    if(menuitem.component !== null || menuitem.run !== null){ // note to self for continuation: make a proper onclick handler to both navigateTo and run the 'run', or either one if only one is provided
      attrs.onclick = function(){
        if(menuitem.component !== null){ _Navigation.navigateTo(menuitem.component,menuitem.attrs); }
        if(menuitem.run !== null){ menuitem.run(); }
        };
      }
    return m("a.btn.btn-link", attrs, [
            menuitem.label,
            m('.list',
              menuitem.children.map(function(mi){
                if(!menuitem.restricted || _User.isLoggedIn()){
                  return m(MenuItem, {menuitem: mi});
                  }
                }))
            ]);
    }
  };
  };

  var Navigation = function(){
  return {view: function(){
      var hidden_class = _Navigation.is_hidden ?'.hidden':'';
      var v = m("section.navbar-section", _Navigation.menu.map(function(menuitem){
        if(!menuitem.restricted){
          return m(MenuItem, {menuitem: menuitem})
          }
        else if(menuitem.restricted === 'admin' && _User.isAdmin()){
          return m(MenuItem, {menuitem: menuitem})
          }
        else if(menuitem.restricted === true && _User.isLoggedIn()){
          return m(MenuItem, {menuitem: menuitem})
          }
        }));
      return m('header.navbar'+hidden_class, [
        //m('button',{onclick: function(){ _Navigation.is_hidden = true; }},'Close'),
        v
        ]);
      /*
      return m("ul.flex.items-center.justify-center.bg-gray-900.text-white.cursor-default", [
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", {onclick: navigateTo(Home,null)}, "Home")
          ]),
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", {onclick: navigateTo(AboutUs,null)}, "About Us")
          ]),
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", {onclick: navigateTo(Events,null)}, "Events"),
          m(".menu.hidden", [
            m(".item", "Upcoming Trade Shows")
            ])
          ]),
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", "Collections Catalog"),
          m(".menu.hidden", [
            m(".section-heading", "Optical Frames"),
            m(".heading", "Style"),
            m(".subheading", "Adults"),
            m(".item", {onclick: navigateTo(ItemBrowser, {filter:{type: "frame", gender: "mens"}})}, "Mens"),
            m(".item", "Womens"),
            m(".item", "Unisex"),
            m(".subheading.item", "Teens"),
            m(".subheading.item", "Kids"),
            m(".heading", "Material"),
            m(".subheading", "Plastic"),
            m(".item", "Acetate"),
            m(".item", "TR90 & Silicone"),
            m(".item", "Injection"),
            m(".subheading", "Metal"),
            m(".item", "Aluminum"),
            m(".item", "Monel"),
            m(".item", "Stainless Steel"),
            m(".item", "Titanium"),
            m(".section-heading", "Sunglasses"),
            m(".heading", "Brand"),
            m(".subheading.item", "Designer Brands"),
            m(".subheading", "Exclusive Labels"),
            m(".item", "Kadima"),
            m(".item", "Kapricci"),
            m(".item", "Bubble Gum"),
            m(".item", "Primmera"),
            m(".heading", "Gender"),
            m(".item", "Mens"),
            m(".item", "Womens"),
            m(".item", "Unisex"),
            m(".heading.item", "Clearance Items")
            ])
          ]),
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", "Lenses"),
          m(".menu.hidden", [
            m(".section-heading", "Finished"),
            m(".heading", "Blue Bocker"),
            m(".heading", "Single Vision"),
            m(".heading", "Multifocals"),
            m(".section-heading", "Semi-Finished"),
            m(".heading", "Blue Bocker"),
            m(".heading", "Single Vision"),
            m(".heading", "Multifocals")
            ])
          ]),
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", "Equipment"),
          m(".menu.hidden", [
            m(".heading", "Autorefractometer"),
            m(".heading", "Chart Projector"),
            m(".heading", "Lensometer"),
            m(".heading", "Ophthalmoscope"),
            m(".heading", "Pachimeter"),
            m(".heading", "Phoropter"),
            m(".heading", "Prism bar"),
            m(".heading", "Pupilometer"),
            m(".heading", "Retinoscope"),
            m(".heading", "Slit Lamp"),
            m(".heading", "Trial Lens Set"),
            m(".item", "*104 pcs"),
            m(".item", "*158 pcs"),
            m(".item", "*232 pcs"),
            m(".item", "*266 pcs")
            ])
          ]),
        m("li", [
          m(".hover:bg-gray-700.rounded.px-2.py-1.text-center", "Accessories"),
          m(".menu.hidden", [
            m(".heading", "Cases"),
            m(".heading", "Cords"),
            m(".heading", "Microfiber Cloth Lens Cleaner"),
            m(".heading", "Lens Cleaner Bottles"),
            m(".heading", "Nosepads"),
            m(".heading", "Screws")
            ])
          ])
        ]);
        */
        }}};

  function Cart(initialVnode) {
    return {
      view: function(vnode) {
        if(!_User.isLoggedIn()){
          return m('.cart', [
            m("h1.text-center", "Shopping Cart"),
            m('p', 'You must be logged-in to see your cart.')
            ]);
          }
        var grand_total = 0;
        return m(".cart", [
          m("h1.text-center", "Shopping Cart"),
          m("table.table.table-striped.table-hover.line-item-list", [
            m('thead', [
              m('tr', [
                m('th', 'Item'),
                m('th', 'Price'),
                m('th', 'Quantity'),
                m('th', 'Subtotal')
                ])
              ]),
            m('tbody',
                _Cart.current.lineitem_ids.map(function(lineitem_id, lineitem_index){
                  var lineitem = _DB$1.getRecord(lineitem_id);
                  var item = _DB$1.getRecord(lineitem.item_id);
                  var price = lineitem.price;
                  var quantity = lineitem.quantity;
                  var sub_total = price*quantity;
                  grand_total += sub_total;
                  return m('tr.line-item', [
                      m('td.item-title', item.name),
                      m('td.price', "$"+price),
                      m('td', [
                        m('input[type=text].quantity.form-input', {
                          // TODO: Don't update quantity if it's not a (whole) number
                          onchange: function (e) {
                            //lineitem.quantity = toNumber(e.target.value);
                            var new_quantity = toNumber(e.target.value);
                            //if(new_quantity === 0){
                            //  _Cart.removeLineItem(lineitem_index);  // TODO: change to removeByLineitem, it's more efficient
                            //  }
                            //else if(!isNumber(new_quantity)){
                            if(!isNumber(new_quantity)){
                              //console.log("Qty. is not a number.");
                              _Message$1.addError("Quantity '"+new_quantity+"' is not a number.");
                              }
                            else{
                              _Cart.updateQuantityOfItem(item, new_quantity);
                              //lineitem.quantity = new_quantity;
                              }
                            },
                          value: lineitem.quantity
                          }),
                        ]),
                      m('td.line-item-total', '$'+sub_total)
                      ]);
                    })
              )
            ]),
          m('.total', [
            m('label.grand-total-label', "Grand Total: "),
            m('span.grand-total', '$'+grand_total)
            ]),
          m("button.btn.btn-primary", {onclick: _Cart.placeOrder}, "Place Order")
          ]);
      }
    }
  }

  var Messages = function(){
    return {
      view: function(vnode){
        return m('.messages-box.p-fixed.p-2', {style: 'left:0px;top:0px;width:100%;'},_Message$1.messages.map(function(msg, index){
          var message_class;
          if(msg.type === 'success'){
            message_class = 'toast-success';
            }
          else if(msg.type === 'notification'){
            message_class = 'toast-primary';
            }
          else if(msg.type === 'error'){
            message_class = 'toast-error';
            }
          return m('.toast.'+message_class, [
            m('button.btn.btn-clear.float-right', {onclick: function(){ _Message$1.remove(index); }}, ""),
            msg.text
            ]);
          }));
        }
      };
    };

  var _Login = {};

  _Login.username = "";
  _Login.password = "";

  _Login.is_hidden = true;

  var _AccountApplication = {};

  //_AccountApplication._show = false;
  _AccountApplication.username = '';
  _AccountApplication.salutation = '';
  _AccountApplication.firstname = '';
  _AccountApplication.lastname = '';
  _AccountApplication.position = '';
  _AccountApplication.store = '';
  _AccountApplication.address = '';
  _AccountApplication.practice_type = '';
  _AccountApplication.phone_office = '';
  _AccountApplication.phone_cell = '';
  _AccountApplication.email = '';

  _AccountApplication.salutations = [
    {value: 'mr', text: 'Mr.'},
    {value: 'ms', text: 'Ms.'},
    {value: 'mrs', text: 'Mrs.'},
    {value: 'dr', text: 'Dr.'}
    ];
  _AccountApplication.positions = [
    {value: 'owner', text: 'Owner'},
    {value: 'manager', text: 'Manager'},
    {value: 'buyer', text: 'Buyer'},
    {value: 'other', text: 'Other'}
    ];
  _AccountApplication.practice_types = [
    {value: 'optometrist', text: 'Optometrist'},
    {value: 'ophthalmologist', text: 'Ophthalmologist'},
    {value: 'optician', text: 'Optician'},
    {value: 'optical_retail_store', text: 'Optical Retail Store'},
    {value: 'optical_lab', text: 'Optical Lab'},
    {value: 'importer_distributor', text: 'Importer/Distributor'}
    ];

  //_AccountApplication.show = function(){
  //  _AccountApplication._show = true;
  //  };
  //_AccountApplication.hide = function(){
  //  _AccountApplication._show = false;
  //  };
  //_AccountApplication.isShowing = function(){
  //  return _AccountApplication._show === true;
  //  };
  _AccountApplication.submit = function(){
    m.request({
      method: 'POST',
      url: '/cgi/submitnewuserapplication',
      body: {
        username: _AccountApplication.username,
        salutation: _AccountApplication.salutation,
        firstname: _AccountApplication.firstname,
        lastname: _AccountApplication.lastname,
        position: _AccountApplication.position,
        store: _AccountApplication.store,
        address: _AccountApplication.address,
        practice_type: _AccountApplication.practice_type,
        phone_office: _AccountApplication.phone_office,
        phone_cell: _AccountApplication.phone_cell,
        email: _AccountApplication.email
        }
      }).then(function(){
        _Message$1.addNotification('Application Submitted!');
        _AccountApplication._show = false;
        _AccountApplication.username = '';
        _AccountApplication.salutation = '';
        _AccountApplication.firstname = '';
        _AccountApplication.lastname = '';
        _AccountApplication.position = '';
        _AccountApplication.store = '';
        _AccountApplication.address = '';
        _AccountApplication.practice_type = '';
        _AccountApplication.phone_office = '';
        _AccountApplication.phone_cell = '';
        _AccountApplication.email = '';
        });
    };

  var AccountApplicationBox = function(){
    return {
      view: function(vnode){
          return m('.account-application.form-horizontal', [
                m('h1.text-center', 'Account Application Form'),
                m('h3', 'Account Information'),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', [
                        'Username',
                        m('small', '(use your email address)')
                        ])
                      ]),
                    m('col-9', [
                        m('input[type=text]', {
                          onchange: function(e){ _AccountApplication.username = e.target.value; },
                          value: _AccountApplication.username
                          })
                        ])
                    ]),
                m('h3', 'Personal Information'),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Salutation')
                      ]),
                    m('.col-9', [
                        _AccountApplication.salutations.map(function(s){
                          return [
                            m('label.form-radio.form-inline', [
                              m('input[type=radio][name=salutation]', {
                                onchange: function(e){ _AccountApplication.salutation = e.target.value; },
                                value: s.value
                                }),
                              m('i.form-icon',''),
                              s.text
                              ])
                            ];
                          })
                        ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'First Name')
                      ]),
                    m('.col-9', [
                      m('input[type=text][placeholder=First Name]', {
                        onchange: function(e){ _AccountApplication.firstname = e.target.value; },
                        value: _AccountApplication.firstname
                        })
                      ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Last Name')
                      ]),
                    m('.col-9', [
                        m('input[type=text][placeholder=Last Name]', {
                          onchange: function(e){ _AccountApplication.lastname = e.target.value; },
                          value: _AccountApplication.lastname
                          })
                        ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Position in Company')
                      ]),
                    m('.col-9', _AccountApplication.positions.map(function(s){
                          return [
                            m('label.form-radio.form-inline', [
                              m('input[type=radio][name=position]', {
                                onchange: function(e){ _AccountApplication.position = e.target.value; },
                                value: s.value
                                }),
                              m('i.form-icon',''),
                              s.text
                              ])
                            ];
                          })
                        )
                    ]),
                m('h3', 'Business Information'),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Name of Business')
                      ]),
                    m('.col-9', [
                        m('input[type=text][placeholder=Name of Business (your shop/clinic/practice name)]', {
                          onchange: function(e){ _AccountApplication.store = e.target.value; },
                          value: _AccountApplication.store
                          })
                        ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', [
                        'Address',
                        m('small', '(full address including city and country)')
                        ])
                      ]),
                    m('.col-9', [
                      m('input[type=text][placeholder=Address (full address including city and country)]', {
                        onchange: function(e){ _AccountApplication.address = e.target.value; },
                        value: _AccountApplication.address
                        })
                      ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Type of Business')
                      ]),
                    m('.col-9', [
                        _AccountApplication.practice_types.map(function(s){
                          return [
                            m('label.form-radio.form-inline', [
                              m('input[type=radio][name=practice_type].practice-type', {
                                onchange: function(e){ _AccountApplication.practice_type = e.target.value; },
                                value: s.value
                                }),
                              m('i.form-icon', ''),
                              s.text
                              ])
                            ];
                          })
                        ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Phone (Office)')
                      ]),
                    m('.col-9', [
                      m('input[type=text][placeholder=Phone (Office)]', {
                        onchange: function(e){ _AccountApplication.phone_office = e.target.value; },
                        value: _AccountApplication.phone_office
                        })
                      ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Phone (Cell/WhatsApp)')
                      ]),
                    m('.col-9', [
                      m('input[type=text][placeholder=Phone (Cell/WhatsApp)]', {
                        onchange: function(e){ _AccountApplication.phone_cell = e.target.value; },
                        value: _AccountApplication.phone_cell
                        })
                      ])
                    ]),
                m('.form-group', [
                    m('.col-3', [
                      m('label.form-label', 'Email Address')
                      ]),
                    m('.col-9', [
                      m('input[type=text][placeholder=Email Address].email', {
                        onchange: function(e){ _AccountApplication.email = e.target.value; },
                        value: _AccountApplication.email
                        })
                      ])
                    ]),
                m('button.btn.btn-primary.application-submit-button', {onclick: function(e){
                  e.preventDefault(); // this is require since the button is in a form
                  _AccountApplication.submit();
                  }}, "Submit")
                ]);
        }
      };
    };

  var LoginBox = function(){
    return {
      view: function(vnode){
        if(!_User.isLoggedIn()){
          return m('.column.col-8', [
              m('.form-group', [
                //m('button.red',{onclick: function(){ _Login.is_hidden = true; }},'Close'),
                m('.has-icon-left', [
                  m('input[type=text][placeholder=Username].form-input', {
                    onchange: function(e){ _Login.username = e.target.value; },
                    value: _Login.username
                    }),
                  m('i.form-icon.icon.icon-arrow-right')
                  ]),
                m('input[type=password][placeholder=Password].form-input', {
                  onchange: function(e){ _Login.password = e.target.value; },
                  value: _Login.password
                  }),
                m('button.btn.btn-primary', {onclick: function(e){
                  e.preventDefault(); // this is require since the button is in a form
                  _User.attemptLogin(_Login.username, _Login.password);
                  }}, "Login"),
                m('button.btn', {onclick: function(e){
                  e.preventDefault(); // this is require since the button is in a form
                  _Navigation.navigateTo(AccountApplicationBox, null);
                  }}, "Apply for Account")
                ])
            ]);
          }
        else{
          return m('.logout_box.column.col-11', [
            m('button.btn.btn-primary', {
              onclick: function(){
                _User.logout();
                _Login.username = "";
                _Login.password = "";
                }}, 'Logout')
            ])
          }
        }
      };
    };

  var Modal = function(){
    return {
      view: function(vnode){
        var active_class = (_Modal.component === null ? '' : '.active');
        return m('.modal'+active_class, [
          m('a.modal-overlay', {
            'aria-label':"Close",
            onclick: function(){ _Modal.close(); }
            }),
          m('.modal-container', [
            (_Modal.component === null ?
              ''
              :
              m(_Modal.component, _Modal.attrs)
              )
            ])
          ]);
        }
      };
    };

  var root = document.body;
  window._DB = _DB$1;

  var Page = {
  view: function(){
    return [
          m('#root.container.grid-lg', _Root.attrs, [
            m('#head.columns', [
              m('img.img-responsive.column.col-3', {src: 'images/piazza-optical-logo.jpg'}),
              m(LoginBox),
              m('.column.col-1', [
                m('button.btn.btn-primary', {onclick: _Navigation.navigateToFunction(Cart,null)}, [
                  m('i.icon-basket'),
                  'Cart'
                  ])
                ])
              ]),
            m(Navigation),
            m('#main', [
              m(_Navigation.component, _Navigation.attrs)
              //m(ItemBrowser)
              ]),
            m(Modal),
            //m(LargeImage),
            m(Messages) // last so it's always on top
            ]),
          m("#footer.bg-dark", [
            m("h6#copyright.text-center", "Copyright ©2019 Piazza Optical")
            ])
      ]
    }
  };
  m.mount(root, Page);

  // TODO: get rid of this function in production
  function api(endpoint, payload){
    return m.request({
      method: 'POST',
      url: '/cgi/'+endpoint,
      body: payload
      });
    }
  window.api = api;

  //module.exports = {};

}());
