commit
bc02d72576
64 files changed
+9366
No files matched your search
@@ -0,0 +1,171 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { computed, ref, watch } from "vue";
|
||||
import { loadGalleryAssets } from "@/data";
|
||||
import type { Collection, GalleryAsset } from "@/types/gallery";
|
||||
|
||||
export const BATCH = 12;
|
||||
|
||||
function assetMatchesFilters(
|
||||
asset: GalleryAsset,
|
||||
collection: Collection | "all",
|
||||
selectedTags: Set<string>,
|
||||
): boolean {
|
||||
if (collection !== "all" && asset.collection !== collection) {
|
||||
return false;
|
||||
}
|
||||
if (selectedTags.size === 0) {
|
||||
return true;
|
||||
}
|
||||
return [...selectedTags].some((t) => asset.tags.includes(t));
|
||||
}
|
||||
|
||||
export const useGalleryStore = defineStore("gallery", () => {
|
||||
const allAssets = ref<GalleryAsset[]>([]);
|
||||
const isLoading = ref(false);
|
||||
const loadError = ref<string | null>(null);
|
||||
|
||||
const activeCollection = ref<Collection | "all">("all");
|
||||
const selectedTags = ref<Set<string>>(new Set());
|
||||
const visibleCount = ref(BATCH);
|
||||
const lightboxAssetId = ref<string | null>(null);
|
||||
|
||||
const filteredAssets = computed(() =>
|
||||
allAssets.value.filter((a) =>
|
||||
assetMatchesFilters(a, activeCollection.value, selectedTags.value),
|
||||
),
|
||||
);
|
||||
|
||||
const visibleAssets = computed(() =>
|
||||
filteredAssets.value.slice(0, visibleCount.value),
|
||||
);
|
||||
|
||||
const hasMore = computed(
|
||||
() => visibleCount.value < filteredAssets.value.length,
|
||||
);
|
||||
|
||||
const allTags = computed(() => {
|
||||
const s = new Set<string>();
|
||||
for (const a of allAssets.value) {
|
||||
for (const t of a.tags) {
|
||||
s.add(t);
|
||||
}
|
||||
}
|
||||
return [...s].sort((a, b) => a.localeCompare(b));
|
||||
});
|
||||
|
||||
function setCollection(c: Collection | "all") {
|
||||
activeCollection.value = c;
|
||||
}
|
||||
|
||||
async function init() {
|
||||
if (isLoading.value) {
|
||||
return;
|
||||
}
|
||||
isLoading.value = true;
|
||||
loadError.value = null;
|
||||
try {
|
||||
allAssets.value = await loadGalleryAssets();
|
||||
resetPagination();
|
||||
} catch (error) {
|
||||
loadError.value = "Unable to load gallery assets.";
|
||||
allAssets.value = [];
|
||||
resetPagination();
|
||||
console.error(error);
|
||||
} finally {
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTag(tag: string) {
|
||||
const next = new Set(selectedTags.value);
|
||||
if (next.has(tag)) {
|
||||
next.delete(tag);
|
||||
} else {
|
||||
next.add(tag);
|
||||
}
|
||||
selectedTags.value = next;
|
||||
}
|
||||
|
||||
function clearTags() {
|
||||
selectedTags.value = new Set();
|
||||
}
|
||||
|
||||
function loadMore() {
|
||||
if (!hasMore.value) {
|
||||
return;
|
||||
}
|
||||
visibleCount.value = Math.min(
|
||||
visibleCount.value + BATCH,
|
||||
filteredAssets.value.length,
|
||||
);
|
||||
}
|
||||
|
||||
function resetPagination() {
|
||||
visibleCount.value = Math.min(BATCH, filteredAssets.value.length);
|
||||
}
|
||||
|
||||
watch([activeCollection, selectedTags], () => {
|
||||
resetPagination();
|
||||
});
|
||||
|
||||
function openLightbox(assetId: string) {
|
||||
lightboxAssetId.value = assetId;
|
||||
}
|
||||
|
||||
function closeLightbox() {
|
||||
lightboxAssetId.value = null;
|
||||
}
|
||||
|
||||
const lightboxAsset = computed(() => {
|
||||
const id = lightboxAssetId.value;
|
||||
if (!id) {
|
||||
return null;
|
||||
}
|
||||
return filteredAssets.value.find((a) => a.id === id) ?? null;
|
||||
});
|
||||
|
||||
const lightboxIndex = computed(() => {
|
||||
const id = lightboxAssetId.value;
|
||||
if (!id) {
|
||||
return -1;
|
||||
}
|
||||
return filteredAssets.value.findIndex((a) => a.id === id);
|
||||
});
|
||||
|
||||
function stepLightbox(delta: number) {
|
||||
const list = filteredAssets.value;
|
||||
if (list.length === 0) {
|
||||
return;
|
||||
}
|
||||
let i = lightboxIndex.value;
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
const next = (i + delta + list.length) % list.length;
|
||||
lightboxAssetId.value = list[next]!.id;
|
||||
}
|
||||
|
||||
return {
|
||||
allAssets,
|
||||
isLoading,
|
||||
loadError,
|
||||
activeCollection,
|
||||
selectedTags,
|
||||
visibleAssets,
|
||||
filteredAssets,
|
||||
hasMore,
|
||||
allTags,
|
||||
setCollection,
|
||||
init,
|
||||
toggleTag,
|
||||
clearTags,
|
||||
loadMore,
|
||||
resetPagination,
|
||||
lightboxAssetId,
|
||||
lightboxAsset,
|
||||
lightboxIndex,
|
||||
openLightbox,
|
||||
closeLightbox,
|
||||
stepLightbox,
|
||||
};
|
||||
});
|
||||
Reference in new issue
Block a user