75 lines
2.4 KiB
TypeScript
75 lines
2.4 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { loadSettings } from "../api";
|
|
import { defaultSettings } from "../constants";
|
|
import type { AppSettings, ClassType, Grade, WordItem } from "../types";
|
|
import { mergeSettings } from "../utils";
|
|
|
|
export function usePkSetup() {
|
|
const [selectedGrade, setSelectedGrade] = useState<Grade>("中班");
|
|
const [classTypes, setClassTypes] = useState<ClassType[]>([]);
|
|
const [selectedClassTypeId, setSelectedClassTypeId] = useState<number>(0);
|
|
const [availableWords, setAvailableWords] = useState<WordItem[]>([]);
|
|
const [loadingSetup, setLoadingSetup] = useState(true);
|
|
const [settings, setSettings] = useState<AppSettings>(defaultSettings);
|
|
|
|
useEffect(() => {
|
|
async function loadInitialSetup() {
|
|
setLoadingSetup(true);
|
|
const [classTypesResponse, nextSettings] = await Promise.all([
|
|
fetch("/api/class-types?includeDisabled=false", { cache: "no-store" }),
|
|
loadSettings(),
|
|
]);
|
|
const classTypesData = (await classTypesResponse.json()) as { classTypes: ClassType[] };
|
|
setClassTypes(classTypesData.classTypes);
|
|
setSettings(mergeSettings(nextSettings));
|
|
setSelectedClassTypeId((current) => current || classTypesData.classTypes[0]?.id || 0);
|
|
setLoadingSetup(false);
|
|
}
|
|
|
|
void loadInitialSetup();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
function refreshSettingsOnFocus() {
|
|
void loadSettings().then((nextSettings) => setSettings(mergeSettings(nextSettings)));
|
|
}
|
|
|
|
window.addEventListener("focus", refreshSettingsOnFocus);
|
|
return () => window.removeEventListener("focus", refreshSettingsOnFocus);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
async function loadWords() {
|
|
if (!selectedClassTypeId) {
|
|
setAvailableWords([]);
|
|
return;
|
|
}
|
|
|
|
const params = new URLSearchParams({
|
|
grade: selectedGrade,
|
|
classTypeId: String(selectedClassTypeId),
|
|
enabledOnly: "true",
|
|
});
|
|
const response = await fetch(`/api/words?${params.toString()}`, { cache: "no-store" });
|
|
const data = (await response.json()) as { words: WordItem[] };
|
|
setAvailableWords(data.words);
|
|
}
|
|
|
|
void loadWords();
|
|
}, [selectedGrade, selectedClassTypeId]);
|
|
|
|
return {
|
|
selectedGrade,
|
|
setSelectedGrade,
|
|
classTypes,
|
|
selectedClassTypeId,
|
|
setSelectedClassTypeId,
|
|
availableWords,
|
|
setAvailableWords,
|
|
loadingSetup,
|
|
settings,
|
|
};
|
|
}
|