功能:首頁新增其他區名單,可在記分板臨時選上場但不參與配對
根本原因: 現場常有臨時來打球的人,不屬於 A、B 區的正規輪替名單;原本要讓他們上場只能把名字塞進 A 或 B 區,但這樣會被排進對戰組合,打亂正規配對。 影響: 首頁 A、B 區下方新增跨整行的「其他區名單」輸入框,內容存 localStorage 且不會被資料庫載入蓋掉;分組配對完全不使用其他區。記分板選隊伍時,其他區的人排在清單最後、名字旁掛「其他區」徽章,可手動勾選上場(含與正規名單混搭),今日場次照計;「自動選擇」不會選到他們,自動輪替仍以正規名單為準。 修法: App 新增 areaOtherInput 狀態與 localStorage 持久化,parseRoster 後以 extraPlayers 傳入 ScoreboardPage;selectablePlayers 併入其他區人選並用 extraPlayerSet 標記,autoPickDraftPlayers 過濾掉其他區,TeamPickerModal 依標記顯示徽章;TeamSelectionPage 新增第三個輸入欄位與說明文字。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+15
@@ -47,6 +47,7 @@ import type {
|
||||
const STORAGE_KEYS = {
|
||||
areaA: 'badminton-scoreboard::area-a',
|
||||
areaB: 'badminton-scoreboard::area-b',
|
||||
areaOther: 'badminton-scoreboard::area-other',
|
||||
history: 'badminton-scoreboard::history',
|
||||
playCounts: 'badminton-scoreboard::play-counts',
|
||||
} as const
|
||||
@@ -123,6 +124,10 @@ function App() {
|
||||
const [areaBInput, setAreaBInput] = useState(() =>
|
||||
loadStoredText(STORAGE_KEYS.areaB, defaultAreaB.join('\n')),
|
||||
)
|
||||
// 其他區:不參與分組配對,但會帶進記分板讓臨時上場的人可以被選到。
|
||||
const [areaOtherInput, setAreaOtherInput] = useState(() =>
|
||||
loadStoredText(STORAGE_KEYS.areaOther, ''),
|
||||
)
|
||||
const [groups, setGroups] = useState<RoundGroup[]>([])
|
||||
const [groupSource, setGroupSource] = useState<'idle' | 'db' | 'manual'>('idle')
|
||||
const [loadStatus, setLoadStatus] = useState<LoadStatus>('idle')
|
||||
@@ -163,6 +168,7 @@ function App() {
|
||||
|
||||
const parsedAreaA = useMemo(() => parseRoster(areaAInput), [areaAInput])
|
||||
const parsedAreaB = useMemo(() => parseRoster(areaBInput), [areaBInput])
|
||||
const parsedAreaOther = useMemo(() => parseRoster(areaOtherInput), [areaOtherInput])
|
||||
const selectedGroup = groups.find((group) => group.id === selectedGroupId) ?? null
|
||||
const leftTeam = activeMatchup.leftTeam
|
||||
const rightTeam = activeMatchup.rightTeam
|
||||
@@ -177,6 +183,10 @@ function App() {
|
||||
window.localStorage.setItem(STORAGE_KEYS.areaB, areaBInput)
|
||||
}, [areaBInput])
|
||||
|
||||
useEffect(() => {
|
||||
window.localStorage.setItem(STORAGE_KEYS.areaOther, areaOtherInput)
|
||||
}, [areaOtherInput])
|
||||
|
||||
useEffect(() => {
|
||||
window.localStorage.setItem(STORAGE_KEYS.history, JSON.stringify(history))
|
||||
}, [history])
|
||||
@@ -1068,6 +1078,7 @@ function App() {
|
||||
<TeamSelectionPage
|
||||
areaAInput={areaAInput}
|
||||
areaBInput={areaBInput}
|
||||
areaOtherInput={areaOtherInput}
|
||||
groups={groups}
|
||||
groupSource={groupSource}
|
||||
loadMessage={loadMessage}
|
||||
@@ -1075,6 +1086,7 @@ function App() {
|
||||
targetDate={targetDate}
|
||||
onAreaAInputChange={setAreaAInput}
|
||||
onAreaBInputChange={setAreaBInput}
|
||||
onAreaOtherInputChange={setAreaOtherInput}
|
||||
onGenerateManualGroups={generateManualGroups}
|
||||
onLoadGroupsFromDb={() => void loadGroupsFromDb()}
|
||||
onTargetDateChange={setTargetDate}
|
||||
@@ -1088,6 +1100,7 @@ function App() {
|
||||
<TeamSelectionPage
|
||||
areaAInput={areaAInput}
|
||||
areaBInput={areaBInput}
|
||||
areaOtherInput={areaOtherInput}
|
||||
groups={groups}
|
||||
groupSource={groupSource}
|
||||
loadMessage={loadMessage}
|
||||
@@ -1095,6 +1108,7 @@ function App() {
|
||||
targetDate={targetDate}
|
||||
onAreaAInputChange={setAreaAInput}
|
||||
onAreaBInputChange={setAreaBInput}
|
||||
onAreaOtherInputChange={setAreaOtherInput}
|
||||
onGenerateManualGroups={generateManualGroups}
|
||||
onLoadGroupsFromDb={() => void loadGroupsFromDb()}
|
||||
onTargetDateChange={setTargetDate}
|
||||
@@ -1107,6 +1121,7 @@ function App() {
|
||||
element={
|
||||
<ScoreboardPage
|
||||
currentSelectionOrder={getSelectionOrder(leftTeam, rightTeam)}
|
||||
extraPlayers={parsedAreaOther}
|
||||
finishDialogError={settlement.error}
|
||||
finishDialogOpen={settlement.open}
|
||||
finishDialogUploading={settlement.uploading}
|
||||
|
||||
Reference in New Issue
Block a user