From 47a522e44323a4d4be5b7716a2402f24544d4931 Mon Sep 17 00:00:00 2001 From: Gabriellvl Date: Fri, 21 Mar 2025 23:50:57 +0100 Subject: [PATCH] feat: basecontroller --- frontend/src/components/BrowseThemes.vue | 7 +- frontend/src/controller/fetch.ts | 20 ------ frontend/src/controller/themes.ts | 14 ---- frontend/src/controllers/base-controller.ts | 73 +++++++++++++++++++++ frontend/src/controllers/controllers.ts | 14 ++++ frontend/src/controllers/themes.ts | 16 +++++ 6 files changed, 108 insertions(+), 36 deletions(-) delete mode 100644 frontend/src/controller/fetch.ts delete mode 100644 frontend/src/controller/themes.ts create mode 100644 frontend/src/controllers/base-controller.ts create mode 100644 frontend/src/controllers/controllers.ts create mode 100644 frontend/src/controllers/themes.ts diff --git a/frontend/src/components/BrowseThemes.vue b/frontend/src/components/BrowseThemes.vue index ac67f42e..d3edcc89 100644 --- a/frontend/src/components/BrowseThemes.vue +++ b/frontend/src/components/BrowseThemes.vue @@ -3,7 +3,8 @@ import { ref, onMounted, watch } from "vue"; import { useI18n } from "vue-i18n"; import {AGE_TO_THEMES, THEMESITEMS} from "@/utils/constants.ts"; - import {getAllThemes} from "@/controller/themes.ts"; + import {getAllThemes} from "@/controllers/themes.ts"; + import {getThemeController} from "@/controllers/controllers.ts"; // Receive the selectedTheme and selectedAge from the parent component const props = defineProps({ @@ -17,6 +18,8 @@ } }); + const themeController = getThemeController(); + const {locale} = useI18n(); const allCards = ref>([]); @@ -29,7 +32,7 @@ const language = locale.value; // Update the cards value with the fetched themes - allCards.value = await getAllThemes(language); + allCards.value = await themeController.getAll(language); cards.value = allCards.value; } catch (error) { console.error("Error fetching themes:", error); diff --git a/frontend/src/controller/fetch.ts b/frontend/src/controller/fetch.ts deleted file mode 100644 index 09e9350b..00000000 --- a/frontend/src/controller/fetch.ts +++ /dev/null @@ -1,20 +0,0 @@ -export const fetchJson = async (url: string, init?: RequestInit): Promise => { - const response = await fetch(url, init); - - if (!response.ok) { - let errorMessage = `Error ${response.status} ${response.statusText}`; - - try { - const errorData = await response.json(); - if (errorData?.error) { - errorMessage = errorData.error; - } - } catch { - // No valid JSON or error property - } - - throw new Error(errorMessage); - } - - return await response.json(); -}; diff --git a/frontend/src/controller/themes.ts b/frontend/src/controller/themes.ts deleted file mode 100644 index 31e67446..00000000 --- a/frontend/src/controller/themes.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {fetchJson} from "@/controller/fetch.ts"; -import {API_BASE} from "../../config.ts"; - -export const getAllThemes = async (language: string | null = null) => { - const url = language - ? `${API_BASE}/theme?language=${encodeURIComponent(language)}` - : `${API_BASE}/theme`; - return await fetchJson(url); -}; - -export const getHruidsByTheme = async (theme: string) => { - const url = `${API_BASE}/theme/${encodeURIComponent(theme)}`; - return await fetchJson(url); -}; diff --git a/frontend/src/controllers/base-controller.ts b/frontend/src/controllers/base-controller.ts new file mode 100644 index 00000000..e422b4be --- /dev/null +++ b/frontend/src/controllers/base-controller.ts @@ -0,0 +1,73 @@ +import { API_BASE } from "../../config.ts"; + +export class BaseController { + protected baseUrl: string; + + constructor(basePath: string) { + this.baseUrl = `${API_BASE}/${basePath}`; + } + + protected async get(path: string, queryParams?: Record): Promise { + let url = `${this.baseUrl}${path}`; + if (queryParams) { + const query = new URLSearchParams(); + Object.entries(queryParams).forEach(([key, value]) => { + if (value !== undefined && value !== null) { + query.append(key, value.toString()); + } + }); + url += `?${query.toString()}`; + } + + const res = await fetch(url); + if (!res.ok) { + const errorData = await res.json().catch(() => ({})); + throw new Error(errorData?.error || `Error ${res.status}: ${res.statusText}`); + } + + return res.json(); + } + + protected async post(path: string, body: unknown): Promise { + const res = await fetch(`${this.baseUrl}${path}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }); + + if (!res.ok) { + const errorData = await res.json().catch(() => ({})); + throw new Error(errorData?.error || `Error ${res.status}: ${res.statusText}`); + } + + return res.json(); + } + + protected async delete(path: string): Promise { + const res = await fetch(`${this.baseUrl}${path}`, { + method: "DELETE", + }); + + if (!res.ok) { + const errorData = await res.json().catch(() => ({})); + throw new Error(errorData?.error || `Error ${res.status}: ${res.statusText}`); + } + + return res.json(); + } + + protected async put(path: string, body: unknown): Promise { + const res = await fetch(`${this.baseUrl}${path}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }); + + if (!res.ok) { + const errorData = await res.json().catch(() => ({})); + throw new Error(errorData?.error || `Error ${res.status}: ${res.statusText}`); + } + + return res.json(); + } +} diff --git a/frontend/src/controllers/controllers.ts b/frontend/src/controllers/controllers.ts new file mode 100644 index 00000000..b3bbeb61 --- /dev/null +++ b/frontend/src/controllers/controllers.ts @@ -0,0 +1,14 @@ +import {ThemeController} from "@/controllers/themes.ts"; + +export function controllerGetter(Factory: new () => T): () => T { + let instance: T | undefined; + + return (): T => { + if (!instance) { + instance = new Factory(); + } + return instance; + }; +} + +export const getThemeController = controllerGetter(ThemeController); diff --git a/frontend/src/controllers/themes.ts b/frontend/src/controllers/themes.ts new file mode 100644 index 00000000..447c9248 --- /dev/null +++ b/frontend/src/controllers/themes.ts @@ -0,0 +1,16 @@ +import {BaseController} from "@/controllers/base-controller.ts"; + +export class ThemeController extends BaseController { + constructor() { + super("theme"); + } + + getAll(language: string | null = null) { + const query = language ? { language } : undefined; + return this.get("/", query); + } + + getHruidsByKey(themeKey: string) { + return this.get(`/${encodeURIComponent(themeKey)}`); + } +}