<repo_name>gregoryanderson/Overlook<file_sep>/test/room-test.js
import Room from '../src/Room'
import data from '../data'
import chai from 'chai';
import spies from 'chai-spies'
const expect = chai.expect;

  describe("Room", function() {

    let room

    beforeEach(function (){
        room = new Room(data, data, data,'2019/08/29')
    });

    it.only('should return true', function() {
      expect(true).to.equal(true);
    });

    it.only('should be an function', function(){
      expect(Room).to.be.a('function')
    })

    it.only('should be an instance of Room', function(){
      expect(room).to.be.an.instanceOf(Room)
    })
  });<file_sep>/src/roomService.js
import domUpdates from "./domUpdates";

class RoomService {
  constructor(services, menu, guestId) {
    this.services = services.roomServices;
    this.menu = this.createMenu();
    this.id = guestId;
  }

  createMenu(){
    let fullMenu = [];
      return this.services.reduce((fullMenuObjs, order) => {
        if(!fullMenu.includes(order.food)){
          fullMenu.push(order.food)
          fullMenuObjs.push({food: order.food, cost: order.totalCost})
        }
        return fullMenuObjs
      }, [])
  }

  findCorrectItem(foodId){
    return this.services.find(item => item.totalCost == foodId)
  }

  filterAllOrdersBySpecificGuest(guest){
    let specificOrders = this.services.filter(service => {
      if (parseInt(guest.id) === service.userID){
        return service
      }
    })
    domUpdates.displayAllOrdersBySpecificGuest(specificOrders)
  }

  findTotalCostOfAllOrdersBySpecificGuest(guest){
    let specificOrdersCost = this.services.filter(order => {
      if(parseInt(guest.id) === order.userID){
        return order
      }
    }).reduce((totalCost, order) => {
      totalCost += order.totalCost
      return totalCost
    }, 0)
    domUpdates.displayTotalRoomServiceCostForSpecificUser(specificOrdersCost)
  }
}

export default RoomService;<file_sep>/src/domUpdates.js
import $ from "jquery";


