From e3847edae10450aeec2a588a767641462d3679cb Mon Sep 17 00:00:00 2001 From: kaivalya Date: Thu, 9 Jul 2026 15:39:50 +0200 Subject: [PATCH] F7: Deduplicate the four CRUD composables useExercises/useCombos/useSessions/useCollections were the same 54 lines with a different repository (~160 duplicated lines). They are now one-liners over a createCrudComposable(repository, itemsKey) factory; the returned API is identical so no call site changes. Co-Authored-By: Claude Fable 5 --- src/composables/createCrudComposable.js | 71 +++++++++++++++++++++++++ src/composables/useCollections.js | 54 +------------------ src/composables/useCombos.js | 54 +------------------ src/composables/useExercises.js | 54 +------------------ src/composables/useSessions.js | 54 +------------------ 5 files changed, 79 insertions(+), 208 deletions(-) create mode 100644 src/composables/createCrudComposable.js diff --git a/src/composables/createCrudComposable.js b/src/composables/createCrudComposable.js new file mode 100644 index 0000000..2f1392f --- /dev/null +++ b/src/composables/createCrudComposable.js @@ -0,0 +1,71 @@ +import { ref } from 'vue' + +/** + * Factory for the four identical CRUD composables (exercises, combos, + * sessions, collections). Returns a composable exposing the reactive item + * list under `itemsKey` plus the shared loading/error/CRUD API, so + * useExercises & co. stay one-liners with unchanged call sites. + */ +export function createCrudComposable(repository, itemsKey) { + return function useCrud() { + const items = ref([]) + const loading = ref(false) + const error = ref(null) + + async function fetchAll() { + loading.value = true + error.value = null + try { + items.value = await repository.getAll() + } catch (e) { + error.value = e.message + } finally { + loading.value = false + } + } + + async function create(data) { + const id = await repository.create(data) + await fetchAll() + return id + } + + async function update(id, data) { + await repository.update(id, data) + await fetchAll() + } + + async function remove(id) { + await repository.delete(id) + await fetchAll() + } + + async function search(query) { + loading.value = true + error.value = null + try { + items.value = await repository.search(query) + } catch (e) { + error.value = e.message + } finally { + loading.value = false + } + } + + async function getById(id) { + return repository.getById(id) + } + + return { + [itemsKey]: items, + loading, + error, + fetchAll, + create, + update, + remove, + search, + getById, + } + } +} diff --git a/src/composables/useCollections.js b/src/composables/useCollections.js index 2679f3d..2f92a9c 100644 --- a/src/composables/useCollections.js +++ b/src/composables/useCollections.js @@ -1,54 +1,4 @@ -import { ref } from 'vue' import { collectionRepository } from '../db/repositories/collectionRepository.js' +import { createCrudComposable } from './createCrudComposable.js' -export function useCollections() { - const collections = ref([]) - const loading = ref(false) - const error = ref(null) - - async function fetchAll() { - loading.value = true - error.value = null - try { - collections.value = await collectionRepository.getAll() - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function create(data) { - const id = await collectionRepository.create(data) - await fetchAll() - return id - } - - async function update(id, data) { - await collectionRepository.update(id, data) - await fetchAll() - } - - async function remove(id) { - await collectionRepository.delete(id) - await fetchAll() - } - - async function search(query) { - loading.value = true - error.value = null - try { - collections.value = await collectionRepository.search(query) - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function getById(id) { - return collectionRepository.getById(id) - } - - return { collections, loading, error, fetchAll, create, update, remove, search, getById } -} +export const useCollections = createCrudComposable(collectionRepository, 'collections') diff --git a/src/composables/useCombos.js b/src/composables/useCombos.js index dcdcbc7..0121e3b 100644 --- a/src/composables/useCombos.js +++ b/src/composables/useCombos.js @@ -1,54 +1,4 @@ -import { ref } from 'vue' import { comboRepository } from '../db/repositories/comboRepository.js' +import { createCrudComposable } from './createCrudComposable.js' -export function useCombos() { - const combos = ref([]) - const loading = ref(false) - const error = ref(null) - - async function fetchAll() { - loading.value = true - error.value = null - try { - combos.value = await comboRepository.getAll() - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function create(data) { - const id = await comboRepository.create(data) - await fetchAll() - return id - } - - async function update(id, data) { - await comboRepository.update(id, data) - await fetchAll() - } - - async function remove(id) { - await comboRepository.delete(id) - await fetchAll() - } - - async function search(query) { - loading.value = true - error.value = null - try { - combos.value = await comboRepository.search(query) - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function getById(id) { - return comboRepository.getById(id) - } - - return { combos, loading, error, fetchAll, create, update, remove, search, getById } -} +export const useCombos = createCrudComposable(comboRepository, 'combos') diff --git a/src/composables/useExercises.js b/src/composables/useExercises.js index 57797d0..6e91b85 100644 --- a/src/composables/useExercises.js +++ b/src/composables/useExercises.js @@ -1,54 +1,4 @@ -import { ref } from 'vue' import { exerciseRepository } from '../db/repositories/exerciseRepository.js' +import { createCrudComposable } from './createCrudComposable.js' -export function useExercises() { - const exercises = ref([]) - const loading = ref(false) - const error = ref(null) - - async function fetchAll() { - loading.value = true - error.value = null - try { - exercises.value = await exerciseRepository.getAll() - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function create(data) { - const id = await exerciseRepository.create(data) - await fetchAll() - return id - } - - async function update(id, data) { - await exerciseRepository.update(id, data) - await fetchAll() - } - - async function remove(id) { - await exerciseRepository.delete(id) - await fetchAll() - } - - async function search(query) { - loading.value = true - error.value = null - try { - exercises.value = await exerciseRepository.search(query) - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function getById(id) { - return exerciseRepository.getById(id) - } - - return { exercises, loading, error, fetchAll, create, update, remove, search, getById } -} +export const useExercises = createCrudComposable(exerciseRepository, 'exercises') diff --git a/src/composables/useSessions.js b/src/composables/useSessions.js index f96596e..6f9d138 100644 --- a/src/composables/useSessions.js +++ b/src/composables/useSessions.js @@ -1,54 +1,4 @@ -import { ref } from 'vue' import { sessionRepository } from '../db/repositories/sessionRepository.js' +import { createCrudComposable } from './createCrudComposable.js' -export function useSessions() { - const sessions = ref([]) - const loading = ref(false) - const error = ref(null) - - async function fetchAll() { - loading.value = true - error.value = null - try { - sessions.value = await sessionRepository.getAll() - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function create(data) { - const id = await sessionRepository.create(data) - await fetchAll() - return id - } - - async function update(id, data) { - await sessionRepository.update(id, data) - await fetchAll() - } - - async function remove(id) { - await sessionRepository.delete(id) - await fetchAll() - } - - async function search(query) { - loading.value = true - error.value = null - try { - sessions.value = await sessionRepository.search(query) - } catch (e) { - error.value = e.message - } finally { - loading.value = false - } - } - - async function getById(id) { - return sessionRepository.getById(id) - } - - return { sessions, loading, error, fetchAll, create, update, remove, search, getById } -} +export const useSessions = createCrudComposable(sessionRepository, 'sessions')