iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 28
0
自我挑戰組

花三十天找到 JavaScript 沙漠中的綠洲系列 第 28

28 製作訂房網站(上):頁面傳遞

前言

在這個系列的最後,要利用六角學院的 API 製作訂房網站。要使用 API 必須要註冊,並取得自己的 token 。基於安全考量,我的 token 就不放上來了,但下面會記錄寫法,希望對你有所幫助。

概念

概念是這樣,我想要做兩個畫面,一個是主頁,列出所有房型;另一個是房型頁,看我在主頁點擊哪個房型,就跳出哪個房型的詳細資料。

畫面如下:

實作

可想而知我至少會需要四個檔案: index.html / index.js / room.html / room.js

  • index.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>製作訂房網站</title>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
	<div class = "wrap">
  		<ul class = "room"></ul>
	</div>
  	<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  	<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
  	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
	<script src="index.js"></script> 
</body>
</html>

這裡應該沒有問題,帶入一些該載入的 js ,並且額外載入了 boostrap 的 css 和 js 設定檔,規劃一下等等從 API 那抓到的東西要放在哪裡。

  • index.js
const api = 'https://challenge.thef2e.com/api/thef2e2019/stage6/rooms';
const room = document.querySelector('.room');

let data = [];

axios.defaults.headers.common["Authorization"] = `Bearer 把註冊得到的token放在這裡` 

axios.get(api).then((res) =>{ 
  this.data = res.data.items;
  render(data);
});

