V8.0.31
Dual-source 收斂 — 永遠根治 V8.0.30 修的問題:砍掉 9 個 tracked .js(server / morning / morning-builder / generate-ics-headless / spa/html-body / spa/js-core / spa/js-pilot-log / spa/js-weather / spa/styles)+ 13 個 untracked stale 編譯產物,.ts 變唯一 source-of-truth。tsx 對 './xxx.js' 的 import 會自動 fallback 到同名 .ts,所以 server.ts 不用改 import 路徑。.gitignore 加防護避免本機跑 tsc 再被誤 track。從此推版只改 .ts,不再有「改了 .js 但 prod 跑 .ts」這種白做工的可能。
Dual-source consolidation — permanent fix for the issue V8.0.30 patched: removed 9 tracked .js files (server / morning / morning-builder / generate-ics-headless / spa/html-body / spa/js-core / spa/js-pilot-log / spa/js-weather / spa/styles) plus 13 untracked stale build artifacts, making .ts the sole source of truth. tsx automatically falls back from './xxx.js' imports to the matching .ts, so server.ts import paths don't need to change. .gitignore now explicitly blocks the .js compilation outputs to prevent re-tracking if someone runs tsc locally. Going forward only the .ts needs to be touched, eliminating the「edited .js but prod runs .ts」class of no-op releases.
V8.0.30
修正 V8.0.27 / V8.0.28 / V8.0.29 三版皆未生效於 prod 的根本問題:src/spa/html-body.ts 跟 html-body.js 是同名雙檔(都被 git tracked),server.ts 雖 import './spa/html-body.js',但 tsx ESM resolver 優先解析到同名 .ts → prod runtime 永遠 serve V8.0.26 的 source。前三次推版只改 .js 沒改 .ts,等於白做。本版把 .ts 內容同步到 .js 最新版(含 V8.0.27~29 全部 fix),未來推版兩份要一起改直到 dual-source 收斂。
Fix the root cause of V8.0.27/28/29 all failing to take effect in prod: src/spa/html-body.ts and html-body.js are dual-source files (both git-tracked); although server.ts imports './spa/html-body.js', tsx's ESM resolver prefers the same-named .ts → prod runtime always serves V8.0.26 source. The previous three releases only updated .js without touching .ts, so they were no-ops on prod. This release syncs .ts to match .js (carrying V8.0.27~29 fixes through), and going forward both files must be edited together until the dual-source situation is resolved.
V8.0.29
修正 PWA cache 永遠看到舊版本問題:Service Worker 的 cache name 寫死成 'crewsync-v8026',每次推版都用同一個 cache name → SW activate handler 「刪除別的 cache key」永遠刪不到自己 → 舊 shell 永遠 cached,user kill PWA 重開仍看舊版號(V8.0.26 / V8.0.27 / V8.0.28 改完都沒生效)。改成從 SPA HTML 內動態抓當前 V8.0.X 字串組 cache name → 每次推版 cache name 自動跟著變 → 新 SW 自動 invalidate 舊 cache。
Fix PWA cache stuck on old version: Service Worker cache name was hardcoded as 'crewsync-v8026', so every deploy reused the same cache key — SW activate handler's delete keys !== CACHE never cleared its own cache → app shell stuck at the cached old version (V8.0.26/27/28 all failed to take effect even after kill+reopen PWA). Now the cache name is derived dynamically from the current V8.0.X string in the SPA HTML, so it changes with every deploy and the new SW automatically invalidates the old cache.
V8.0.28
修正 Briefing 中 Overtime warning「表定 FT 00:00 → 任何輸入都顯示 OT」bug:root cause 是 DHD(deadhead,配位調機)任務班表系統會把 flightTime 寫成 "00:00"(DHD 計薪方式不算 FT),但 dep/arr time 還在(飛機還是要飛),DHD 也該算 OT。_briefCalcSchedFTmin 原本看到 flightTime 就用,parse 出 0 也回傳 → OT 警告基準變 0 → 永遠觸發。改成 parse 出 0 視為無效繼續走下方 dep/arr fallback 用 schedule dep/arr 算 schedFT(跟 Overtime 子頁 _otCalcMagic 同邏輯)。
Fix Briefing Overtime warning「sched FT 00:00 → always triggers」bug: root cause is DHD (deadhead) tasks — roster system writes flightTime="00:00" for DHD (its pay logic excludes FT), but dep/arr times are still present (the plane still flies) and DHD should still trigger OT calc. _briefCalcSchedFTmin previously took flightTime as-is, returning 0 → OT baseline became 0 → warning always triggered. Now treats parsed value of 0 as invalid and falls through to dep/arr-based sched FT calculation (same logic as Overtime subtab _otCalcMagic).
V8.0.27
修正 JX 班表登入流程:原本 catch {} 吞掉真實 error 硬塞「密碼錯」當 fallback 訊息,員工被誤導以為自己帳密錯但其實是 navigation timeout / network error。改為 catch (e) 接住 error 並 log cause,錯誤訊息帶實際原因方便排查(navigation timeout / network error / 真錯帳密)。同時把 page.waitForNavigation timeout 從 8 秒拉到 20 秒,避免班表發布日 JX 後端壅塞時 8 秒太短被誤判成密碼錯。
Fix JX roster login flow: previously catch {} swallowed the real error and hardcoded "wrong password" as a fallback message, misleading users into thinking their credentials were wrong when it was actually a navigation timeout / network error. Changed to catch (e) that logs the cause; error message now includes the real reason (navigation timeout / network error / actual wrong credentials) for easier diagnosis. Also bumped page.waitForNavigation timeout from 8s to 20s — 8s was too aggressive during JX server congestion right after roster release.
V8.0.26
修正 Briefing 中 Overtime warning:統一航班號比對規則(去前導 0/去空白)、改用 flight-level 日期推算(學 overtime 子頁的方式,更穩)、找不到航班或算不出表定 FT 時改顯示診斷提示,不再靜默失敗。Groups 群組面板:清除 SFO/FO 合併前留下的舊群組(denylist 模式,只刪明確列出的 legacy id,未來新增機隊/preset 不會被誤刪)。Duty Time 持久化補強:每次輸入即存(不再需要按 Calculate 才存)、保存/還原 crew 人數選擇、重開頁面時若 FDP Start 已填妥則自動重算讓結果區塊回來。
Briefing Overtime warning fix: unified flight number matching (strip leading zeros/spaces), use flight-level date parsing (matches Overtime subtab logic), replaced silent failures with diagnostic hints when roster flight not found or scheduled FT unavailable. Groups panel: removed legacy SFO/FO orphan groups left from the merge (denylist approach — only deletes explicitly listed legacy IDs, so future fleets/presets won't be accidentally removed). Duty Time persistence: instant save on every input (no longer requires clicking Calculate), save/restore crew size selection, auto-recalculates on page reopen when FDP Start is filled so the result section comes back too.
V8.0.25
機場分類資料表更新到 Operations Specifications C-6 Authorized Airport List APR 01 2026 修正版(Amendment 069),共 8 項:(1) A350-1041 新增 RJBB(關西)為定期機場、新增 RJFF(福岡)為備用機場。(2) A330-941:RJCH(函館)、RJOT(高松)、RPVM(宿霧)由定期改備用。(3) A350-941:新增 RJCH(函館)為備用;RJSS(仙台)、RPLC(克拉克)、RPVM(宿霧)由定期改備用。(4) A321-252NX / A330-941 / A350-941:移除 VDPP(金邊)為備用機場。(5) A321-252NX:WADD(峇里島)由定期改備用。(6) A330-941:WIII(雅加達)由定期改備用。(7) A350-941:VVPQ(富國)、WIII(雅加達)由定期改備用。(8) A330-941:移除 WADD(峇里島)為定期機場;A350-941:移除 WADD 為備用機場。
Airport classification table updated to Operations Specifications C-6 Authorized Airport List APR 01 2026 amendment (Amendment 069), 8 changes: (1) A350-1041 — added RJBB (Kansai) as regular, RJFF (Fukuoka) as alternate. (2) A330-941 — RJCH / RJOT / RPVM regular → alternate. (3) A350-941 — added RJCH as alternate; RJSS / RPLC / RPVM regular → alternate. (4) A321-252NX / A330-941 / A350-941 — removed VDPP (Phnom Penh) as alternate. (5) A321-252NX — WADD (Bali) regular → alternate. (6) A330-941 — WIII (Jakarta) regular → alternate. (7) A350-941 — VVPQ / WIII regular → alternate. (8) A330-941 — removed WADD as regular; A350-941 — removed WADD as alternate.
V8.0.24
Roster sync(Playwright)穩定性大改造:(1) 所有 .rbc-event-content 的等待 timeout 從 2s 拉到 10s,慢網下不再因為 calendar 重繪稍慢就噴掉。(2) 外層 while 入口加 try/catch,超時就優雅 break 並保留已抓到的 duties,不再整份 sync 中止。(3) Click 失敗後檢查是否還在 calendar,有部分導航就 goBack 恢復再繼續。(4) 三個失敗點(outer_timeout / click_fail / goback_wait_fail)加詳細 log(url / i / dutyText / .rbc 數量 / readyState)+ 截圖到 /tmp/sync-debug/{jobId}/{i}_{type}_{ts}.png。(5) 最外層 try/catch 接 unhandled Playwright error,若已抓到 ≥1 筆 duty → 回傳 partial + 輸出部分 ICS;完全沒抓到則維持 fail 不包裝。(6) 新增 GET /api/sync-debug/:syncId/:file?eid=xxx(job.employeeId 比對)讓使用者下載除錯截圖;啟動時清除 24h 前的檔案。(7) 前端同步完成頁三態顯示:✅ 完整 / ⚠️ 部分成功(列出原因 + 截圖連結)/ ❌ 失敗。
Roster sync (Playwright) reliability overhaul: (1) all .rbc-event-content wait timeouts raised from 2s to 10s — slow networks no longer trip over calendar re-renders. (2) Outer while-loop entry wrapped in try/catch — timeouts break gracefully, preserving already-captured duties. (3) Click failure now checks if still on calendar, recovers via goBack if partial navigation occurred. (4) Three failure points (outer_timeout / click_fail / goback_wait_fail) now log detailed context (url / i / dutyText / .rbc count / readyState) and snapshot to /tmp/sync-debug/{jobId}/{i}_{type}_{ts}.png. (5) Outermost try/catch catches unhandled Playwright errors — returns partial with partial ICS if ≥1 duty captured, otherwise still fails cleanly (no dishonest wrapping). (6) New GET /api/sync-debug/:syncId/:file?eid=xxx (job.employeeId check) for downloading debug screenshots; 24h-old session dirs auto-cleaned on startup. (7) Sync-complete screen now has three states: ✅ full / ⚠️ partial (with reason + clickable screenshot links) / ❌ failed.
V8.0.23
FLIGHT INFO/DATA 標題的 🗺️ Briefing Room 連結旁,新增小輸入格(約 98px 寬,maxlength 4),placeholder eg. ONT、輸入自動轉大寫,讓使用者自己填 briefing room 代碼。欄位 brief-room 納入 _briefFields 一起 debounced auto-save、歷史同步、載入歷史會還原。
Added a small input next to the 🗺️ Briefing Room link in the FLIGHT INFO/DATA header (~98px wide, maxlength 4, placeholder eg. ONT, auto-uppercase) so users can note their assigned briefing room code. Field brief-room is part of _briefFields — debounced auto-save, history sync, restored on history load.
V8.0.22
修正 V8.0.21 的 🗺️ Briefing Room 連結在 PWA(iPad/手機安裝版)沒地方關閉的問題。改為 in-app modal viewer:點連結不再開新 tab,而是在 app 內彈全螢幕黑底 modal,右上角 ✕ 按鈕(避開 notch safe-area),點空白處也能關,圖片支援雙指縮放(touch-action: pinch-zoom)。修正初始 src="" 被瀏覽器解讀為當前頁 URL 導致 bug。
Fixed V8.0.21 issue where the 🗺️ Briefing Room link had no close button in PWA mode (installed iPad/phone app). Replaced new-tab with in-app modal viewer: tap the link now opens a full-screen black-backdrop modal inside the app, with a ✕ button top-right (respects notch safe-area), tap outside to close, pinch-zoom supported. Fixed a bug where initial src="" was resolved to current page URL by browsers.
V8.0.21
Briefing 新增兩個功能:(1) FLIGHT INFO/DATA 標題旁加「🗺️ Briefing Room」藍色超連結,點擊開新 tab 顯示 briefing room 平面圖,由 server /briefing-room route 提供(7 天 cache)。(2) 輸入 Flight Time 時自動比對 roster 當日表定 FT;邏輯:實際 ≥ 表定 − 10 分鐘就顯示黃色警告框(實際越長 OT 機率越高),含「→ Overtime」按鈕可直接跳去 Overtime subtab。匹配 duty 日期範圍 [reportTime ~ endTime] ± 1 天容錯(處理外站時區差 + 同日來回),冬夏班表不跨月估算。沒同步當天 roster 就靜默不顯示。警告在清除/改航班號/FT 大幅縮短時自動消失。
Briefing gains two features: (1) 🗺️ Briefing Room blue underlined link in the FLIGHT INFO/DATA header — opens floor plan in a new tab, served via /briefing-room route (7-day cache). (2) Entering Flight Time auto-compares against that day's scheduled FT from roster; logic: if actual FT ≥ scheduled − 10 min, shows a yellow warning banner (longer actual = higher OT chance) with a "→ Overtime" button. Matches duty's [reportTime ~ endTime] range with ±1 day tolerance (handles outstation timezone + same-day turns), no cross-month estimation. Silently hides if roster not synced for that day. Warning auto-clears on field clear / flight no. change / FT drop below threshold.
V8.0.20
Briefing 資料儲存改為每字 oninput debounced 500ms 自動存(不用等 blur),整份 briefing(Block 1 + Block 2 notes/POB 全部)都即時同步。搜尋列右邊新增儲存狀態小圓點:🟡 存檔中 / 🟢 已儲存。blur 保留當備胎避免關 tab race。
Briefing auto-save switched from blur to input event (debounced 500ms) — no more waiting for field blur; full briefing (Block 1 + Block 2 notes/POB) syncs in real time. Tiny status dot next to the search row: 🟡 saving / 🟢 saved. Blur kept as fallback to guard against tab-close races.
V8.0.19
Briefing panel 新增歷史功能:📅 History 按鈕打開月曆式歷史檢視,黃色日期表示有 briefing,格子內顯示航班號 + 非 TPE 那端城市(例如 JX820 KIX),多班時顯示 ⋯ +N。點日期格子 → 下方 panel 列出當日全部航班(可點擊載入或 ✕ 刪除)。查詢成功自動存 snapshot、notes blur 自動 save,資料永久保留。有 eid(上傳過班表)→ Postgres 跨裝置同步;無 eid → 本機 localStorage。NOTES 區塊重構:Turbulence / Tail No./MEL / Min Water / Fuel Required 四欄都加永久 label(標題獨立一行在 textarea 上方,不會被輸入遮蔽);新增 👥 Crew + Pax = POB 自動加總欄位(同一行顯示)。後端新增 crewsync_briefings 表 + POST/GET/LIST/DELETE /api/briefing 端點;每筆以 (eid, flight_no, flight_date) 唯一。
Briefing panel gains history feature: 📅 History button opens a calendar-style modal where golden days indicate saved briefings; each cell shows flight_no + non-TPE city (e.g., JX820 KIX) with ⋯ +N for additional flights. Tap a golden date → detail panel below lists all flights for that day (click to load, ✕ to delete). Auto-save on successful Query + debounced on notes blur; permanent retention. Cross-device sync via eid (Postgres) when roster uploaded; else local (localStorage). NOTES restructured: Turbulence / Tail No./MEL / Min Water / Fuel Required all now have a permanent label above each textarea (no longer hidden when typing); new 👥 Crew + Pax = POB row with auto-sum on a single line. Backend: new crewsync_briefings Postgres table + POST/GET/LIST/DELETE /api/briefing endpoints; unique per (eid, flight_no, flight_date).
V8.0.18
修正退出群組時未清理 sharing 和班表資料的 bug:退出最後一個群組後自動設 sharing=false 並刪除雲端班表
Fix: leaving last group now auto-disables sharing and deletes roster data from cloud
V8.0.17
新增「晨報 Morning Report」PWA,掛在 /morning 獨立路由,擁有自己的 icon、manifest、Service Worker 和版次;CrewSync icon 升級為深藍夜空 + 雲海 + 飛機的新設計
Added Morning Report PWA at /morning with independent icon, manifest, Service Worker and versioning; CrewSync icon upgraded with night sky, clouds, and plane design
V8.0.16e
Friends/Groups grid 加入底部 120px spacer 修正最後一列被切、Tab bar 斷點下調至 600px 修正 iPad 直拿
Friends/Groups grid added 120px bottom spacer for last row, tab bar breakpoint lowered to 600px for iPad portrait
V8.0.15a
Groups grid 修正:iPad 垂直捲動 + 水平卷軸修正、.ts/.js 同步修正
Groups grid fix: iPad vertical scroll + horizontal scrollbar fix, .ts/.js sync fix
V8.0.14
Overtime Calculator 結果文字調整:強調額外營運成本提示
Overtime Calculator result text update: highlight additional operational costs warning
V8.0.13
Overtime Calculator UI 優化:header 精簡、航班選單與月份同行、iPad 橫拿捲動修正、已完成航班警語
Overtime Calculator UI improvements: compact header, inline month & flight selector, iPad landscape scroll fix, completed flight warning
V8.0.12
新增 Overtime Calculator subtab(Flight Crew),從班表自動帶入航班時間、月份切換、跨月航班支援、手動輸入模式、24hr 快取
New Overtime Calculator subtab (Flight Crew): auto-load flights from roster, month navigation, cross-month flight support, manual input mode, 24hr cache
V8.0.11
Groups All 群組篩選修正:CC 不顯示機隊下拉;Groups / Friends 記憶上次選擇的群組(30 天快取)
Groups All filter fix: hide fleet dropdown for CC; Groups / Friends remember last selected group (30-day cache)
V8.0.10
Groups 移除分享 toggle,加入群組即啟用分享,退出所有群組自動停止;預設群組改下拉選單 + 已加入標籤;新增 FC/CC/職級篩選器;Friends header 加 ⓘ、名稱/機隊欄位預設顯示、自動載入第一個群組班表;CC Rest Calculator 移除密碼鎖正式開放、新增 Crew Prep 欄位、休時取整至 5 min、新增重設按鈕與 24hr 快取、表單寬度優化;好友圈說明文字更新;PA dep-min 手動修改 flag 修正
Groups: remove share toggle, join = auto-share, leave all = auto-stop; presets changed to dropdown + joined tags; added FC/CC/rank filter; Friends: ⓘ in header, name/fleet shown by default, auto-load first group roster; CC Rest Calculator: removed password lock, added Crew Prep field, rest rounded to 5 min, Reset button, 24hr cache, form width optimized; friend group description updated; PA dep-min manual flag fix
V8.0.08
Friends 拿掉分享 toggle、說明文字更新;Groups ⓘ 修正;加入群組自動開分享;0 人群組自動刪除;離線快取 30 天過期
Friends remove share toggle, updated descriptions; Groups ⓘ fix; auto-share on join; auto-delete empty groups; 30-day cache expiry
V8.0.07
Cabin Crew Rest Calculator(Beta)、FC/CC 身分連動 Friends、Cabin subtab 拖移排序、時區加場站名
Cabin Crew Rest Calculator (Beta), FC/CC role sync with Friends, Cabin subtab drag reorder, timezone with station names
V8.0.06
新增 Cabin Crew tab + 預設群組改版(FC 6 + CC 3 + All)、手機 tab bar 可捲動、分享選 FC/CC 身分
New Cabin Crew tab, preset groups redesign (FC 6 + CC 3 + All), mobile tab bar scrollable, FC/CC role selection
V8.0.05
Training duty(RT)拆分 PT/PC 子項目、每天獨立組員名單;Groups 排版修正、toggle 與名稱同行、ⓘ 修正
Training duty (RT) split into PT/PC sub-items with per-day crew; Groups layout fix, inline toggles, ⓘ fix
V8.0.03
Groups 排版修正:隱藏不符合群組、header 固定、toggle 與名稱同行、ⓘ 修正、Friends 重複按鈕修正
Groups layout fix: hide non-matching groups, fixed header, inline toggles, ⓘ fix, Friends duplicate button fix
V8.0.02
Groups 手機版排版修正:隱藏不符合機隊/職級的群組、header 固定不捲動
Groups mobile layout fix: hide non-matching groups, fixed header
V8.0.01
新增 Groups 群組功能:10 個預設群組(All + 9 個機隊職級)、自訂好友圈、邀請碼加入、員工編號邀請、紅點通知
New Groups feature: 10 preset groups (All + 9 fleet/rank), custom friend circles, invite code, employee ID invitation, notification badge
V7.0.15
Briefing 日期切換改 ◀ M/D ▶ 支援前一天;Gate Info 移除標題、警語改黃色;隱私權政策補齊第三方服務
Briefing date nav changed to ◀ M/D ▶ with yesterday support; Gate Info title removed, warning in yellow; privacy policy third-party services updated
V7.0.14
About card 加註 Android 裝置可能無法正確顯示;FAQ 修正日曆授權說明以符合隱私權政策
About card adds Android display note; FAQ corrects calendar authorization description to align with privacy policy
V7.0.13
PA Welcome 出發分鐘數快取保留、Descent 點選場站帶入中文目的地
PA Welcome departure minutes persisted; Descent tap-to-select fills Chinese destination
V7.0.12
WX 單一機場更新按鈕加入載入狀態,清除 24hr 快取強制重新抓取
WX single airport refresh button shows loading state, clears 24hr cache
V7.0.11
手機直拿 Friends header 分兩行排列,第一行可滑動、第二行月份置中+篩選靠右
Mobile portrait Friends header split into two rows