Files
englishPk/app/pk/hooks/usePkSetup.ts
T
hanhan 17fc24edc7
Build Docker Package / docker-package (push) Successful in 6m34s
feat: add word import and class type display controls
2026-07-02 14:34:00 +08:00

104 lines
2.8 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 nextSettings = await loadSettings();
setSettings(mergeSettings(nextSettings));
setLoadingSetup(false);
}
void loadInitialSetup();
}, []);
useEffect(() => {
let ignore = false;
async function loadClassTypes() {
setLoadingSetup(true);
setSelectedClassTypeId(0);
const params = new URLSearchParams({
includeDisabled: "false",
grade: selectedGrade,
});
const response = await fetch(`/api/class-types?${params.toString()}`, { cache: "no-store" });
const data = (await response.json()) as { classTypes: ClassType[] };
if (!ignore) {
setClassTypes(data.classTypes);
setSelectedClassTypeId(data.classTypes[0]?.id || 0);
setLoadingSetup(false);
}
}
void loadClassTypes();
return () => {
ignore = true;
};
}, [selectedGrade]);
useEffect(() => {
function refreshSettingsOnFocus() {
void loadSettings().then((nextSettings) => setSettings(mergeSettings(nextSettings)));
}
window.addEventListener("focus", refreshSettingsOnFocus);
return () => window.removeEventListener("focus", refreshSettingsOnFocus);
}, []);
useEffect(() => {
let ignore = false;
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[] };
if (!ignore) {
setAvailableWords(data.words);
}
}
void loadWords();
return () => {
ignore = true;
};
}, [selectedGrade, selectedClassTypeId]);
return {
selectedGrade,
setSelectedGrade,
classTypes,
selectedClassTypeId,
setSelectedClassTypeId,
availableWords,
setAvailableWords,
loadingSetup,
settings,
};
}