From 688373f46dc0a07b34b83b0a748b81e9610fdf77 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 21:50:54 +0300 Subject: [PATCH 01/11] add cypress tests for admin text summary page --- cypress/e2e/admin.cy.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/cypress/e2e/admin.cy.js b/cypress/e2e/admin.cy.js index c277eb9..c06aece 100644 --- a/cypress/e2e/admin.cy.js +++ b/cypress/e2e/admin.cy.js @@ -1,7 +1,24 @@ describe('The admin page', () => { - it('successfully loads texts', () => { - cy.visit('/admin') - cy.get('#newTextname').type('new text') - cy.get('#submit').click() + beforeEach(() => { + cy.visit('/admin') + }) + + it('navigates to texts page', () => { + cy.get('#texts').click() + cy.url().should('include', '/admin/texts') + }) + + it('shows texts page with heading and form', () => { + cy.visit('/admin/texts') + cy.get('h1').should('contain', 'Texts') + cy.get('#newTextName').should('exist') + cy.get('#submit').should('exist') + }) + + it('creates a new text', () => { + cy.visit('/admin/texts') + cy.get('#newTextName').type('Test Text') + cy.get('#submit').click() + cy.contains('Test Text') }) }) From 3165bff891e149bcb498e23820b95f0b224cb56e Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 21:51:30 +0300 Subject: [PATCH 02/11] put link to admin/texts in admin page --- views/templates/admin.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/views/templates/admin.php b/views/templates/admin.php index c027843..7f463d4 100644 --- a/views/templates/admin.php +++ b/views/templates/admin.php @@ -1,10 +1,9 @@ - Daily Goals + Daily Goals - Admin - - + Texts From e4001b564a37a24e77a98de11db332f80c7f3b14 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 21:53:11 +0300 Subject: [PATCH 03/11] add texts page for admin --- views/templates/texts.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 views/templates/texts.php diff --git a/views/templates/texts.php b/views/templates/texts.php new file mode 100644 index 0000000..b5058ab --- /dev/null +++ b/views/templates/texts.php @@ -0,0 +1,15 @@ + + + + Daily Goals - Texts + + +

Texts

+ Back to Admin +
    + {{texts}} +
+ + + + From 878e4840a20756461d176a3e8a5d5689163892bb Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 21:54:31 +0300 Subject: [PATCH 04/11] add getAll method to text repo --- app/Text/TextRepository.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/Text/TextRepository.php b/app/Text/TextRepository.php index a280407..d899bcf 100644 --- a/app/Text/TextRepository.php +++ b/app/Text/TextRepository.php @@ -10,4 +10,9 @@ interface TextRepository public function create(CreateTextDto $dto): Text; public function find(int $id): ?Text; + + /** + * @return Text[] + */ + public function getAll(): array; } From e9195fe9913b8f974aff57de3165c463f4042adb Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:05:10 +0300 Subject: [PATCH 05/11] implement text repo for json files --- app/Text/JsonTextRepository.php | 108 ++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 app/Text/JsonTextRepository.php diff --git a/app/Text/JsonTextRepository.php b/app/Text/JsonTextRepository.php new file mode 100644 index 0000000..fc8640d --- /dev/null +++ b/app/Text/JsonTextRepository.php @@ -0,0 +1,108 @@ +filePath = __DIR__.'/../../data/texts.json'; + } + + public function create(CreateTextDto $dto): Text + { + $texts = $this->readTexts(); + $id = $this->getNextId($texts); + + $text = new Text(id: $id, name: $dto->name); + $texts[] = ['id' => $id, 'name' => $dto->name]; + + $this->writeTexts($texts); + + return $text; + } + + public function find(int $id): ?Text + { + $texts = $this->readTexts(); + + foreach ($texts as $data) { + if ($data['id'] === $id) { + return new Text( + id: $data['id'], + name: $data['name'], + ); + } + } + + return null; + } + + /** + * @return Text[] + */ + public function getAll(): array + { + $texts = $this->readTexts(); + + return array_map( + function (array $data) { + return new Text( + id: $data['id'], + name: $data['name'], + ); + }, + $texts + ); + } + + /** + * @return array + */ + private function readTexts(): array + { + if (!file_exists($this->filePath)) { + return []; + } + + $content = file_get_contents($this->filePath); + + return json_decode($content, true) ?? []; + } + + /** + * @param array $texts + */ + private function writeTexts(array $texts): void + { + file_put_contents( + $this->filePath, + json_encode($texts, JSON_PRETTY_PRINT) + ); + } + + /** + * @param array $texts + */ + private function getNextId(array $texts): int + { + if (empty($texts)) { + return 1; + } + + $maxId = 0; + foreach ($texts as $text) { + if ($text['id'] > $maxId) { + $maxId = $text['id']; + } + } + + return $maxId + 1; + } +} From 21076f10e89dcdd8d207b5e209eaf3f373d0f859 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:05:36 +0300 Subject: [PATCH 06/11] init texts.json --- data/texts.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/texts.json diff --git a/data/texts.json b/data/texts.json new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/data/texts.json @@ -0,0 +1 @@ +[] From 0853aacdfb3d0e95f396fd701daa898a634b31bb Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:05:53 +0300 Subject: [PATCH 07/11] implement getAll in fake text repo --- tests/Fakes/FakeTextRepository.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/Fakes/FakeTextRepository.php b/tests/Fakes/FakeTextRepository.php index 86d3076..388e01c 100644 --- a/tests/Fakes/FakeTextRepository.php +++ b/tests/Fakes/FakeTextRepository.php @@ -47,4 +47,20 @@ class FakeTextRepository implements TextRepository { return count($this->existingTexts); } + + /** + * @return Text[] + */ + public function getAll(): array + { + return array_map( + function (Text $text) { + return new Text( + id: $text->getId(), + name: $text->getName(), + ); + }, + $this->existingTexts + ); + } } From 9a64d1dd5067afddeec83e830caa72f0f9d50ed3 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:06:15 +0300 Subject: [PATCH 08/11] bind text repo to json impl in container --- bootstrap/container.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/container.php b/bootstrap/container.php index 3a35c97..3ec249c 100644 --- a/bootstrap/container.php +++ b/bootstrap/container.php @@ -3,7 +3,7 @@ use DI\Container; $container = new Container([ - + \App\Text\TextRepository::class => \App\Text\JsonTextRepository::class, ]); return $container; From 52a68319dac7c8c338e18c703c37d0a150e20d5b Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:13:30 +0300 Subject: [PATCH 09/11] fix container binding --- bootstrap/container.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bootstrap/container.php b/bootstrap/container.php index 3ec249c..09a0d9a 100644 --- a/bootstrap/container.php +++ b/bootstrap/container.php @@ -1,9 +1,12 @@ \App\Text\JsonTextRepository::class, + TextRepository::class => DI\create(JsonTextRepository::class), ]); return $container; From 019f3a61e19566bad688d2c73d39783c29914290 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:13:56 +0300 Subject: [PATCH 10/11] add route for admin texts view --- bootstrap/app.php | 1 + 1 file changed, 1 insertion(+) diff --git a/bootstrap/app.php b/bootstrap/app.php index 1fc3b7e..5d081cd 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -12,5 +12,6 @@ $app = Bridge::create($container); $app->addErrorMiddleware(true, true, true); $app->get('/admin', [ViewController::class, 'admin']); +$app->get('/admin/texts', [ViewController::class, 'texts']); return $app; From d4e31baed0d1fb78ff23cb6bbbb8ff6771f1a831 Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 12 Apr 2026 22:14:30 +0300 Subject: [PATCH 11/11] implement texts view method --- app/View/ViewController.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/app/View/ViewController.php b/app/View/ViewController.php index fb46073..a9f4ccc 100644 --- a/app/View/ViewController.php +++ b/app/View/ViewController.php @@ -2,10 +2,15 @@ namespace App\View; +use App\Text\TextRepository; use Psr\Http\Message\ResponseInterface as Response; class ViewController { + public function __construct( + private TextRepository $textRepository, + ) {} + public function admin(Response $response): Response { $html = file_get_contents(__DIR__.'/../../views/templates/admin.php', true); @@ -13,4 +18,20 @@ class ViewController return $response; } + + public function texts(Response $response): Response + { + $texts = $this->textRepository->getAll(); + + $textsList = ''; + foreach ($texts as $text) { + $textsList .= '
  • ' . htmlspecialchars($text->getName()) . '
  • '; + } + + $html = file_get_contents(__DIR__.'/../../views/templates/texts.php', true); + $html = str_replace('{{texts}}', $textsList, $html); + $response->getBody()->write($html); + + return $response; + } }