<div id="app" class="text-black antialiased h-screen flex flex-col">
<!-- HEADER -->
<div class="flex items-center shadow h-16 px-6">
<div class="ion-md-radio-button-on text-4xl text-indigo-600 pr-2 cursor-pointer"
@click="openView('catalog')"></div>
<div class="flex-1 cursor-pointer font-bold uppercase hover:text-gray-700"
@click="openView('catalog')">
Book-a-dinner
</div>
<button class="px-2 ml-2 font-semibold text-gray-500"
:class="{'text-indigo-700': currentView === 'catalog'}"
@click="openView('catalog')">
Catalog
</button>
<button class="px-2 ml-2 font-semibold text-gray-500"
:class="{'text-indigo-700': currentView === 'favs'}"
@click="openView('favs')">
Favorites
</button>
<button class="px-2 ml-2 font-semibold text-gray-500"
:class="{'text-indigo-700': currentView === 'reservs'}"
@click="openView('reservs')">
Reservations
</button>
</div>
<!-- LIST -->
<div class="flex-1 overflow-scroll pb-8" v-if="currentView === 'catalog'">
<div class="text-3xl font-bold px-6 pt-5">Restaurants</div>
<div class="flex flex-wrap px-4 pt-3">
<div v-for="(rest, i) in restaurants"
class="w-1/2 p-2">
<div class="border border-gray-300 rounded">
<div class="h-48 bg-gray-200 cursor-pointer rounded-t overflow-hidden flex items-center"
@click="openDetails(i)">
<img :src="rest.photo">
</div>
<div class="px-4 pt-2 pb-4 flex items-start">
<div class="flex-1">
<div class="hover:text-gray-800 cursor-pointer font-semibold text-lg pt-1"
@click="openDetails(i)">
{{rest.name}}
</div>
<div class="text-gray-500 text-sm">
{{rest.price}}
</div>
</div>
<button class="ion-md-heart text-xl text-gray-300 cursor-pointer p-1"
:class="{'text-pink-600': rest.isFav}"
@click="addToFavs(i)"></button>
</div>
</div>
</div>
</div>
</div>
<!-- DETAILS -->
<div class="flex-1 overflow-scroll flex h-full"
v-if="currentView === 'details'">
<!-- INFO -->
<div class="flex-1"
:class="{'opacity-50': doShowReservSidebar}">
<!-- image -->
<div class="flex items-center h-48 overflow-hidden">
<img :src="restaurants[selectedRestaurant].photo" alt="">
</div>
<!-- header -->
<div class="flex items-center pt-6">
<!-- back and title -->
<div class="flex-1">
<button class="text-indigo-700 px-6 text-sm"
@click="currentView = backFromDetailsTo">
← Back
</button>
<div class="text-3xl font-bold px-6">
{{restaurants[selectedRestaurant].name}}
</div>
</div>
<!-- controls -->
<div class="px-6 flex" v-if="!doShowReservSidebar">
<button class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded font-semibold mr-2"
@click="doShowReservSidebar = true">
Make a reservation
</button>
<button class="flex items-center items-center bg-gray-100 hover:bg-gray-200 px-4 py-2 rounded"
@click="addToFavs(selectedRestaurant)">
<div class="ion-md-heart text-xl text-gray-400"
:class="{'text-pink-600': restaurants[selectedRestaurant].isFav}"></div>
<!-- <div v-if="!restaurants[selectedRestaurant].isFav">Add to favorites</div>
<div v-if="restaurants[selectedRestaurant].isFav">In favorites</div> -->
</button>
</div>
</div>
<!-- text -->
<div class="px-6 pt-6 max-w-lg">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Neque possimus eos qui sapiente itaque iste, illum tempore soluta nisi quas modi? Nesciunt, voluptatem deleniti! Debitis ipsum illo delectus quisquam quas!
</div>
</div>
<!-- RESERVATION SIDEBAR -->
<div class="w-full max-w-sm shadow"
v-if="doShowReservSidebar">
<!-- header -->
<div class="flex px-6 pt-4 items-center">
<div class="flex-1 text-2xl font-bold">
New reservation
</div>
<button class="ion-md-close text-xl text-gray-500 px-2 pt-2 hover:text-indigo-600"
@click="doShowReservSidebar = false"></button>
</div>
<!-- form -->
<div class="px-6">
<div class="pt-6">
<div class="uppercase text-sm text-gray-500">
Party size
</div>
<div class="flex pt-2">
<div v-for="(party,i) in partyOptions"
class="w-12 h-12 flex items-center justify-center border mr-2 cursor-pointer text-gray-500 border-gray-400 font-semibold rounded"
:class="{'border-indigo-600 text-indigo-600 bg-indigo-100': selectedParty === i}"
@click="selectedParty = i">
{{party}}
</div>
</div>
</div>
<div class="pt-6">
<div class="uppercase text-sm text-gray-500">Date</div>
<select v-model="selectedDate" class="border py-2 px-4 mr-2 mt-1 w-56">
<option v-for="date in dateOptions">{{date}}</option>
</select>
</div>
<div class="pt-6">
<div class="uppercase text-sm text-gray-500">Time</div>
<div class="flex pt-2 flex-wrap">
<div v-for="(time,i) in timeOptions"
class="w-12 h-8 flex items-center justify-center border mr-2 mb-2 cursor-pointer text-gray-500 border-gray-400 font-semibold rounded text-sm"
:class="{'border-indigo-600 text-indigo-600 bg-indigo-100': selectedTime === i}"
@click="selectedTime = i">
{{time}}
</div>
</div>
</div>
<button class="bg-indigo-600 hover:bg-indigo-700 text-white w-full py-3 rounded mt-4"
@click="reserve()">
Reserve
</button>
</div>
</div>
</div>
<!-- FAVS -->
<div class="flex-1 overflow-scroll flex-1 overflow-hidden"
v-if="currentView === 'favs'">
<div class="text-3xl font-bold px-6 pt-5">Favourites</div>
<div class="flex flex-wrap px-4 pt-3">
<div v-for="(rest, i) in restaurants"
class="w-1/2 p-2"
v-if="rest.isFav">
<div class="border border-gray-300 rounded">
<div class="h-48 bg-gray-200 cursor-pointer rounded-t overflow-hidden flex items-center"
@click="openDetails(i)">
<img :src="rest.photo">
</div>
<div class="px-4 pt-2 pb-4 flex items-start">
<div class="flex-1">
<div class="hover:text-gray-800 cursor-pointer font-semibold text-lg pt-1"
@click="openDetails(i)">
{{rest.name}}
</div>
<div class="text-gray-500 text-sm">
{{rest.price}}
</div>
</div>
<button class="ion-md-heart text-xl text-gray-300 cursor-pointer p-1"
:class="{'text-pink-600': rest.isFav}"
@click="addToFavs(i)"></button>
</div>
</div>
</div>
</div>
</div>
<!-- RESERVS -->
<div class="flex-1 overflow-scroll flex-1 overflow-hidden"
v-if="currentView === 'reservs'">
<div class="text-3xl font-bold px-6 pt-5 mb-4">Reservations</div>
<div v-for="(reserv, i) in reservations"
class="flex items-center h-24 mx-6 mb-2">
<div class="w-32 h-24 rounded overflow-hidden flex items-center mr-6">
<img :src="restaurants[reserv.restaurant].photo">
</div>
<div class="flex-1">
<div class="text-lg font-semibold">
{{reserv.date}}, {{reserv.time}}
</div>
<div class="">
{{restaurants[reserv.restaurant].name}}
</div>
<div class="text-sm text-gray-500 font-semibold pt-1">
{{reserv.party}}
<span class="ion-md-person"></span>
</div>
</div>
<button class="text-gray-600 hover:text-indigo-600 text-sm font-semibold px-2"
@click="cancel(i)">
Cancel
</button>
</div>
</div>
<!-- CONFIRMATION -->
<div class="flex items-center py-2 bg-pink-800 px-6 text-white"
v-if="doShowReservConfirmation">
<div class="flex-1 font-bold py-3">
🙌 Table booked
</div>
<button class="px-3 py-2 mr-2 text-pink-800 text-sm bg-white rounded"
@click="openView('reservs'); doShowReservConfirmation = false">
Go to reservations
</button>
<button class="px-3 py-2 mr-2 text-pink-300 text-sm bg-pink-700 rounded"
@click="doShowReservConfirmation = false">
Dismiss
</button>
</div>
</div>
var app = new Vue({
el: '#app',
data: {
currentView: 'catalog',
backFromDetailsTo: '',
selectedRestaurant: 1,
doShowReservSidebar: false,
doShowReservConfirmation: false,
restaurants: [
{
name: 'Bread and Breakfast',
price: '$$',
photo: 'https://images.unsplash.com/photo-1482049016688-2d3e1b311543?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=953&q=80',
isFav: false
},
{
name: 'The Sober Clam',
price: '$$$$',
photo: 'https://images.unsplash.com/photo-1502301103665-0b95cc738daf?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1300&q=80',
isFav: true
},
{
name: 'Salaterio',
price: '$$',
photo: 'https://images.unsplash.com/photo-1551218372-a8789b81b253?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80',
isFav: true
},
{
name: 'Sega Mega Bar',
price: '$',
photo: 'https://images.unsplash.com/photo-1514134583630-250e42c36dbd?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80',
isFav: false
},
{
name: 'Eight 9 Tin',
price: '$$$',
photo: 'https://images.unsplash.com/photo-1517644493876-7864565e3bf9?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60',
isFav: false
},
{
name: 'Red Green Bite',
price: '$$',
photo: 'https://images.unsplash.com/photo-1542814812-992b90017061?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60',
isFav: false
},
],
reservations: [],
//
// reservation form:
partyOptions: ['1', '2', '3', '4', '5+'],
selectedParty: 1,
dateOptions: ['Today, Apr 9', 'Tomorrow, Apr 10', 'Monday, Apr 11', 'Tuesday, Apr 12', 'Wednesday, Apr 13'],
selectedDate: 'Today, Apr 9',
timeOptions: ['12:00', '12:30', '1:00', '1:30', '2:00', '2:30', '3:00', '3:30', '4:00', '4:30', '5:00', '5:30', '6:00', '6:30', '7:00', '7:30', '8:00', '8:30', '9:00', '9:30', '10:00', '10:30', '11:00'],
selectedTime: 12,
},
methods: {
openView (viewName) {
this.currentView = viewName
this.doShowReservSidebar = false
},
openDetails (index) {
this.selectedRestaurant = index
this.backFromDetailsTo = this.currentView
this.currentView = 'details'
},
addToFavs (index) {
this.restaurants[index].isFav = !this.restaurants[index].isFav
},
reserve () {
this.reservations.push({
restaurant: this.selectedRestaurant,
party: this.partyOptions[this.selectedParty],
date: this.selectedDate,
time: this.timeOptions[this.selectedTime]
})
this.doShowReservConfirmation = true
this.doShowReservSidebar = false
},
cancel (index) {
this.reservations.splice(index, 1)
}
}
})