diff --git a/ai/shared.md b/ai/shared.md index b183a7b..3d0522e 100644 --- a/ai/shared.md +++ b/ai/shared.md @@ -20,13 +20,6 @@ guides (`backend-context.md`, `frontend-context.md`) extend these. batch multiple behaviors into one failing-test commit and one implementation commit when they can be reviewed separately. -## Runtime assumptions - -- Assume every process defined in `process-compose.yml` is already running - for local development and verification unless a command proves otherwise. - Do not start duplicate PostgreSQL, backend, or frontend processes just to - run checks. - ## Code style - Lines should not exceed 80 columns, but should use up to 80 columns when diff --git a/backend/app/Controllers/SetController.php b/backend/app/Controllers/SetController.php index 6fcbb8c..1a035c9 100644 --- a/backend/app/Controllers/SetController.php +++ b/backend/app/Controllers/SetController.php @@ -2,17 +2,14 @@ namespace App\Controllers; -use App\Element\ElementRepository; use App\Set\Set as DomainSet; use App\Set\SetRepository; use Illuminate\Http\JsonResponse; class SetController { - public function __construct( - private SetRepository $setRepository, - private ElementRepository $elementRepository, - ) { + public function __construct(private SetRepository $setRepository) + { } public function index(): JsonResponse @@ -32,20 +29,16 @@ class SetController * id: int, * name: string, * description: string, - * iconImageUrl: string, - * rootElementId: int|null + * iconImageUrl: string * } */ private function buildSetPayload(DomainSet $set): array { - $rootElement = $this->elementRepository->findRootBySet($set); - return [ 'id' => $set->getId(), 'name' => $set->getName(), 'description' => $set->getDescription(), 'iconImageUrl' => $set->getIconImageUrl(), - 'rootElementId' => $rootElement?->getId(), ]; } } diff --git a/backend/app/Element/ElementRepository.php b/backend/app/Element/ElementRepository.php index 8ed13bd..4f39fb6 100644 --- a/backend/app/Element/ElementRepository.php +++ b/backend/app/Element/ElementRepository.php @@ -10,8 +10,6 @@ interface ElementRepository public function find(int $id): ?Element; - public function findRootBySet(DomainSet $set): ?Element; - /** * @return Element[] */ diff --git a/backend/app/Element/EloquentElementRepository.php b/backend/app/Element/EloquentElementRepository.php index 68452de..61e1433 100644 --- a/backend/app/Element/EloquentElementRepository.php +++ b/backend/app/Element/EloquentElementRepository.php @@ -35,16 +35,6 @@ class EloquentElementRepository implements ElementRepository return $model === null ? null : $this->toDomain($model); } - public function findRootBySet(DomainSet $set): ?Element - { - $model = ElementModel::where('set_id', $set->getId()) - ->whereNull('parent_element_id') - ->orderBy('id') - ->first(); - - return $model === null ? null : $this->toDomain($model); - } - /** * @return Element[] */ diff --git a/backend/database/seeders/SetSeeder.php b/backend/database/seeders/SetSeeder.php index a8f28ac..b2ca3b5 100644 --- a/backend/database/seeders/SetSeeder.php +++ b/backend/database/seeders/SetSeeder.php @@ -11,19 +11,14 @@ class SetSeeder extends Seeder public function run(): void { $setRepository = app(SetRepository::class); - $baderechTitle = 'Baderech HaAvodah'; + $title = 'Baderech HaAvodah'; - $setRepository->create(new CreateSetDto( - name: $baderechTitle, + $set = $setRepository->create(new CreateSetDto( + name: $title, description: 'Baderech HaAvodah is a way of living - ' . 'a structured path for inner and outer growth, ' . 'spiritual refinement, and personal development.', iconImageUrl: '/assets/baderech-haavodah-icon.png', )); - $setRepository->create(new CreateSetDto( - name: 'Daily Learning', - description: 'Daily learning for steady growth', - iconImageUrl: '/assets/daily-learning-icon.svg', - )); } } diff --git a/backend/tests/Fakes/FakeElementRepository.php b/backend/tests/Fakes/FakeElementRepository.php index cbb4e13..65dbcad 100644 --- a/backend/tests/Fakes/FakeElementRepository.php +++ b/backend/tests/Fakes/FakeElementRepository.php @@ -37,20 +37,6 @@ class FakeElementRepository implements ElementRepository return $this->cloneElement($this->elementsById[$id]); } - public function findRootBySet(DomainSet $set): ?Element - { - foreach ($this->elementsById as $element) { - if ( - $element->getSet()->getId() === $set->getId() - && $element->getParentElement() === null - ) { - return $this->cloneElement($element); - } - } - - return null; - } - /** * @return Element[] */ diff --git a/backend/tests/Feature/SetsEndpointTest.php b/backend/tests/Feature/SetsEndpointTest.php index 6b79a7a..f1ab5cc 100644 --- a/backend/tests/Feature/SetsEndpointTest.php +++ b/backend/tests/Feature/SetsEndpointTest.php @@ -2,8 +2,6 @@ namespace Tests\Feature; -use App\Element\CreateElementDto; -use App\Element\ElementRepository; use App\Set\CreateSetDto; use App\Set\SetRepository; use Illuminate\Foundation\Testing\RefreshDatabase; @@ -16,7 +14,6 @@ class SetsEndpointTest extends TestCase public function testReturnsAllSets(): void { $setRepository = app(SetRepository::class); - $elementRepository = app(ElementRepository::class); $baderechSet = $setRepository->create(new CreateSetDto( name: 'Baderech HaAvodah', description: 'Baderech HaAvodah is a way of living', @@ -27,13 +24,6 @@ class SetsEndpointTest extends TestCase description: 'Daily learning for steady growth', iconImageUrl: '/assets/daily-learning-icon.svg', )); - $baderechRootElement = $elementRepository->create( - new CreateElementDto( - set: $baderechSet, - title: $baderechSet->getName(), - parentElement: null, - ) - ); $response = $this->getJson('/api/sets'); @@ -45,14 +35,12 @@ class SetsEndpointTest extends TestCase 'name' => $baderechSet->getName(), 'description' => $baderechSet->getDescription(), 'iconImageUrl' => $baderechSet->getIconImageUrl(), - 'rootElementId' => $baderechRootElement->getId(), ], [ 'id' => $dailyLearningSet->getId(), 'name' => $dailyLearningSet->getName(), 'description' => $dailyLearningSet->getDescription(), 'iconImageUrl' => $dailyLearningSet->getIconImageUrl(), - 'rootElementId' => null, ], ], ]); diff --git a/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts b/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts index 2a093a0..1202ae9 100644 --- a/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts +++ b/frontend/rabbi_gerzi/cypress/e2e/media.cy.ts @@ -11,11 +11,8 @@ describe('media page sets', () => { cy.contains('h1', 'Torah Media').should('be.visible') cy.get('[data-cy="media-set-grid"]').should('be.visible') cy.get('[data-cy="media-set-card"]', { timeout: 10000 }) - .should('have.length', 2) - - cy.contains('[data-cy="media-set-card"]', 'Baderech HaAvodah') - .as('baderechCard') - .should('have.attr', 'href', '/element/1') + .should('have.length', 1) + .first() .within(() => { cy.get('img[data-cy="media-set-icon"]') .should('be.visible') @@ -25,21 +22,5 @@ describe('media page sets', () => { cy.contains('a structured path for inner and outer growth') .should('be.visible') }) - - cy.contains('[data-cy="media-set-card"]', 'Daily Learning') - .as('dailyLearningCard') - .should('match', 'article') - .and('not.have.attr', 'href') - - cy.get('@dailyLearningCard') - .within(() => { - cy.contains('h2', 'Daily Learning').should('be.visible') - cy.contains('Daily learning for steady growth').should('be.visible') - }) - - cy.get('@baderechCard').click() - cy.location('pathname').should('eq', '/element/1') - cy.get('[data-cy="element-page"]').should('be.visible') - cy.contains('h1', 'Element 1').should('be.visible') }) }) diff --git a/frontend/rabbi_gerzi/src/router/index.ts b/frontend/rabbi_gerzi/src/router/index.ts index 3d5962f..6c71efd 100644 --- a/frontend/rabbi_gerzi/src/router/index.ts +++ b/frontend/rabbi_gerzi/src/router/index.ts @@ -2,7 +2,6 @@ import { createRouter, createWebHistory } from 'vue-router' import HomePage from '@/views/HomePage.vue' import LoginPage from '@/views/LoginPage.vue' import MediaPage from '@/views/MediaPage.vue' -import ElementPage from '@/views/ElementPage.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -22,11 +21,6 @@ const router = createRouter({ name: 'media', component: MediaPage, }, - { - path: '/element/:id', - name: 'element', - component: ElementPage, - }, ], }) diff --git a/frontend/rabbi_gerzi/src/stores/mediaSets.ts b/frontend/rabbi_gerzi/src/stores/mediaSets.ts index b899929..0ed97dd 100644 --- a/frontend/rabbi_gerzi/src/stores/mediaSets.ts +++ b/frontend/rabbi_gerzi/src/stores/mediaSets.ts @@ -6,7 +6,6 @@ export interface MediaSet { name: string description: string iconImageUrl: string - rootElementId: number | null } interface SetsResponse { diff --git a/frontend/rabbi_gerzi/src/views/ElementPage.vue b/frontend/rabbi_gerzi/src/views/ElementPage.vue deleted file mode 100644 index 22191ce..0000000 --- a/frontend/rabbi_gerzi/src/views/ElementPage.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - - - diff --git a/frontend/rabbi_gerzi/src/views/MediaPage.vue b/frontend/rabbi_gerzi/src/views/MediaPage.vue index c1880cd..314d3d3 100644 --- a/frontend/rabbi_gerzi/src/views/MediaPage.vue +++ b/frontend/rabbi_gerzi/src/views/MediaPage.vue @@ -33,41 +33,23 @@ onMounted(() => { No media sets are available yet.

- +
+ +

{{ mediaSet.name }}

+

+ {{ mediaSet.description }} +

+
@@ -132,29 +114,7 @@ onMounted(() => { background: var(--color-white); border: 1px solid #e5cf9f; border-radius: 17px; - color: inherit; text-align: center; - text-decoration: none; - transition: - border-color 180ms ease, - box-shadow 180ms ease, - transform 180ms ease; -} - -a.media-page__card:hover, -a.media-page__card:focus-visible { - border-color: #d4ad5f; - box-shadow: 0 14px 35px rgb(44 44 44 / 10%); - transform: translateY(-2px); -} - -a.media-page__card:focus-visible { - outline: 3px solid rgb(212 173 95 / 45%); - outline-offset: 4px; -} - -.media-page__card--disabled { - opacity: 0.72; } .media-page__card-icon {