DeepLearning101 commited on
Commit
f401a2c
·
verified ·
1 Parent(s): b291721

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -12
app.py CHANGED
@@ -1,8 +1,11 @@
1
  import gradio as gr
2
- from datetime import datetime, timedelta
3
  import os
4
  import requests
5
  from supabase import create_client, Client
 
 
 
 
6
 
7
  # --- 1. 連線設定 ---
8
  # 請確認 HF Secrets 裡都有設定這些變數
@@ -20,7 +23,8 @@ else:
20
  # --- 2. 輔助函式 (日期與時間) ---
21
  def get_date_options():
22
  options = []
23
- today = datetime.now()
 
24
  weekdays = ["(一)", "(二)", "(三)", "(四)", "(五)", "(六)", "(日)"]
25
  for i in range(30):
26
  current_date = today + timedelta(days=i)
@@ -56,7 +60,7 @@ def send_line_notify(data):
56
  if not LINE_ACCESS_TOKEN or not LINE_ADMIN_ID:
57
  return
58
 
59
- # 簡單的文字通知 (您也可以換回之前的 Flex Message)
60
  message = (
61
  f"🔥 新訂位通知 🔥\n"
62
  f"姓名:{data['name']}\n"
@@ -87,6 +91,23 @@ def handle_booking(name, tel, email, date_str, time, pax, remarks):
87
  if not name or not tel or not date_str or not time:
88
  return "⚠️ 請完整填寫必填欄位 (姓名、電話、日期、時間)"
89
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  data = {
91
  "name": name,
92
  "tel": tel,
@@ -99,17 +120,21 @@ def handle_booking(name, tel, email, date_str, time, pax, remarks):
99
  }
100
 
101
  try:
102
- # 1. 寫入資料庫
103
  supabase.table("bookings").insert(data).execute()
104
 
105
- # 2. 發送 LINE
106
  send_line_notify(data)
107
 
 
108
  return """
109
  <div style='text-align: center; color: #fff; padding: 20px; border: 1px solid #d4af37; border-radius: 8px; background: #222;'>
110
  <h2 style='color: #d4af37; margin: 0;'>Request Received</h2>
111
  <p style='margin: 10px 0;'>🥂 預約申請已提交</p>
112
- <p style='font-size: 0.9em; color: #aaa;'>請留意您的 Email 確認信。</p>
 
 
 
113
  </div>
114
  """
115
  except Exception as e:
@@ -117,21 +142,22 @@ def handle_booking(name, tel, email, date_str, time, pax, remarks):
117
  return f"❌ 系統錯誤: {str(e)}"
118
 
119
  # --- 5. 核心邏輯:處理確認連結 (Webhook) ---
 
120
  def check_confirmation(request: gr.Request):
121
  """
122
- 當網址帶有 ?id=xx&action=confirm 時觸發
123
  """
124
  if not request: return ""
125
  params = request.query_params
126
  action = params.get('action')
127
  bid = params.get('id')
128
 
 
129
  if action == 'confirm' and bid:
130
  try:
131
  # 更新資料庫狀態
132
  supabase.table("bookings").update({"status": "顧客已確認"}).eq("id", bid).execute()
133
 
134
- # 回傳給前端顯示的確認訊息
135
  return f"""
136
  <script>
137
  document.addEventListener('DOMContentLoaded', function() {{
@@ -145,6 +171,27 @@ def check_confirmation(request: gr.Request):
145
  except Exception as e:
146
  print(f"Confirm Error: {e}")
147
  return ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  return ""
149
 
150
  # --- 6. 介面設定 (Theme & CSS) ---
@@ -197,14 +244,12 @@ with gr.Blocks(theme=theme, css=custom_css, title="Booking") as demo:
197
  with gr.Column():
198
  gr.Markdown("### 📅 預約資訊 Booking Info")
199
 
200
- # --- 之前漏掉的 Date & Pax ---
201
  date_options = get_date_options()
202
  booking_date = gr.Dropdown(choices=date_options, label="選擇日期 Select Date", interactive=True)
203
  pax_count = gr.Slider(minimum=1, maximum=10, value=2, step=1, label="用餐人數 Guest Count")
204
 
205
  with gr.Column():
206
  gr.Markdown("### 🕰️ 選擇時段 Time Slot")
207
- # --- 之前漏掉的 Status & Time ---
208
  status_box = gr.Markdown("請先選擇日期...", visible=True)
209
  time_slot = gr.Dropdown(choices=[], label="可用時段 Available Time", interactive=True)
210
 
@@ -216,9 +261,8 @@ with gr.Blocks(theme=theme, css=custom_css, title="Booking") as demo:
216
  cust_name = gr.Textbox(label="訂位姓名 Name *", placeholder="ex. 王小明")
217
  cust_tel = gr.Textbox(label="手機號碼 Phone *", placeholder="ex. 0912-xxx-xxx")
218
 
219
- # --- 新增的 Email 與 備註 ---
220
  with gr.Row():
221
- cust_email = gr.Textbox(label="電子信箱 E-mail (接收確認 E-Mail用)", placeholder="example@gmail.com")
222
  with gr.Row():
223
  cust_remarks = gr.Textbox(label="備註 Remarks (過敏/慶生/特殊需求)", lines=2)
224
 
 
1
  import gradio as gr
 
2
  import os
3
  import requests
4
  from supabase import create_client, Client
5
+ from datetime import datetime, timedelta, timezone
6
+
7
+ # 設定台北時區
8
+ TAIPEI_TZ = timezone(timedelta(hours=8))
9
 
10
  # --- 1. 連線設定 ---
11
  # 請確認 HF Secrets 裡都有設定這些變數
 
23
  # --- 2. 輔助函式 (日期與時間) ---
24
  def get_date_options():
25
  options = []
26
+ # 這裡一定要加時區,不然會抓到 UTC 時間
27
+ today = datetime.now(TAIPEI_TZ)
28
  weekdays = ["(一)", "(二)", "(三)", "(四)", "(五)", "(六)", "(日)"]
29
  for i in range(30):
30
  current_date = today + timedelta(days=i)
 
60
  if not LINE_ACCESS_TOKEN or not LINE_ADMIN_ID:
61
  return
62
 
63
+ # 簡單的文字通知
64
  message = (
65
  f"🔥 新訂位通知 🔥\n"
66
  f"姓名:{data['name']}\n"
 
91
  if not name or not tel or not date_str or not time:
92
  return "⚠️ 請完整填寫必填欄位 (姓名、電話、日期、時間)"
93
 
94
+ # --- 1. 防呆機制:檢查是否重複提交 ---
95
+ try:
96
+ # 搜尋該電話在該時段的訂單
97
+ existing = supabase.table("bookings").select("id")\
98
+ .eq("tel", tel)\
99
+ .eq("date", date_str)\
100
+ .eq("time", time)\
101
+ .neq("status", "顧客已取消")\
102
+ .execute()
103
+
104
+ if existing.data and len(existing.data) > 0:
105
+ return "⚠️ 系統偵測到您已預約過此時段,請勿重複提交。"
106
+ except Exception as e:
107
+ print(f"Check duplicate error: {e}")
108
+ pass
109
+
110
+ # --- 準備資料 ---
111
  data = {
112
  "name": name,
113
  "tel": tel,
 
120
  }
121
 
122
  try:
123
+ # 2. 寫入資料庫
124
  supabase.table("bookings").insert(data).execute()
125
 
126
+ # 3. 發送 LINE 通知
127
  send_line_notify(data)
128
 
129
+ # 4. 回傳成功訊息
130
  return """
131
  <div style='text-align: center; color: #fff; padding: 20px; border: 1px solid #d4af37; border-radius: 8px; background: #222;'>
132
  <h2 style='color: #d4af37; margin: 0;'>Request Received</h2>
133
  <p style='margin: 10px 0;'>🥂 預約申請已提交</p>
134
+ <p style='font-size: 0.9em; color: #aaa;'>系統將發送確認信至您的 Email。</p>
135
+ <p style='font-size: 0.85em; color: #ff5252; margin-top: 5px;'>
136
+ (若未收到,請檢查您的<b>垃圾信件匣</b>)
137
+ </p>
138
  </div>
139
  """
140
  except Exception as e:
 
142
  return f"❌ 系統錯誤: {str(e)}"
143
 
144
  # --- 5. 核心邏輯:處理確認連結 (Webhook) ---
145
+ # ⚠️ 修正重點:這裡是 check_confirmation,不是 send_confirmation_email
146
  def check_confirmation(request: gr.Request):
147
  """
148
+ 當網址帶有 ?id=xx&action=confirm 或 ?id=xx&action=cancel 時觸發
149
  """
150
  if not request: return ""
151
  params = request.query_params
152
  action = params.get('action')
153
  bid = params.get('id')
154
 
155
+ # --- 情況 A: 確認訂位 ---
156
  if action == 'confirm' and bid:
157
  try:
158
  # 更新資料庫狀態
159
  supabase.table("bookings").update({"status": "顧客已確認"}).eq("id", bid).execute()
160
 
 
161
  return f"""
162
  <script>
163
  document.addEventListener('DOMContentLoaded', function() {{
 
171
  except Exception as e:
172
  print(f"Confirm Error: {e}")
173
  return ""
174
+
175
+ # --- 情況 B: 取消訂位 ---
176
+ elif action == 'cancel' and bid:
177
+ try:
178
+ # 更新資料庫狀態
179
+ supabase.table("bookings").update({"status": "顧客已取消"}).eq("id", bid).execute()
180
+
181
+ return f"""
182
+ <script>
183
+ document.addEventListener('DOMContentLoaded', function() {{
184
+ alert('已為您取消訂位 (編號 {bid})');
185
+ }});
186
+ </script>
187
+ <div style='padding:20px; background:#333; border: 1px solid #ff5252; color:#ff5252; text-align:center; margin-bottom:20px; border-radius:8px;'>
188
+ 🚫 訂位已取消。<br>期待您下次有機會再來訪。
189
+ </div>
190
+ """
191
+ except Exception as e:
192
+ print(f"Cancel Error: {e}")
193
+ return ""
194
+
195
  return ""
196
 
197
  # --- 6. 介面設定 (Theme & CSS) ---
 
244
  with gr.Column():
245
  gr.Markdown("### 📅 預約資訊 Booking Info")
246
 
 
247
  date_options = get_date_options()
248
  booking_date = gr.Dropdown(choices=date_options, label="選擇日期 Select Date", interactive=True)
249
  pax_count = gr.Slider(minimum=1, maximum=10, value=2, step=1, label="用餐人數 Guest Count")
250
 
251
  with gr.Column():
252
  gr.Markdown("### 🕰️ 選擇時段 Time Slot")
 
253
  status_box = gr.Markdown("請先選擇日期...", visible=True)
254
  time_slot = gr.Dropdown(choices=[], label="可用時段 Available Time", interactive=True)
255
 
 
261
  cust_name = gr.Textbox(label="訂位姓名 Name *", placeholder="ex. 王小明")
262
  cust_tel = gr.Textbox(label="手機號碼 Phone *", placeholder="ex. 0912-xxx-xxx")
263
 
 
264
  with gr.Row():
265
+ cust_email = gr.Textbox(label="電子信箱 E-mail (接收確認信用,請記得檢查垃圾信件匣。)", placeholder="example@gmail.com")
266
  with gr.Row():
267
  cust_remarks = gr.Textbox(label="備註 Remarks (過敏/慶生/特殊需求)", lines=2)
268