Add overwrite confirmation and update README
This commit is contained in:
@@ -11,7 +11,9 @@
|
|||||||
- 每一組都會把 A 區與 B 區名單完整分配完成
|
- 每一組都會把 A 區與 B 區名單完整分配完成
|
||||||
- 若某一區人數不足,系統會自動補入「那個」
|
- 若某一區人數不足,系統會自動補入「那個」
|
||||||
- 產生配對後可用按鈕手動上傳資料到資料庫
|
- 產生配對後可用按鈕手動上傳資料到資料庫
|
||||||
|
- 若指定日期已經有資料,上傳前會先詢問是否覆蓋
|
||||||
- 可讀取指定日期的資料庫內容並回填到畫面
|
- 可讀取指定日期的資料庫內容並回填到畫面
|
||||||
|
- 若指定日期沒有資料,畫面會顯示「指定日期沒有資料」
|
||||||
- 支援換行、半形逗號、全形逗號與頓號輸入
|
- 支援換行、半形逗號、全形逗號與頓號輸入
|
||||||
- 會自動去除空白與重複名稱
|
- 會自動去除空白與重複名稱
|
||||||
|
|
||||||
@@ -22,6 +24,12 @@ npm install
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
|
前端開發網址預設為:
|
||||||
|
|
||||||
|
```text
|
||||||
|
http://localhost:3500
|
||||||
|
```
|
||||||
|
|
||||||
## 資料庫欄位
|
## 資料庫欄位
|
||||||
|
|
||||||
- `time`: 目標日期,格式為 `YYYYMMDD`
|
- `time`: 目標日期,格式為 `YYYYMMDD`
|
||||||
|
|||||||
49
src/App.tsx
49
src/App.tsx
@@ -98,13 +98,26 @@ function App() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
setActionState('saving')
|
|
||||||
setActionMessage('上傳資料到資料庫中...')
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await saveMatchResults(convertDateToKey(targetDate), parsedAreaA, parsedAreaB, results)
|
const timeKey = convertDateToKey(targetDate)
|
||||||
|
const existingResult = await findMatchResults(timeKey)
|
||||||
|
|
||||||
|
if (existingResult.found) {
|
||||||
|
const confirmed = window.confirm(`${timeKey} 已經有資料,確定要覆蓋嗎?`)
|
||||||
|
|
||||||
|
if (!confirmed) {
|
||||||
|
setActionState('idle')
|
||||||
|
setActionMessage('已取消上傳。')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setActionState('saving')
|
||||||
|
setActionMessage('上傳資料到資料庫中...')
|
||||||
|
|
||||||
|
await saveMatchResults(timeKey, parsedAreaA, parsedAreaB, results)
|
||||||
setActionState('saved')
|
setActionState('saved')
|
||||||
setActionMessage(`已同步到資料庫:${convertDateToKey(targetDate)}`)
|
setActionMessage(`已同步到資料庫:${timeKey}`)
|
||||||
} catch (saveError) {
|
} catch (saveError) {
|
||||||
setActionState('error')
|
setActionState('error')
|
||||||
setActionMessage(
|
setActionMessage(
|
||||||
@@ -362,6 +375,16 @@ async function saveMatchResults(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function loadMatchResults(time: string) {
|
async function loadMatchResults(time: string) {
|
||||||
|
const result = await findMatchResults(time)
|
||||||
|
|
||||||
|
if (!result.found || !result.data) {
|
||||||
|
throw new Error('指定日期沒有資料。')
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.data
|
||||||
|
}
|
||||||
|
|
||||||
|
async function findMatchResults(time: string) {
|
||||||
const response = await fetch(`/api/match-results/${time}`)
|
const response = await fetch(`/api/match-results/${time}`)
|
||||||
const payload = (await response.json()) as {
|
const payload = (await response.json()) as {
|
||||||
ok?: boolean
|
ok?: boolean
|
||||||
@@ -369,11 +392,21 @@ async function loadMatchResults(time: string) {
|
|||||||
data?: LoadMatchResultsResponse
|
data?: LoadMatchResultsResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.ok || !payload.ok || !payload.data) {
|
if (response.status === 404) {
|
||||||
throw new Error(payload.message ?? '指定日期沒有資料。')
|
return {
|
||||||
|
found: false,
|
||||||
|
data: null,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return payload.data
|
if (!response.ok || !payload.ok) {
|
||||||
|
throw new Error(payload.message ?? '讀取資料失敗。')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
found: true,
|
||||||
|
data: payload.data ?? null,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertDbRecordToAppState(record: LoadMatchResultsResponse) {
|
function convertDbRecordToAppState(record: LoadMatchResultsResponse) {
|
||||||
|
|||||||
Reference in New Issue
Block a user