如何實作:同一題的restful api或action擇一實作即可,任何return null的action視為未實作,這時會自動改為呼叫api。
api實作說明:會將資料傳入body,請根據body的資料完成指定動作。某些url有類似 ":" 的路徑,代表的就是param( ex. :menuId => [menuId] )。
action說明: 若該題有body,則會將body傳入第一個參數(ex.1)。若該題有param,則會看有沒有body後決定填入第一或第二個參數(ex.2, ex.3)
ex.1 只有body:addOrder(body);
ex.2 body, params 皆有:editOrderStatus(body, orderId);
ex.3 只有param:getCustomerOrder(customerId);
ex.4 皆沒有:getPendingOrders();
實作MQTT步驟說明:
1.在指定的地方呼叫publishMessage(topic, message)
2. 指定的topic都可以在"/utils/mqttTopic.ts"找到。
ex. 若要實作 /chekcout 頁面的getOrderCheckoutTopic();
import { getOrderCheckoutTopic } from "@/utils/mqttTopic";
然後const topic = getOrderCheckoutTopic();
並呼叫publishMessage(topic, JSON.stringify(your_message_object));
管理員上傳菜單圖片 ( 2分 )
在 /admin/menu 上傳圖片。對應的action:uploadMenuImage
/api/image/upload
Body:
{
"file": "上傳的圖片"
}
備註:body是formData,欄位名稱是"file"
Response:
{
"success": true,
"url": "imgUrl"
}
備註:可利用try catch,把失敗的api回傳為"success": false
管理員新增菜單( 1分 )
在 /admin/menu 新增菜單。對應的action:addMenuItem
/api/menu
Body:
{
"name": "餐點名稱",
"description": "餐點敘述",
"price": 50,
"imageUrl": "imgUrl",
"isAvailable": true
}
Response:
{
"id": "menuId",
"name": "餐點名稱",
"description": "餐點敘述",
"price": 50,
"imageUrl": "imgUrl",
"isAvailable": true
}
管理員編輯菜單( 1分 )
在 /admin/menu 編輯菜單。對應的action:editMenuItem
/api/menu/:menuId
Body:
{
"name": "新餐點名稱",
"description": "新餐點敘述",
"price": 35,
"imageUrl": "newImgUrl",
"isAvailable": true
}
Response:
{
"id": "menuId",
"name": "新餐點名稱",
"description": "新餐點敘述",
"price": 35,
"imageUrl": "newImgUrl",
"isAvailable": true
}
取得所有菜單( 1分 )
在 /admin/menu 和 /menu 取得菜單。對應的action:getMenuItems
/api/menu
Response:
[
{
"id": "menuItemId",
"name": "餐點名稱",
"description": "餐點敘述",
"price": 35,
"imageUrl": "imgUrl",
"isAvailable": true
}
]
顧客下單( 2分 )
在 /checkout 下單。依照body新增一筆order及對應的orderItems。對應的action:addOrder
/api/orders
Body:
{
"customerId": "customerId",
"orderItems": [
{
"menuItemId": "menuItemId",
"quantity": 1,
"specialRequest": "備註"
}
]
}
Response:
{
"id": "orderId",
"customerId": "customerId",
"totalAmount": 35,
"customer": {
"name": "customerName"
},
"items": [
{
"menuItemId": "menuItemId",
"quantity": 1,
"specialRequest": "餐點備註",
"menuItem": {
"name": "餐點名稱",
"price": 35
}
}
],
"status": "PENDING",
"createdAt": "2025-06-10T14:19:40.204Z"
}
顧客下單(2分)
在 /checkout 實作,staff就可以即時收到訂單更新。
MQTT
topic: getOrderCheckoutTopic();
Message:
{
"id": "orderId",
"customerId": "customerId",
"totalAmount": 35,
"customer": {
"name": "customerName"
},
"items": [
{
"menuItemId": "menuItemId",
"quantity": 1,
"specialRequest": "餐點備註",
"menuItem": {
"name": "餐點名稱",
"price": 35
}
}
],
"status": "PENDING",
"createdAt": "2025-06-10T14:19:40.204Z"
}
備註:顧客下單api的response就是message
取得顧客訂單( 2分 )
在 /orders 取得顧客訂單。對應的action:getCustomerOrder
/api/orders/customers/:customerId
Response:
[
{
"id": "orderid",
"customerId": "customerId",
"status": "PENDING",
"totalAmount": 80,
"createdAt": "2025-06-07T06:58:35.725Z",
"items": [
{
"id": "orderItemId",
"orderId": "orderId",
"menuItemId": "menuItemId",
"quantity": 1,
"specialRequest": "餐點備註",
"createdAt": "2025-06-07T06:58:35.725Z",
"menuItem": {
"name": "餐點名稱",
"price": 35
}
}
]
}
]
備註:nested relations prisma 提示:連結
根據status更改訂單狀態( 1分 )
在訂單狀態更改時呼叫。對應的action:editOrderStatus
/api/orders/:orderId/status
Body:
{
"status": "PENDING"
}
Response:
{}
備註:成功時回傳空物件即可
接受訂單,傳送通知給顧客 ( 2分 )
在 /pending 頁面實作。顧客就能即時收到通知。
MQTT
topic: getAcceptCustomerOrderTopic(customerId);
Message:
{
"id": " notificationRes.id ",
"title": "訂單",
"type": "order",
"content": " 訂單 ${orderId.slice(0, 8)} 正在製作中 ",
"read": false,
"time": " new Date().toLocaleString() ",
"status": "PREPARING",
"orderId": " orderId "
}
備註:除了title,type,read,status不用改以外,其他稍微修正一下就可以了
接受訂單,傳送通知給廚房 ( 2分 )
在 /pending 頁面實作。廚房就能即時收到訂單。
MQTT
topic: getKitchenOrderTopic();
Message:
{
"id": "orderId",
"customerId": "customerId",
"status": "PENDING",
"totalAmount": 35,
"createdAt": "2025-06-11T06:17:58.171Z",
"customer": {
"name": "customerName"
},
"items": [
{
"id": "orderItemId",
"quantity": 1,
"specialRequest": null,
"createdAt": "2025-06-11T06:17:58.171Z",
"menuItem": {
"name": "餐點名稱",
"price": 35
}
}
]
}
備註:這一筆message其實就是其中一筆order。使用orders.find就可以找到了
取得所有待處理訂單( 2分 )
在 /orders/pending 取得待處理訂單。對應的action:getPendingOrders
/api/orders/pending
Response:
[
{
"id": "orderId",
"customerId": "customerId",
"status": "PENDING",
"totalAmount": 80,
"createdAt": "2025-06-07T06:58:35.725Z",
"customer": {
"name": "customerName"
},
"items": [
{
"id": "orderItemId",
"quantity": 1,
"specialRequest": null,
"createdAt": "2025-06-07T06:58:35.725Z",
"menuItem": {
"name": "經典蛋餅",
"price": 35
}
}
]
}
]
備註:nested relations prisma 提示:連結
新增通知( 1分 )
在訂單變成PREPARING/READY時會呼叫。對應的action:addNotification
/api/notifications/users/:userId
Body:
{
"orderId": "orderId",
"message": "訊息內容"
}
Response:
{
"id": "notificationId",
"userId": "userId",
"orderId": "orderId",
"message": "訊息內容",
"isRead": false,
"createdAt": "2025-06-10T17:26:58.507Z",
"items": [
{
"menuItem": {
"id": "menuItemId",
"name": "經典蛋餅"
},
"quantity": 1,
"specialRequest": null
}
],
"customer": {
"name": "customerName"
}
}
備註:先notification.create再order.findUnique,然後把兩個資料整理後回傳。
取得使用者通知( 1分 )
在 hook/useNotifications呼叫。對應的action:getUserNotification
/api/notifications/users/:userId
Response:
[
{
"id": "notificationId",
"userId": "userId",
"orderId": "orderId",
"message": "message content",
"isRead": false,
"createdAt": "2025-06-08T09:17:50.558Z"
}
]
刪除通知( 1分 )
在component/notifyButton呼叫。對應action:deleteNotification
/api/notifications/:notificationId
Response:
{}
備註:成功時回傳空物件即可
取得廚房訂單( 2分 )
在 /kitchen 取得廚房訂單。對應action:getKitchenOrders
/api/orders/kitchen
Response:
[
{
"id": "orderId",
"customerId": "customerId",
"status": "PREPARING",
"totalAmount": 80,
"createdAt": "2025-06-07T06:58:35.725Z",
"items": [
{
"id": "orderItemId",
"quantity": 1,
"specialRequest": "餐點備註",
"menuItem": {
"id": "menuItemId",
"name": "餐點名稱",
"description": "餐點敘述",
"price": 35,
"imageUrl": "imgUrl",
"isAvailable": true
}
}
]
}
]
備註:nested relations prisma 提示:連結
取得製作完成的訂單( 2分 )
在 /orders/ready 取得完成的訂單。對應的action:getReadyOrders
/api/orders/ready
Response:
[
{
"id": "orderId",
"status": "READY",
"totalAmount": 80,
"createdAt": "2025-06-08T09:17:33.585Z",
"customer": {
"name": "customerName"
},
"items": [
{
"id": "orderItemId",
"quantity": 1,
"specialRequest": "餐點備註",
"menuItem": {
"name": "餐點名稱",
"price": 45
}
}
]
}
]
備註:nested relations prisma提示:連結
獲取訂單資訊 ( 1分 )
在 /orders/ready 取得訂單詳細資訊。對應的action:getOrderById
/api/orders/:orderId
Response:
{
"id": "orderId",
"customerId": "customerId",
"status": "COMPLETED",
"totalAmount": 35,
"createdAt": "2025-06-10T17:26:44.590Z",
"updatedAt": "2025-06-10T17:32:29.246Z",
"paymentStatus": false,
"completedAt": null,
"items": [
{
"id": "orderItemId",
"orderId": "orderId",
"menuItemId": "menuItemId",
"quantity": 1,
"specialRequest": null,
"createdAt": "2025-06-10T17:26:44.590Z"
}
],
"customer": {
"id": "customerId",
"email": "customer@gmail.com",
"emailVerified": null,
"name": "customerName",
"password": "password",
"role": "CUSTOMER",
"image": null,
"createdAt": "2025-05-27T23:29:40.605Z",
"updatedAt": "2025-05-27T23:29:40.605Z"
}
}