From 535fb29e112abc88b41879e7905389fdfa29f3ab Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Mon, 25 May 2026 20:09:21 +0300 Subject: [PATCH] render media set cards --- frontend/rabbi_gerzi/src/stores/mediaSets.ts | 44 +++++++ frontend/rabbi_gerzi/src/views/MediaPage.vue | 116 ++++++++++++++++++- 2 files changed, 157 insertions(+), 3 deletions(-) create mode 100644 frontend/rabbi_gerzi/src/stores/mediaSets.ts diff --git a/frontend/rabbi_gerzi/src/stores/mediaSets.ts b/frontend/rabbi_gerzi/src/stores/mediaSets.ts new file mode 100644 index 0000000..c524fcb --- /dev/null +++ b/frontend/rabbi_gerzi/src/stores/mediaSets.ts @@ -0,0 +1,44 @@ +import { ref } from 'vue' +import { defineStore } from 'pinia' + +export interface MediaSet { + id: number + name: string +} + +interface SetsResponse { + sets: MediaSet[] +} + +const API_BASE_URL = import.meta.env.VITE_API_BASE_URL as string + +export const useMediaSetsStore = defineStore('mediaSets', () => { + const sets = ref([]) + const isLoading = ref(false) + const error = ref(null) + + async function fetchSets(): Promise { + error.value = null + isLoading.value = true + + try { + const response = await fetch(`${API_BASE_URL}/api/sets`) + + if (!response.ok) { + sets.value = [] + error.value = 'Could not load media sets' + return + } + + const data: SetsResponse = await response.json() + sets.value = data.sets + } catch { + sets.value = [] + error.value = 'Network error - could not load media sets' + } finally { + isLoading.value = false + } + } + + return { sets, isLoading, error, fetchSets } +}) diff --git a/frontend/rabbi_gerzi/src/views/MediaPage.vue b/frontend/rabbi_gerzi/src/views/MediaPage.vue index b405d36..74ea6e9 100644 --- a/frontend/rabbi_gerzi/src/views/MediaPage.vue +++ b/frontend/rabbi_gerzi/src/views/MediaPage.vue @@ -1,5 +1,15 @@ @@ -24,7 +64,7 @@ import SiteHeader from '@/components/SiteHeader.vue' } .media-page__main { - padding: 5rem 2rem; + padding: 5rem 2rem 6rem; } .media-page__hero { @@ -64,13 +104,83 @@ import SiteHeader from '@/components/SiteHeader.vue' line-height: 1.7; } +.media-page__sets { + max-width: 1100px; + margin: 3rem auto 0; +} + +.media-page__sets-header { + margin-bottom: 1.5rem; +} + +.media-page__section-heading { + margin: 0; + color: var(--color-slate); + font-family: var(--font-serif); + font-size: clamp(1.8rem, 3vw, 2.6rem); + font-weight: 400; + line-height: 1.2; +} + +.media-page__status { + margin: 0; + padding: 1rem 1.25rem; + color: var(--color-text-muted); + background: var(--color-white); + border: 1px solid var(--color-border); + border-radius: 8px; + font-size: 0.95rem; +} + +.media-page__status--error { + color: #7c2d2d; + border-color: #e5b8b8; +} + +.media-page__grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 1rem; +} + +.media-page__card { + min-height: 170px; + padding: 1.5rem; + background: var(--color-white); + border: 1px solid var(--color-border); + border-top: 4px solid var(--color-olive); + border-radius: 8px; +} + +.media-page__card-kicker { + margin: 0 0 0.8rem; + color: var(--color-olive); + font-size: 0.78rem; + font-weight: 700; + letter-spacing: 0.08em; + text-transform: uppercase; +} + +.media-page__card-title { + margin: 0; + color: var(--color-slate-dark); + font-family: var(--font-serif); + font-size: 1.45rem; + font-weight: 400; + line-height: 1.35; +} + @media (max-width: 768px) { .media-page__main { - padding: 3rem 1rem; + padding: 3rem 1rem 4rem; } .media-page__hero { padding: 3rem 1.5rem; } + + .media-page__sets { + margin-top: 2rem; + } }