feat: Square payment integration, booking flow redesign, and timezone/weekday fixes

- Add Square payment integration (mock + handlers + UI): terminal/online payments,
  refunds, tips, saved cards, webhooks. Build-tagged dev/prod clients.
- Redesign booking flow: Step 4 conditional (deposit only), Step 5 confirmation
  screen with booking ID, auto-submit on transition.
- Redesign schedule modal: 2x3 button grid with Pay Deposit/Pay Early logic.
- Add deposit warning banner at Step 1 for users with outstanding deposits.
- Fix weekday conversion bug: Go 0=Sunday vs DB 0=Monday mismatch in 6 locations.
- Fix timezone bug: UTC vs London time in closing hours validation.
- Fix frontend error parsing: plain text backend errors now displayed correctly.
- Fix crypto.randomUUID fallback for environments without Web Crypto.
- Add 7 new regression tests: closing hours, advance check, active booking limit,
  weekday conversion, UTC/London, deposit snapshot, exceptional hours.
- Fix 3 flaky tests: dynamic dates instead of fixed, no-show timing.
This commit is contained in:
2026-05-23 11:29:34 +01:00
parent bcd5ed2bd9
commit 2e1ab9d745
31 changed files with 6155 additions and 229 deletions
+176
View File
@@ -0,0 +1,176 @@
{
"log": {
"version": "1.2",
"creator": {
"name": "Zen",
"version": "1.19.12b"
},
"browser": {
"name": "Zen",
"version": "1.19.12b"
},
"pages": [
{
"id": "page_1",
"pageTimings": {
"onContentLoad": -82849,
"onLoad": -82148
},
"startedDateTime": "2026-05-17T17:55:39.809+01:00",
"title": "http://192.168.1.135:5173/book"
}
],
"entries": [
{
"startedDateTime": "2026-05-17T17:55:39.809+01:00",
"request": {
"bodySize": 87,
"method": "POST",
"url": "http://192.168.1.135:5173/api/bookings/reserve",
"httpVersion": "HTTP/1.1",
"headers": [
{
"name": "Host",
"value": "192.168.1.135:5173"
},
{
"name": "User-Agent",
"value": "Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0"
},
{
"name": "Accept",
"value": "*/*"
},
{
"name": "Accept-Language",
"value": "en-US,en;q=0.9"
},
{
"name": "Accept-Encoding",
"value": "gzip, deflate"
},
{
"name": "Referer",
"value": "http://192.168.1.135:5173/book"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Content-Length",
"value": "87"
},
{
"name": "Origin",
"value": "http://192.168.1.135:5173"
},
{
"name": "Sec-GPC",
"value": "1"
},
{
"name": "Connection",
"value": "keep-alive"
},
{
"name": "Priority",
"value": "u=4"
},
{
"name": "Pragma",
"value": "no-cache"
},
{
"name": "Cache-Control",
"value": "no-cache"
}
],
"cookies": [],
"queryString": [],
"headersSize": 449,
"postData": {
"mimeType": "application/json",
"params": [],
"text": "{\"start_time\":\"2026-05-21T16:00:00.000Z\",\"service_ids\":[\"cf628115690e\",\"543de40e5079\"]}"
}
},
"response": {
"status": 400,
"statusText": "Bad Request",
"httpVersion": "HTTP/1.1",
"headers": [
{
"name": "Vary",
"value": "Origin"
},
{
"name": "content-length",
"value": "67"
},
{
"name": "content-type",
"value": "text/plain; charset=utf-8"
},
{
"name": "date",
"value": "Sun, 17 May 2026 16:55:39 GMT"
},
{
"name": "referrer-policy",
"value": "strict-origin-when-cross-origin"
},
{
"name": "strict-transport-security",
"value": "max-age=31536000; includeSubDomains"
},
{
"name": "x-content-type-options",
"value": "nosniff"
},
{
"name": "x-frame-options",
"value": "DENY"
},
{
"name": "x-xss-protection",
"value": "1; mode=block"
},
{
"name": "Connection",
"value": "keep-alive"
},
{
"name": "Keep-Alive",
"value": "timeout=5"
}
],
"cookies": [],
"content": {
"mimeType": "text/plain; charset=utf-8",
"size": 67,
"text": "Cannot book this time - services would extend beyond closing hours\n"
},
"redirectURL": "",
"headersSize": 390,
"bodySize": 457
},
"cache": {},
"timings": {
"blocked": -1,
"dns": 0,
"connect": 0,
"ssl": 0,
"send": 0,
"wait": 7,
"receive": 0
},
"time": 7,
"_securityState": "insecure",
"serverIPAddress": "192.168.1.135",
"connection": "5173",
"pageref": "page_1"
}
]
}
}