Files
Sith/sas/static/bundled/sas/user/pictures-index.ts
T

83 lines
2.7 KiB
TypeScript

import { paginated } from "#core:utils/api";
import {
type PictureSchema,
type PicturesFetchPicturesData,
picturesFetchPictures,
} from "#openapi";
interface PagePictureConfig {
userId: number;
nbPictures?: number;
}
interface Album {
id: number;
name: string;
pictures: PictureSchema[];
}
document.addEventListener("alpine:init", () => {
Alpine.data("user_pictures", (config: PagePictureConfig) => ({
loading: true,
albums: [] as Album[],
async fetchPictures(): Promise<PictureSchema[]> {
// Check the cache before hitting the API.
const storageKey = "userPictures";
const cacheContent: { userId: number; pictures: PictureSchema[] }[] = JSON.parse(
sessionStorage.getItem(storageKey) || "[]",
);
const userPictures = cacheContent.find((obj) => obj.userId === config.userId);
if (
userPictures !== undefined &&
userPictures.pictures.length === config.nbPictures
) {
// The cached value is considered valid
// if it contains the right amount of pictures.
// This amount is known because it is given in the template.
return userPictures.pictures;
}
const pictures = await paginated(picturesFetchPictures, {
// biome-ignore lint/style/useNamingConvention: from python api
query: { users_identified: [config.userId] },
} as PicturesFetchPicturesData);
cacheContent.push({ userId: config.userId, pictures: pictures });
try {
// cache only the pictures of the last 4 visited profiles
sessionStorage.setItem(storageKey, JSON.stringify(cacheContent.slice(-4)));
} catch {
// an exception is raised if the storage is entirely filled.
// To be as safe as possible, delete the cached pictures.
// A cache hit is not worth the page breaking.
sessionStorage.removeItem(storageKey);
}
return pictures;
},
async init() {
const pictures = await this.fetchPictures();
const groupedAlbums = Object.groupBy(pictures, (i) => i.album.id as number);
this.albums = Object.values(groupedAlbums as Record<number, PictureSchema[]>).map(
(pictures) => {
return {
id: pictures[0].album.id as number,
name: pictures[0].album.name,
pictures: pictures,
};
},
);
this.albums.sort((a: Album, b: Album) => b.id - a.id);
const hash = document.location.hash.replace("#", "");
if (hash.startsWith("album-")) {
this.$nextTick(() => document.getElementById(hash)?.scrollIntoView()).then();
}
this.loading = false;
},
allPictures(): PictureSchema[] {
return this.albums.flatMap((album: Album) => album.pictures);
},
}));
});