const domUpdates = {
  displayDate() {},

  displayDate(date){
    $('.header--date').text(date)
  },

  displayRoomsAvailable(rooms) {
    $("#main__avail-rooms").text(`There are ${rooms} rooms available.`);
  },

  displayTotalServiceChargesForToday(charges) {
    $("#main__charges-today").text(
      `$${charges} has been made in room service charges today.`
    );
  },

  displayRoomChargesRevenueForToday(charges) {
    $("#main__revenue-today").text(
      `$${charges} has been made in room booking revenue today.`
    );
  },

  displayPercentageOfRoomsBooked(percent) {
    $("#main__occupied-rate").text(
      `${percent}% of rooms have been booked today.`
    );
  },

  displayMostRoomsBookedInOneDay(totalRoomNumber, date) {
    $("#rooms__booking-high-date").text(
      `On ${date}, we booked ${totalRoomNumber} rooms, which was the highest booking date for our hotel. Great work!`
    );
  },

  displayLeastRoomsBookedInOneDay(totalRoomNumber, date) {
    $("#rooms__booking-low-date").text(
      `On ${date}, we booked ${totalRoomNumber} rooms, which was the lowest booking date for our hotel.`
    );
  },

  displayRoomServiceOrdersForToday(todaysOrders) {
    if (todaysOrders.length === 0) {
      $("#orders__tbody--today").text("There are no orders today");
    } else {
      todaysOrders.forEach(order => {
        $("#orders__tbody--today").append(`<tr>
        <td>${order.food}</td><td>$${order.totalCost}</td>
            </tr>`);
      });
    }
  },

  displayRoomServiceOrdersForSpecificDate(specificDateOrders) {
    if (specificDateOrders.length === 0) {
      $("#orders__tbody--searched").text("");
      $("#orders__tbody--searched").text("There are no orders for that date");
    } else {
      $("#orders__tbody--searched").text("");
      specificDateOrders.forEach(order => {
        $("#orders__tbody--searched").append(`<tr>
            <td>${order.food}</td><td>$${order.totalCost}</td><td>${
          order.date
        }</td>
            </tr>`);
      });
    }
  },

  displayBookingsForToday(todaysBookings) {
    if (todaysBookings.length === 0) {
      $("#room__tbody--booked").text("There are no bookings today");
    } else {
      todaysBookings.forEach(booking => {
        $("#room__tbody--booked").append(`<tr>
            <td>${booking.roomNumber}</td><td>${booking.date}</td>
            </tr>`);
      });
    }
  },

  displayRoomsAvailableForToday(todaysRoomsAvailable) {
    if (todaysRoomsAvailable.length === 0) {
      "#rooms__tbody--available".text("There are no rooms available today");
    } else {
      todaysRoomsAvailable.forEach(room => {
        $("#rooms__tbody--available").append(`<tr>
                <td>${room.number}</td><td>${room.roomType}</td><td>${room.bedSize}</td><td>${
          room.numBeds
        }</td><td>${room.bidet}</td><td>${room.costPerNight}</td>
                </tr>`);
      });
    }
  },

  displayAllGuests(allGuests) {
    if (allGuests.length === 0) {
      "#guests__tbody".text("Please search and select a guest");
    } else {
      allGuests.forEach(guest => {
        $("#guests__tbody").append(`<tr>
              <td>${guest.name}</td><td>${guest.id}</td>
              </tr>`);
      });
    }
  },

  displaySearchedUsers(filteredSearchGuests) {
    if (filteredSearchGuests.length > 0){
      $("#guests__tbody--searched").text("");
      filteredSearchGuests.forEach(guest => {
        $("#guests__tbody--searched").append(
          `<tr><td class="guests__td--searched" data-id=${guest.id}>${
            guest.name
          }</td><td>${guest.id}</td></tr>`
        );
      });
    } else {
      newGuestReminder()
    }
  },

  displaySelectedGuest(selectedGuest) {
    $("#header--selected-guest").text(selectedGuest.name);
    $("#guests__div--specific").text(`${selectedGuest.name} has been selected. Their information will now be shown throughout`);
    $('#guests__tbody--searched').text('');
    $('#guests__section--new-guest').text('');
    $('#guests__div--searched').hide();
    $('.specific').text(`${selectedGuest.name}`)
  },

  newGuestReminder() {
    $("#guests__section--new-guest").html(
      '<p>Or, Please Enter a Name to Create a New Guest.</p><input type="text" id="guests__input--create"><button id="guests__button--create">Create</button>'
    );
    $("#guests__tbody--searched").text("");
  },

  displayAllOrdersBySpecificGuest(orders) {
    $("#orders__tbody--guest").text('')
    if (orders.length === 0) {
      $("#orders__section--new-order").html(
        '<p>No Orders Found.</p><button id="orders__button--create">Create</button>'
      );
    } else {
      orders.forEach(order => {
        $("#orders__tbody--guest").append(`<tr>
    <td>${order.food}</td><td>$${order.totalCost}</td><td>${order.date}</td>
    </tr>`);
      });
    }
  },

  displayAllBookingsBySpecificGuest(bookings) {
    $("#rooms__tbody--guest").text('')
    if (bookings.length === 0) {
      $("#rooms__section--new-order").html(
        '<p>No Bookings Found.</p><button id="orders__button--create">Create</button>'
      );
    } else {
      bookings.forEach(booking => {
        $("#rooms__tbody--guest").append(`<tr>
    <td>${booking.date}</td><td>${booking.roomNumber}</td><td><button class"button unbook">UNBOOK</button>
    </tr>`);
      });
    }
  }, 

  displayTotalRoomServiceCostForSpecificUser(ordersCost){
    if(ordersCost > 0){
    $("#orders__section--total").text(`Total: ${ordersCost}`)
    } else {
    $("#orders__section--total").text(`Total: $0.00`)
    }
  },

  displayTodaysBookingForSpecificGuest(guest, booking){
    if(booking){
    $('#rooms__section--create-booking').text('')
    $('#rooms__tbody--todays-booking').html(`<tr><td>${guest.name}</td><td>${booking.roomNumber}</td><td><button class"button unbook">UNBOOK</button></td></tr>`)
    } else {
    $("#rooms__section--create-booking").html(`<tr><td>${guest.name} has not made a reservation today. Click to create one</td><td><button id="rooms__button--reservation">Create Reservation</button></td></tr>`)
    }
  }, 

  displayTodaysBookingForSpecificGuestBookingToday(guest, booking, menu){
    $('#rooms__section--create-booking').text('')
    $('#rooms__tbody--todays-booking').html(`<tr><td>${guest.name}</td><td>${booking.number}</td><td>${booking.bedSize}</td><td>${booking.numBeds}</td><td>${booking.bidet}</td><td>${booking.costPerNight}</td><td><button data-id=${booking.costPerNight} id="unbook--newReservation" class=unbook button>UNBOOK</button></td></tr>`);
    $('#rooms__section--new-order').html(`<p>Would the guest enjoy room service?</p><button id="rooms__button--no-thanks">NO THANK YOU</button>`);
    menu.forEach(item => {
    $('#rooms__tbody--todays-orders').append(`<tr><td>${item.food}</td><td>${item.cost}</td><td><button class="button rooms__button--service" data-id=${item.cost}>Select</button></td></tr>`)
    })
  }, 

  displayRoomsAvailableForSpecificGuest(todaysRoomsAvailable) {
    console.log(todaysRoomsAvailable)
    if (todaysRoomsAvailable.length === 0) {
      $("#rooms__tbody--todays-booking").text("There are no rooms available today");
    } else {
      todaysRoomsAvailable.forEach(room => {
        $("#rooms__tbody--todays-booking").append(`<tr>
                <td>${room.number}</td><td>${room.roomType}</td><td>${room.bedSize}</td><td>${
          room.numBeds
        }</td><td>${room.bidet}</td><td>${room.costPerNight}</td><td><button class="button guests__button--select" data-id=${room.number}>Select Room</button></td>
                </tr>`);
      });
    }
  },

  displayAdditionalFoodService(foodItem){
    $('#orders__table--new').show()
    $('#rooms__section--new-order').hide()
    $('#rooms__section--new-orders').hide()
    $('#orders__tbody--new').html(`<tr>
      <td>${foodItem.food}</td><td>${foodItem.totalCost}</td></tr>`)
  }

};
    // displayTotalBookingsCostForSpecificUser(bookingsCost){
    //   console.log(bookingsCost)
    //   if(bookingsCost > 0){
    //     $("#rooms__section--total").text(`Total: ${bookingsCost}`)
    //   } else {
    //     $("#rooms__section--total").text(`Total: $0.00`)    
    //   }
    // }
    // // configureDate(date) {
  
    // },