function render(){
  let str = "";
  this.data.forEach((item) =>{ 
    str +=`
    <div class="col-md-4 col-sm-6 mb-3"> 
      <div class="card rounded h-100">
          <h2 class="card-header text-center" >${item.name}</h2>
          <div style="height: 250px; background-size: cover; background-position: center; background-image: url(${item.imageUrl}"></div>
          <p>平日價格: ${item.normalDayPrice} 元</p>
          <p>假日價格: ${item.holidayPrice} 元</p>
          <a href="room.html?id=${item.id}" data-id="${item.id}" class="detail btn btn-outline-primary btn-block">詳細資料</a> 
      </div>
    </div>
    `;    
  });
  room.innerHTML = str; 

運用之前學到的 axios.get ,取出抓到的 API 裡需要的資料,分別放進該放的位置。

  • room.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>製作訂房網站</title>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
	<div class="container mt-5">
    	<div class="roomDetail">
      		<div id="carouselControls" class="carousel slide" data-ride="carousel"></div>
        	<div class="carousel-inner"></div>
        	<a class="carousel-control-prev" href="#carouselControls" role="button" data-slide="prev">
          		<span class="carousel-control-prev-icon" aria-hidden="true"></span>
          		<span class="sr-only">Previous</span>
        	</a>
        	<a class="carousel-control-next" href="#carouselControls" role="button" data-slide="next">
          		<span class="carousel-control-next-icon" aria-hidden="true"></span>
          		<span class="sr-only">Next</span>
        	</a>
      	</div>
      	<div class="roomInfo"></div> <!--放從別的網站抓到的房型細節-->
      	<div class="amenitiesInfo row bg-light mb-5"></div> <!--放房間設備圖示-->
    </div>
	<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
  	<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
  	<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
	<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
	<script src="room.js"></script>
</body>
</html>

同上 index.html ,也是規畫該把東西放哪並載入該載的檔案。

  • room.js
const id = location.search.split("=")[1];
const imgCarousel = document.querySelector(".carousel-inner");
const roomInfo = document.querySelector(".roomInfo");
const amenitiesInfo = document.querySelector(".amenitiesInfo");
const api = `https://challenge.thef2e.com/api/thef2e2019/stage6/room/${id}`; 

let roomData = [];

axios.defaults.headers.common["Authorization"] = `Bearer 把註冊得到的token放在這裡`

axios.get(api).then((res) =>{
  roomData = res.data.room[0];
  imageCard(roomData); //照片切換功能
  infoCard(roomData); //內容介紹
  amenitiesCard(roomData); //設備介紹
});

function imageCard() { //照片切換功能
  const image = roomData.imageUrl;
  imgCarousel.innerHTML = `
    <div class="carousel-item active">
      <img class="d-block w-100" src="${image[0]}" alt="First slide"
        style="height: 500px; object-fit: cover;">
    </div>
    <div class="carousel-item">
      <img class="d-block w-100" src="${image[1]}" alt="Second slide"
        style="height: 500px; object-fit: cover;">
    </div>
    <div class="carousel-item">
      <img class="d-block w-100" src="${image[2]}" alt="Third slide"
        style="height: 500px; object-fit: cover;">
    </div>
    `;
}

function infoCard() { //內容介紹
  roomInfo.innerHTML = `
  <h3>${roomData.name}</h3>
  <p>${roomData.description}</p>
  <ul>
    <li>人數限制: ${roomData.descriptionShort.GuestMin} ~ ${roomData.descriptionShort.GuestMax}</li>
    <li>床型: ${roomData.descriptionShort.Bed[0]}</li>
    <li>衛浴: ${roomData.descriptionShort["Private-Bath"]} 間 </li>
    <li>房間大小: ${roomData.descriptionShort.Footage} 平方公尺 </li>
  </ul>
  <p>Check In: ${roomData.checkInAndOut.checkInEarly} ~ ${roomData.checkInAndOut.checkInLate}</p>
  <p>Check Out: ${roomData.checkInAndOut.checkOut}</p>
  <p>平日(一~四)價格: ${(roomData.normalDayPrice)}</p>
  <p>假日(五~日)價格: ${(roomData.holidayPrice)}</p>
  `;
}

function amenitiesCard() { //設備介紹
  amenitiesInfo.innerHTML = `
    <div class="col-lg-4 ${
          !roomData.amenities["Wi-Fi"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-wifi"></i>
      <span class="pl-2">Wi-Fi</span>
    </div>
    <div class="col-lg-4 ${
      !roomData.amenities["Air-Conditioner"] ? "text-muted" : "text-success"
    }">
      <i class="fas fa-wind"></i>
      <span class="pl-2">空調</span>
    </div>
    <div class="col-lg-4 ${
      !roomData.amenities["Breakfast"] ? "text-muted" : "text-success"
    }">
      <i class="fas fa-utensils"></i>
       <span class="pl-2">含早餐</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Child-Friendly"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-baby"></i>
      <span class="pl-2">小孩友善</span>
    </div>
    <div class="col-lg-4 ${
      !roomData.amenities["Pet-Friendly"] ? "text-muted" : "text-success"
    }">
      <i class="fas fa-paw"></i>
      <span class="pl-2">寵物友善</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Great-View"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-mountain"></i>
      <span class="pl-2">漂亮視野</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Mini-Bar"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-glass-cheers"></i>
      <span class="pl-2">Mini Bar</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Refrigerator"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-ice-cream"></i>
      <span class="pl-2">含冰箱</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Room-Service"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-concierge-bell"></i>
      <span class="pl-2">客房服務</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Smoke-Free"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-smoking"></i>
      <span class="pl-2">煙友友善</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Sofa"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-couch"></i>
      <span class="pl-2">含沙發</span>
    </div>
    <div class="col-lg-4 ${
          !roomData.amenities["Television"] ? "text-muted" : "text-success"
        }">
      <i class="fas fa-tv"></i>
      <span class="pl-2">含電視</span>
    </div>
  `;
}

這是四個檔案裡最複雜的。首先利用 spilt() 把等號作為斷點,分離左右兩邊,藉此取得等號右邊的 id ,才去用各自房型的 id 代出我要他帶出的單一產品資料。然後一樣使用 axios.get 抓資料,分別跑下面三個函式:照片切換、內容介紹、設備介紹,接著當然就是分別把資料帶入三個區塊了。

剩下的功能,就讓我們明天繼續...

學習與參考資料

JS 學徒特訓班教學影片及練習題 49-52 關


上一篇
27 Token
下一篇
29 製作訂房網站(下):預約列表
系列文
花三十天找到 JavaScript 沙漠中的綠洲35

尚未有邦友留言

立即登入留言