mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-04 02:32:57 +00:00
123 lines
4.2 KiB
TypeScript
123 lines
4.2 KiB
TypeScript
import api from './api';
|
|
|
|
export interface ZoneramaPhoto {
|
|
id: string;
|
|
page_url: string;
|
|
image_1500?: string;
|
|
title?: string;
|
|
}
|
|
|
|
export interface ZoneramaAlbumResp {
|
|
album: { id?: string; title?: string; url?: string };
|
|
photos: ZoneramaPhoto[];
|
|
}
|
|
|
|
export interface ZoneramaPickPayload {
|
|
id: string;
|
|
album_id?: string;
|
|
album_url: string;
|
|
page_url?: string;
|
|
image_url: string;
|
|
title?: string;
|
|
}
|
|
|
|
export async function getZoneramaAlbum(link: string, opts: { photo_limit?: number; rendered?: boolean } = {}): Promise<ZoneramaAlbumResp> {
|
|
const params: any = { link };
|
|
if (typeof opts.photo_limit === 'number') params.photo_limit = String(opts.photo_limit);
|
|
if (typeof opts.rendered === 'boolean') params.rendered = String(opts.rendered);
|
|
const res = await api.get<ZoneramaAlbumResp>('/zonerama/album', { params });
|
|
return res.data as any;
|
|
}
|
|
|
|
export async function getZoneramaPicks(): Promise<ZoneramaPickPayload[]> {
|
|
const res = await api.get<ZoneramaPickPayload[]>('/zonerama/picks');
|
|
return Array.isArray(res.data) ? res.data : [] as any;
|
|
}
|
|
|
|
export async function putZoneramaPick(payload: ZoneramaPickPayload): Promise<{ ok: boolean; count: number }> {
|
|
const res = await api.post<{ ok: boolean; count: number }>('/admin/zonerama/pick', payload);
|
|
return res.data;
|
|
}
|
|
|
|
export interface ZoneramaAlbumData {
|
|
id: string;
|
|
title: string;
|
|
url: string;
|
|
date: string;
|
|
photos_count: number;
|
|
views_count?: number;
|
|
photos: ZoneramaPhoto[];
|
|
fetched_at?: string;
|
|
}
|
|
|
|
export async function saveAlbumToCache(albumLink: string, photoLimit: number = 50): Promise<ZoneramaAlbumData> {
|
|
const res = await api.post<ZoneramaAlbumData>('/admin/zonerama/save-album', {
|
|
link: albumLink,
|
|
photo_limit: photoLimit
|
|
});
|
|
return res.data;
|
|
}
|
|
|
|
// Helper to read the flat manifest produced by the prefetcher for fast grid rendering
|
|
export async function getZoneramaManifest(): Promise<Array<{ id: string; album_id: string; src: string; local: string; page_url: string }>> {
|
|
const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:8080/api/v1';
|
|
const origin = new URL(apiUrl).origin;
|
|
// New unified path for prefetched Zonerama items
|
|
const url = `${origin}/cache/prefetch/zonerama_flat.json`;
|
|
const res = await fetch(url, { cache: 'no-cache' });
|
|
if (!res.ok) return [];
|
|
try {
|
|
const json = await res.json();
|
|
if (Array.isArray(json)) return json as any;
|
|
return [];
|
|
} catch {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
// More robust loader that tries multiple sources for prefetched items
|
|
export async function getZoneramaManifestWithFallbacks(): Promise<Array<{ id: string; album_id: string; src: string; local: string; page_url: string }>> {
|
|
// 1) Try the main manifest
|
|
const primary = await getZoneramaManifest();
|
|
if (primary && primary.length > 0) return primary;
|
|
|
|
const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:8080/api/v1';
|
|
const origin = new URL(apiUrl).origin;
|
|
|
|
// 1b) Backward-compat removed - old path no longer used to avoid 404 errors
|
|
|
|
// 2) Try unified controller JSON (one JSON to control all prefetched albums)
|
|
try {
|
|
const ctrlUrl = `${origin}/cache/prefetch/zonerama_albums.json`;
|
|
const resCtrl = await fetch(ctrlUrl, { cache: 'no-cache' });
|
|
if (resCtrl.ok) {
|
|
const json = await resCtrl.json();
|
|
// Expect shape: { albums: [{ id, page_url, cover_local, cover_src, items: [...] }], items?: [...] }
|
|
const items = Array.isArray(json?.items) ? json.items : [];
|
|
const flatFromCtrl = items.map((it: any) => ({
|
|
id: String(it.id || it.photo_id || ''),
|
|
album_id: String(it.album_id || ''),
|
|
src: String(it.src || it.image_url || ''),
|
|
local: String(it.local || it.local_url || it.image_local || ''),
|
|
page_url: String(it.page_url || it.url || ''),
|
|
}));
|
|
if (flatFromCtrl.length > 0) return flatFromCtrl;
|
|
}
|
|
} catch { /* ignore */ }
|
|
|
|
// 3) Fall back to picks endpoint if available (admin saves picks)
|
|
try {
|
|
const picks = await getZoneramaPicks();
|
|
const mapped = picks.map((p) => ({
|
|
id: String(p.id),
|
|
album_id: String(p.album_id || ''),
|
|
src: String(p.image_url),
|
|
local: String(p.image_url),
|
|
page_url: String(p.page_url || p.album_url || ''),
|
|
}));
|
|
return mapped;
|
|
} catch { /* ignore */ }
|
|
|
|
return [];
|
|
}
|