Integrate React frontend with backend API

This commit is contained in:
Koha9
2025-11-28 03:00:02 +09:00
parent 4c6af7115e
commit 8d358a1de2
14 changed files with 2608 additions and 150 deletions
+62 -9
View File
@@ -18,9 +18,10 @@ const App: React.FC = () => {
const [localPlaylists, setLocalPlaylists] = useState<Playlist[]>([]);
const [cloudPlaylists, setCloudPlaylists] = useState<Playlist[]>([]);
const [cloudServerInfo, setCloudServerInfo] = useState<PlexServerConnection | undefined>(undefined);
const [loadingLocal, setLoadingLocal] = useState(false);
const [loadingCloud, setLoadingCloud] = useState(false);
const [statusIntervalMs, setStatusIntervalMs] = useState<number>(60000);
// Connection Modal State
const [isConnectionModalOpen, setIsConnectionModalOpen] = useState(false);
@@ -115,12 +116,16 @@ const App: React.FC = () => {
const playlistResult = await apiService.getPlaylists(ServerType.CLOUD);
if (playlistResult.status === 'success') {
setCloudPlaylists(playlistResult.data);
} else {
setCloudPlaylists([]);
}
// Fetch server info
const infoResult = await apiService.getServerStatus();
if (infoResult.status === 'success') {
setCloudServerInfo(infoResult.data);
} else {
setCloudServerInfo({ isConnected: false });
}
setLoadingCloud(false);
@@ -128,20 +133,68 @@ const App: React.FC = () => {
// Initial Load
useEffect(() => {
refreshLocal();
refreshCloud();
const loadSettings = async () => {
const [settings, uiConfig] = await Promise.all([
apiService.getSettings(),
apiService.getUiConfig()
]);
if (settings.status === 'success') {
setCurrentStrategy(normalizeStrategy(settings.data.syncStrategy));
if (settings.data.regexRules) {
setRegexReplacements(settings.data.regexRules);
}
}
if (uiConfig.status === 'success') {
const ms = Math.max(10000, (uiConfig.data.statusCheckIntervalSeconds || 60) * 1000);
setStatusIntervalMs(ms);
}
refreshLocal();
refreshCloud();
};
loadSettings();
}, [refreshLocal, refreshCloud]);
// Periodically check cloud connection status to avoid stale UI loops
useEffect(() => {
const timer = window.setInterval(() => {
refreshCloud();
}, statusIntervalMs);
return () => window.clearInterval(timer);
}, [refreshCloud, statusIntervalMs]);
const normalizeStrategy = (value?: string): SyncStrategy => {
if (!value) return SyncStrategy.LOCAL_OVERWRITE;
const values = Object.values(SyncStrategy);
return values.includes(value as SyncStrategy)
? (value as SyncStrategy)
: SyncStrategy.LOCAL_OVERWRITE;
};
// Handle Strategy Change
const handleStrategyChange = (strategy: SyncStrategy, label: string) => {
const handleStrategyChange = async (strategy: SyncStrategy, label: string) => {
setCurrentStrategy(strategy);
addToast(`Selected strategy "${label}" has been saved.`);
const result = await apiService.saveStrategy(strategy);
if (result.status === 'success') {
addToast(`Selected strategy "${label}" has been saved.`);
} else {
addToast('Failed to save strategy to server.');
}
};
// Handle Regex Save
const handleSaveRegex = (replacements: RegexReplacement[]) => {
setRegexReplacements(replacements);
addToast('Regex preprocessing rules have been saved.');
const handleSaveRegex = async (replacements: RegexReplacement[]) => {
const result = await apiService.saveRegexRules(replacements);
if (result.status === 'success') {
setRegexReplacements(result.data);
addToast('Regex preprocessing rules have been saved.');
} else {
addToast(result.message || 'Failed to save regex rules.');
}
};
const handleConnectSuccess = (serverInfo: PlexServerConnection) => {