[fix] sidebar:組織切換即時回饋、user menu 改成選單並可接受邀請 - #65
Merged
Conversation
✅ SonarQube Quality Gate passed — pathorsAI_internal0 open issues on this PR. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
側邊欄三個一直被抱怨的地方,一次修掉。
1. 組織切換器常常是空的、選完要等很久
問題:
OrgSwitcher完全靠 client hook(useListOrganizations()/useActiveOrganization())。第一次繪製時兩個都還沒回來,所以看到的是一個空白而且 disabled 的下拉選單;選完之後await setActive→router.refresh(),期間每一頁 force-dynamic 的 server component 都要重跑,畫面卻完全沒有「正在換」的跡象,而且顯示的值要等 hook 重抓才會更新。另外還有一段 localStorage「還原上次組織」的 effect,會在 mount 時再觸發一次切換 + refresh。改法:
src/app/dashboard/layout.tsx(server component)一次撈好 session 與auth.api.listOrganizations(),把initialOrganizations/initialActiveOrgId傳給AppSidebar→OrgSwitcher。第一次繪製就有組織名稱可顯示。organizations ?? initialOrganizations)。selectedId由initialActiveOrgId起始,選擇當下就樂觀更新,下拉立刻顯示新組織;失敗才回捲並跳 toast。Skeleton,不再出現空白 disabled 的下拉。src/components/refresh-pending.tsx:RefreshPendingProvider/useRefreshPending/RefreshPendingOverlay。切換期間主內容區壓暗(opacity+pointer-events-none)並在最上緣顯示一條不定量進度條,切換器本身換成 spinner。lastOrgId還原邏輯 —— session 本來就記得 active org,那段自動切換只會造成莫名其妙的重新載入。2. 使用者按鈕一按就登出
問題:
UserMenu的整顆按鈕就是signOut,沒有選單、沒有確認,手滑一次就掉出去。改法:改成
DropdownMenu,圖示從LogOut換成ChevronsUpDown。選單內容由上而下:3. 邀請只有 /onboarding 看得到
問題:接受邀請的 UI 只在
/onboarding,而那頁只有「還沒有任何組織」的人進得去。已經在某個組織、又被邀請去另一個組織的人,永遠看不到那張邀請(目前也沒有邀請信,sendInvitationEmail沒設定)。改法:
src/components/pending-invitations.tsx,把 onboarding 的邀請清單與接受邏輯抽出來共用。導出useUserInvitations()(回傳{ invites, acceptable, expired, loading, refresh })與PendingInvitations元件。過期/未過期的切分沿用 onboarding 原本的判斷(listUserInvitations只濾status === "pending",過期的仍會回來,得在前端自己分)。acceptInvitation/rejectInvitation);過期的一樣只顯示不給按鈕。Dialog裝這個元件,沒有邀請時顯示空狀態。auth.onboarding.invites提到auth.invites(兩邊共用同一份),userMenu.*補在common.ts。Render 策略
初始資料由 dashboard 的 server layout 一次撈好往下傳,client 端只負責保持新鮮;互動先樂觀更新本地 state,真正的 server 往返用共用的 transition 包起來,pending 狀態透過 context 傳到主內容區顯示。transition 開在
RefreshPendingProvider而不是各自在呼叫端,因為router.refresh()要在 transition 裡呼叫,isPending才會一路撐到 server 回來 —— 呼叫端自己開的話只能在送出 refresh() 的當下關掉旗標,而那正好是等待開始的時間點。沒有 schema 變更。
驗證
bun run lint通過bunx tsc --noEmit零錯誤bun run build成功/login200、/onboarding與/dashboard未登入正常 307,無 runtime error