// attachCreateButtonListener(){
//   $("#guests__button--create").on("click", function() {
//     console.log("linked");
//     let customerName = $("guests__input--create").val();
//     console.log(customerName);
//     let newCustomer = new Customer(allData.customers, null, customerName);
//     console.log(newCustomer);
//     let newMain = new Main(
//       allData.customers,
//       allData.bookings,
//       allData.services,
//       allData.rooms,
//       dateToday(),
//       newCustomer
//     );
//     console.log(newMain);
//     domUpdates.displaySelectedGuest(customerName);
//   });

//   searchCustomers(users) {
//     $('#no-users').text('')
//     $('.tab__customers-output').text('')
//     users.forEach(user => {
//       $('.tab__customers-output').append(`<li class="customer__search-data" data-id="${user.id}">${user.name}</li>`)
//     })
//   },

export default domUpdates;
<file_sep>/test/guestRepo-test.js
const expect = chai.expect;

import GuestRepo from '../src/guestRepo'
import chai from 'chai';
import spies from 'chai-spies';
import data from '../data';
import domUpdates from '../src/domUpdates';

chai.use(spies)

describe("guestRepo", function() {

  let guestRepo 

  beforeEach(function (){
      guestRepo = new GuestRepo(data)
  });

  it.only("should return true", function() {
      expect(true).to.equal(true);
  });

  it.only('should filter users by search', function() {
    guestRepo.filterUsersBySearch('a')
    expect(domUpdates.displaySearchedUsers).to.be.called(1)
  })

  it.only('should update to dom', function() {
    expect(domUpdates.displayAllGuests).to.be.called(3)
  })
})<file_sep>/src/customer.js
import domUpdates from "./domUpdates";

class Customer {
    constructor (guests, id, name){
        this.guests = guests.users;
        this.id = id || this.findIdOfGuest();
        this.name = name || this.findNameOfGuest();
    }

