From f8666454c394dec2d897d2224edf92ad6064a99a Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Thu, 2 Jul 2026 17:19:19 +0300 Subject: [PATCH] add set controls --- frontend/rabbi_gerzi/src/stores/mediaSets.ts | 114 ++++- frontend/rabbi_gerzi/src/views/MediaPage.vue | 461 ++++++++++++++++++- 2 files changed, 568 insertions(+), 7 deletions(-) diff --git a/frontend/rabbi_gerzi/src/stores/mediaSets.ts b/frontend/rabbi_gerzi/src/stores/mediaSets.ts index e869470..e669e85 100644 --- a/frontend/rabbi_gerzi/src/stores/mediaSets.ts +++ b/frontend/rabbi_gerzi/src/stores/mediaSets.ts @@ -15,11 +15,18 @@ export interface CreateMediaSetInput { iconImage: File } +export interface UpdateMediaSetInput { + id: number + name: string + description: string + iconImage: File | null +} + interface SetsResponse { sets: MediaSet[] } -interface CreateSetResponse { +interface SetResponse { set: MediaSet } @@ -34,7 +41,11 @@ export const useMediaSetsStore = defineStore('mediaSets', () => { const isLoading = ref(false) const error = ref(null) const isCreating = ref(false) + const isUpdating = ref(false) + const isDeleting = ref(false) const createError = ref(null) + const updateError = ref(null) + const deleteError = ref(null) async function fetchSets(): Promise { error.value = null @@ -83,7 +94,7 @@ export const useMediaSetsStore = defineStore('mediaSets', () => { return null } - const data: CreateSetResponse = await response.json() + const data: SetResponse = await response.json() sets.value = [...sets.value, data.set] return data.set @@ -95,13 +106,112 @@ export const useMediaSetsStore = defineStore('mediaSets', () => { } } + async function updateSet( + input: UpdateMediaSetInput, + ): Promise { + updateError.value = null + isUpdating.value = true + + const formData = new FormData() + formData.append('name', input.name) + formData.append('description', input.description) + if (input.iconImage !== null) { + formData.append('iconImage', input.iconImage) + } + + try { + const encodedSetId = encodeURIComponent(input.id.toString()) + const response = await fetch( + `${API_BASE_URL}/api/sets/${encodedSetId}/update`, + { + method: 'POST', + credentials: 'include', + body: formData, + }, + ) + + if (!response.ok) { + updateError.value = await errorMessage( + response, + 'Could not update media set', + ) + return null + } + + const data: SetResponse = await response.json() + sets.value = sets.value.map((mediaSet) => { + if (mediaSet.id === data.set.id) { + return data.set + } + + return mediaSet + }) + + return data.set + } catch { + updateError.value = 'Network error - could not update media set' + return null + } finally { + isUpdating.value = false + } + } + + async function deleteSet(setId: number): Promise { + deleteError.value = null + isDeleting.value = true + + try { + const encodedSetId = encodeURIComponent(setId.toString()) + const response = await fetch(`${API_BASE_URL}/api/sets/${encodedSetId}`, { + method: 'DELETE', + credentials: 'include', + }) + + if (!response.ok) { + deleteError.value = await errorMessage( + response, + 'Could not delete media set', + ) + return false + } + + sets.value = sets.value.filter((mediaSet) => { + return mediaSet.id !== setId + }) + return true + } catch { + deleteError.value = 'Network error - could not delete media set' + return false + } finally { + isDeleting.value = false + } + } + + async function errorMessage( + response: Response, + fallbackMessage: string, + ): Promise { + try { + const data: ErrorResponse = await response.json() + return data.error ?? fallbackMessage + } catch { + return fallbackMessage + } + } + return { sets, isLoading, error, isCreating, + isUpdating, + isDeleting, createError, + updateError, + deleteError, fetchSets, createSet, + updateSet, + deleteSet, } }) diff --git a/frontend/rabbi_gerzi/src/views/MediaPage.vue b/frontend/rabbi_gerzi/src/views/MediaPage.vue index 513a329..07f407b 100644 --- a/frontend/rabbi_gerzi/src/views/MediaPage.vue +++ b/frontend/rabbi_gerzi/src/views/MediaPage.vue @@ -1,11 +1,17 @@