58 lines
1.4 KiB
TypeScript
58 lines
1.4 KiB
TypeScript
// src/stores/albums.ts
|
|
import { ref, computed } from "vue";
|
|
import { defineStore } from "pinia";
|
|
import axios from "axios";
|
|
import type { Album } from "@/types/album";
|
|
|
|
const API_URL = "https://jsonplaceholder.typicode.com/albums";
|
|
|
|
export const useAlbumsStore = defineStore("albums", () => {
|
|
// ---- state ----
|
|
const albums = ref<Album[]>([]);
|
|
const loading = ref(false);
|
|
const error = ref<unknown>(null);
|
|
let loaded = false; // module-internal guard (not reactive)
|
|
|
|
// ---- getters ----
|
|
const titles = computed(() => albums.value.map((a) => a.title));
|
|
const count = computed(() => albums.value.length);
|
|
const isLoading = computed(() => loading.value);
|
|
|
|
// ---- actions ----
|
|
async function fetchAlbums(force = false) {
|
|
if (loaded && !force) return;
|
|
if (loading.value) return;
|
|
|
|
loading.value = true;
|
|
error.value = null;
|
|
try {
|
|
const { data } = await axios.get<Album[]>(API_URL);
|
|
albums.value = data.slice(0, 12);
|
|
loaded = true;
|
|
console.log("albums loaded:", albums.value.length);
|
|
} catch (e) {
|
|
error.value = e;
|
|
console.error("Error fetching albums!", e);
|
|
} finally {
|
|
loading.value = false;
|
|
}
|
|
}
|
|
|
|
function reset() {
|
|
albums.value = [];
|
|
error.value = null;
|
|
loaded = false;
|
|
}
|
|
|
|
return {
|
|
albums,
|
|
loading,
|
|
error,
|
|
titles,
|
|
count,
|
|
isLoading,
|
|
fetchAlbums,
|
|
reset,
|
|
};
|
|
});
|