    findNameOfGuest(){
        let selectedGuest = this.guests.find(guest => guest.id == this.id);
        return selectedGuest.name
    }

    findIdOfGuest(){
        return this.guests.length + 1
    }

    pushGuestIntoGuestArray(guest){
        this.guests.push(guest)
    }

    // createNewCustomer(name) {
    //     let newCustomer = new Customer(name, null, this.users, this.rooms, this.bookings, this.roomServices);
    //     this.users.push(newbieCustomer);
    //     this.currentCustomer = newbieCustomer;
    //     this.hotelBenchmarks = new Hotel(this.users, this.rooms, this.bookings, this.roomServices, this.today);
    //     return newbieCustomer;
    //   }
}

export default Customer<file_sep>/test/customer-test.js
const expect = chai.expect;

import Customer from '../src/Customer'
import chai from 'chai';
import data from '../data'

describe("customer", function() {

  let customer 

  beforeEach(function (){
      customer = new Customer(data, 4, "<NAME>")
  });

  it.only("should return true", function() {
      expect(true).to.equal(true);
  })

  it.only("should return correct name", function() {
    expect(customer.findNameOfGuest()).to.equal("<NAME>");
  })

  it.only("should return correct id", function() {
    expect(customer.findIdOfGuest()).to.equal(21);
  })

})<file_sep>/src/bookingRepo.js
import domUpdates from "./domUpdates";

class BookingRepo {
  constructor(bookings, rooms, customers, date) {
    this.bookings = bookings.bookings;
    this.rooms = rooms.rooms;
    this.customers = customers.users;
    this.date = date;
    this.info = this.updateToDom();
  }

  filterBookingsByDate(specDate) {
    return this.bookings.filter(booking => booking.date === specDate);
  }

  sortBookingsByDate(specDate) {
    let todaysBookings = this.filterBookingsByDate(specDate);
    return todaysBookings.sort((a, b) => a.roomNumber - b.roomNumber);
  }

  mapBookingsForRoomNumber(bookings){
    return bookings.map(booking => booking.roomNumber)
  }

  filterRoomsAvailableToday(specDate){
      let todaysBookings = this.sortBookingsByDate(specDate)
      let bookedRoomNumbers = (this.mapBookingsForRoomNumber(todaysBookings))
      return this.rooms.filter(room => {
          if(!bookedRoomNumbers.includes(room.number)){
            return room
          }
      })
  }

  pushBookingIntoBookingsArray(booking, bookedRoom){
    this.bookings.push(booking)
  }

  findCorrectRoom(room){
    return this.rooms.find(item => item.number == room);
  }

  updateToDom() {
    domUpdates.displayBookingsForToday(this.sortBookingsByDate(this.date));
    domUpdates.displayRoomsAvailableForToday(this.filterRoomsAvailableToday(this.date));
  }
}

export default BookingRepo;
<file_sep>/test/bookingRepo-test.js
const expect = chai.expect;

import BookingRepo from '../src/BookingRepo'
import chai from 'chai';
import spies from "chai-spies";
import data from '../data'
import domUpdates from '../src/domUpdates';
chai.use(spies)

describe("bookingRepo", function() {

  let bookingRepo 

  beforeEach(function (){
      bookingRepo = new BookingRepo(data, data, data,'2019/08/29')
  })

  it.only("should return true", function() {
    expect(true).to.equal(true);
  })

  it.only('should filter the rooms available today', function(){
    expect(bookingRepo.filterRoomsAvailableToday('2019/08/29')).to.be.an('array')
    expect(bookingRepo.filterRoomsAvailableToday('2019/08/29')).to.have.length(49)

  })

  it.only('should sort the rooms available today', function(){
    expect(bookingRepo.sortBookingsByDate('2019/08/29')).to.be.an('array')
    expect(bookingRepo.sortBookingsByDate('2019/08/29')).to.have.length(1)
  })

  it.only('should find a specific room', function(){
    expect(bookingRepo.findCorrectRoom(5)).to.be.an('object')
  })

  it.only('should update the dom', function(){
    bookingRepo.updateToDom()
    expect(domUpdates.displayBookingsForToday).to.have.been.called(6)
    expect(domUpdates.displayRoomsAvailableForToday).to.have.been.called(6)
  })
})<file_sep>/test/roomService-test.js
const expect = chai.expect;

