# 飲料點餐版面(Vue挑戰版)
###### codepen在這邊:https://codepen.io/liu_0821/pen/rNrWYMP?editors=0010

## 前情提要
#### 額外增加的內容
##### 1. 刪除單筆訂單
#### 這版之後打算再多增加幾項功能~~~~~
##### 1. 可以修改訂單
##### 2. 當訂單產生後,重新點選品項,訂單產生畫面即可隱藏起來
#### 一樣下方都有註解,直接看下方程式碼瞜
## HTML
```
<div id="app">
<div class="container gx-2">
<div class="row gx-3 bg-light py-3">
<div class="col-md-4">
<div class="list-group">
<a
href="#"
class="list-group-item list-group-item-action"
@click.prevent="selectedItem(item)"
v-for="(item,key) in products"
:key="item.name"
:class="{'active':selectProduct.name === item.name}"
>
<h6 class="card-title mb-1">{{item.name}}</h6>
<div
class="d-flex align-items-center justify-content-between"
>
<p class="mb-0"><small>{{item.engName}}</small></p>
<p class="mb-0"><small>NT$ {{item.price}}</small></p>
</div>
</a>
</div>
</div>
<div class="col-md-8">
<div class="card mb-2">
<div
v-if="!selectProduct.name "
class="position-absolute text-white d-flex align-items-center justify-content-center"
style="
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.65);
z-index: 100;
"
>
請先選擇飲品
</div>
<div class="card-body px-4">
<div class="mb-3">
<label for="productNum" class="form-label">數量</label>
<input
type="number"
class="form-control"
id="productNum"
placeholder="數量"
min="1"
v-model="selectProduct.count"
/>
</div>
<div class="mb-3">
<label for="productNum" class="form-label d-block"
>冰塊*</label
>
<div
class="form-check form-check-inline"
v-for="(item,key) in iceType"
:key="'ice'+ key"
>
<input
class="form-check-input"
name="iceType"
type="radio"
:value="item"
:id="'ice'+ key"
v-model="selectProduct.ice"
:disabled="!selectProduct.hasOwnProperty('defaults') || (selectProduct.defaults.ice !== '' && selectProduct.defaults.ice !== item)"
/>
<!--hasOwnProperty 測試屬性是否存在-->
<label class="form-check-label" :for="'ice'+ key"
>{{item}}</label
>
</div>
</div>
<div class="mb-3">
<label for="productNum" class="form-label d-block"
>甜度*</label
>
<div
class="form-check form-check-inline"
v-for="(item,key) in sugarType"
:key="'sugar'+ key"
>
<input
class="form-check-input"
name="sugarType"
type="radio"
:id="'sugar'+ key"
:value="item"
v-model="selectProduct.sugar"
:disabled="!selectProduct.hasOwnProperty('defaults') || (selectProduct.defaults.sugar !== '' && selectProduct.defaults.sugar !== item)"
/>
<label class="form-check-label" :for="'sugar'+ key"
>{{item}}</label
>
</div>
</div>
<div class="mb-3">
<label for="productNum" class="form-label d-block"
>加料</label
>
<div
class="form-check form-check-inline"
v-for="(item,key) in toppingsType"
:key="'topping'+key"
>
<input
class="form-check-input"
type="checkbox"
:id="'topping'+key"
:value="item"
v-model="selectProduct.topping"
:disabled="!selectProduct.hasOwnProperty('defaults') || selectProduct.defaults.toppings.includes(item)"
/>
<label class="form-check-label" :for="'topping'+key"
>{{item}}</label
>
</div>
</div>
<div class="mb-3">
<label for="productNotice" class="form-label"
>備註</label
>
<textarea
class="form-control"
id="productNotice"
rows="2"
v-model="selectProduct.text"
></textarea>
</div>
<div class="d-flex gap-2">
<button
class="btn btn-outline-primary w-100"
type="button"
>
取消
</button>
<button
class="btn btn-primary w-100"
@click.prevent="addToShoppingCart(selectProduct)"
type="button"
>
加入
</button>
</div>
</div>
</div>
<div class="card">
<div class="card-body">
<table class="table">
<thead>
<tr>
<th scope="col">品項</th>
<th scope="col">冰塊</th>
<th scope="col">甜度</th>
<th scope="col">加料</th>
<th scope="col">單價</th>
<th scope="col">數量</th>
<th scope="col">小計</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr v-for="(item,key) in orderList" :key="'key'+key">
<th scope="row">
{{item.name}}<br />
<small class="text-muted fw-normal"
>備註:{{item.text}}</small
>
</th>
<td>{{item.ice}}</td>
<td>{{item.sugar}}</td>
<td>{{item.topping.toString()}}</td>
<td>{{item.price + item.topping.length*10}}</td>
<td>{{item.count}}</td>
<td>{{item.total}}</td>
<td
class="text-end"
@click.prevent="deleteOrder(item)"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
class="bi bi-x"
viewBox="0 0 16 16"
>
<path
d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"
/>
</svg>
</td>
</tr>
</tbody>
</table>
<p class="text-end">共 NT$ {{totalPrice}} 元</p>
<div class="d-flex gap-2">
<button
class="btn btn-sm btn-outline-secondary w-100"
@click.prevent="clearOrder"
>
清空購物車
</button>
<button
class="btn btn-sm btn-secondary w-100"
@click.prevent="outputOrder(orderList,totalPrice)"
:disabled="orderList.length === 0"
>
產生訂單
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div
class="bg-light p-3 mt-3"
v-if="checkedOrder.orders.length >0 "
>
<div
class="bg-white p-3 d-flex flex-column"
style="min-height: 450px"
>
<table class="table">
<thead>
<tr>
<th scope="col">品項</th>
<th scope="col">冰塊</th>
<th scope="col">甜度</th>
<th scope="col">加料</th>
<th scope="col">單價</th>
<th scope="col">數量</th>
<th scope="col">小計</th>
</tr>
</thead>
<tbody>
<tr v-for="(item,id) in checkedOrder.orders" :key="'id'+id">
<th scope="row">
{{item.name}}<br />
<small class="text-muted fw-normal"
>備註:{{item.text}}</small
>
</th>
<td>{{item.ice}}</td>
<td>{{item.sugar}}</td>
<td>{{item.topping.toString()}}</td>
<td>{{item.price + item.topping.length*10}}</td>
<td>{{item.count}}</td>
<td class="text-end">{{item.total}}</td>
</tr>
</tbody>
</table>
<p class="mt-3 mb-1">訂單成立時間:{{checkedOrder.date}}</p>
<p class="mb-1">餐點數: {{checkedOrder.orderCount}}</p>
<p class="mb-1">付款狀態:未付款</p>
<p class="text-end mt-auto">
共 NT$ {{checkedOrder.checkOrderPrice}} 元
</p>
</div>
</div>
</div>
```
## JS(Vue)
> `selectProduct` 放被選擇的項目
`orderList` 購物車
`totalPrice` 總價
`checkedOrder` 結帳
```
const App = {
data() {
return {
selectProduct: {},
orderList: [],
checkedOrder: {
orders: [],
date: "",
orderCount: 1,
checkOrderPrice: "",
},
iceType: ["正常冰", "少冰", "微冰", "去冰", "熱"],
sugarType: ["全糖", "七分", "半糖", "三分", "無糖"],
toppingsType: ["珍珠", "粉條", "小粉圓", "椰果", "芋頭"],
products: [
{
name: "珍珠鮮奶茶",
engName: "Pearl Milk Tea",
price: 60,
defaults: {
toppings: ["珍珠"],
sugar: "",
ice: "",
},
},
{
name: "椰果鮮奶茶",
engName: "Coconut Milk Tea",
price: 60,
defaults: {
toppings: ["椰果"],
sugar: "",
ice: "",
},
},
{
name: "鮮奶茶",
engName: "Milk Tea",
price: 50,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
{
name: "古意冬瓜茶 (糖固定)",
engName: "Winter Melon Drink",
price: 30,
defaults: {
toppings: [""],
sugar: "全糖",
ice: "",
},
},
{
name: "蜜香紅茶",
engName: "Black Tea",
price: 30,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
{
name: "包種青茶",
engName: "Black Tea",
price: 35,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
{
name: "檸檬烏龍",
engName: "Lemon Oolong Tea",
price: 55,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
{
name: "薑母茶 (熱飲)",
engName: "Ginger Tea",
price: 55,
defaults: {
toppings: [""],
sugar: "",
ice: "熱",
},
},
{
name: "青草茶",
engName: "Herbal Tea",
price: 35,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
{
name: "金桔檸檬",
engName: "Kumquat Lemonade",
price: 40,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
{
name: "柳澄青茶",
engName: "Orange Mountain Tea",
price: 45,
defaults: {
toppings: [""],
sugar: "",
ice: "",
},
},
],
};
},
methods: {
selectedItem(product) {
this.selectProduct = {
...product,
count: 1,
ice:
product.defaults.ice !== ""
? product.defaults.ice
: "正常冰",
sugar:
product.defaults.sugar !== ""
? product.defaults.sugar
: "全糖",
text: "", // 備註
topping: [], // 加料
};
},
addToShoppingCart(selectProduct) {
const order = {
...selectProduct,
total:
(selectProduct.price +
selectProduct.topping.length * 10) *
selectProduct.count,
};
this.orderList.push(order);
this.resetOrder(); // 加入購物車後清空
this.countTotal(); // 計算總價
},
countTotal() {
this.totalPrice = 0;
this.orderList.forEach((item) => {
this.totalPrice += item.total;
});
},
clearOrder() {
this.totalPrice = 0;
this.orderList.length = 0;
// 也可以這樣寫 this.orderList = [];
},
outputOrder(orders, total) {
const date = new Date().toLocaleString(); // 訂單時間
const orderCount = orders.length;
this.checkedOrder.date = date;
this.checkedOrder.orders = orders;
this.checkedOrder.orderCount = orderCount;
this.checkedOrder.checkOrderPrice = total;
this.orderList = [];
this.resetOrder();
},
resetOrder() {
this.selectProduct = {};
},
deleteOrder(item) {
this.orderList.splice(this.orderList.indexOf(item), 1);
},
},
};
Vue.createApp(App).mount("#app");
```
## 後續補充
#### 耶補充一下新增的功能 / 修改的部分
#### 一、點選品項會把下方的訂單區塊隱藏起來
##### 在點選品項時,觸發`selectedItem`去清除目前訂單的資料`this.checkedOrder.orders.length = 0`,如此一來`v-if`的判斷式就會觸發~~
#### 二、修改個別訂單資料
##### 目前還是先用比較簡單的版本哈,在前面[選我](https://hackmd.io/@LindaLiu/HkPXfG-cs)也有提到的方式來做修改訂單的部分~
#### 更新版本會另外放一篇筆記做個紀錄~~~
#### [更新版本在這裡~](https://hackmd.io/@LindaLiu/Hyb8hlrqi)
---
#### ヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)ノヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)人
##### 以上 如果註解哪裡有錯誤或有問題,歡迎提出來一起討論~~~~