import RoomService from "../src/roomService";
import chai from "chai";
import spies from "chai-spies";
import data from "../data";
import domUpdates from '../src/domUpdates';


chai.use(spies)


describe("roomService", function() {

  let roomService 

  beforeEach(function (){
      roomService = new RoomService(data, null, 5)
  });

  it.only("should return true", function() {
      expect(true).to.equal(true);
  })

  it.only('should create a menu', function(){
      expect(roomService.createMenu()).to.be.an('array')
      expect(roomService.createMenu()).to.have.length(47)
  })

  it.only('should find an item on the menu', function(){
    expect(roomService.findCorrectItem(14.9)).to.be.an('object')
  })

  it.only('should filter all orders by a specific guest', () => {
    roomService.filterAllOrdersBySpecificGuest({id: 4, name: "<NAME>"})
    expect(domUpdates.displayAllOrdersBySpecificGuest).to.have.been.called(1)
  })

  it.only('should find the total cost of all orders by a specific guest', () => {
    roomService.findTotalCostOfAllOrdersBySpecificGuest({id: 4, name: "<NAME>"})
    expect(domUpdates.displayTotalRoomServiceCostForSpecificUser).to.have.been.called(1)
  })
})
<file_sep>/README.md
# Overlook Hotel Management App

Overlook is a mockup of a hotel management app. I used fetched JSON data and a number of Object, Array, String, and Number prototype methods to manipulate the data. This is my first solo project using webpack. I also used jQuery to add things to the DOM and SCSS for styling.

## How to Get it Working

1. Clone down this repo. 
1. Save the dependencies by running `npm install`
1. Enjoy navigating the page.

## How to Run the Tests

1. There are a comprehensive set of mocha/chai tests for all classes, properties, and methods.
1. Run tests by typing npm test in your terminal in your cloned directory.

## Goals and Objectives

1. Implement ES6 classes that communicate to each other as needed.
1. Write modular, reusable code adhereing to SRP
1. Substitution Principle, Interface Segregation Principle, Dependency Inversion Principle, and Test Driven Development.
1. Implement a robust testing environment using Mocha and Chai.
1. Use object and array prototype methods to perform rich data manipulation.
1. Display information on the page while maintaining ability to test class properties and methods.
1. Create a dash that is easy to follow and displays information in a clear and consise way.

![My comp](images/overlook1.png)
![MY comp](images/overlook2.png)
![My comp](images/overlook3.png)
![My comp - GIF](images/OverlookGIF.gif)
<file_sep>/src/roomServiceRepo.js
import domUpdates from "./domUpdates";

class RoomServiceRepo {
  constructor(guests, services, date) {
    this.guests = guests.users
    this.services = services.roomServices;
    this.date = date;
    this.info = this.updateToDom();
  }

  filterOrdersByDate(specDate) {
    return this.services.filter(order => order.date == specDate);
  }

  updateToDom() {
    domUpdates.displayRoomServiceOrdersForToday(
      this.filterOrdersByDate(this.date)
    )
  }
}

export default RoomServiceRepo;
<file_sep>/test/booking-test.js
const expect = chai.expect;

import Booking from '../src/Booking';
import chai from 'chai';
import spies from 'chai-spies';
import data from '../data';
import domUpdates from '../src/domUpdates';

chai.use(spies)

describe("Booking", function() {

  let booking 

  beforeEach(function (){
      booking = new Booking(data, 5,'2019/08/29')
  });

  it.only("should return true", function() {
      expect(true).to.equal(true);
  });

  it.only("should filter all bookings by a specific guest", function() {
    booking.filterAllBookingsBySpecificGuest({id: 4,name: "<NAME>"})
    expect(domUpdates.displayAllBookingsBySpecificGuest).to.have.been.called(1);
  });

  it.only("should find todays booking for a specific guest", function() {
    booking.findTodaysBookingForSpecificGuest({id: 4,name: "<NAME>"})
    expect(domUpdates.displayTodaysBookingForSpecificGuest).to.have.been.called(1);
  });
});

<file_sep>/src/room.js
import domUpdates from "./domUpdates";

class Rooms {
    constructor (bookings, rooms, customers, date){
        this.bookings = bookings.bookings
        this.rooms = rooms
        this.customers = customers
        this.date = date
    }

}

export default Rooms