Compare commits

...

5 commits

5 changed files with 88 additions and 38 deletions

View file

@ -0,0 +1,53 @@
<?php
namespace App\Text;
use App\Text\TextRepository;
use App\Text\UseCases\CreateText;
use App\Text\UseCases\CreateTextRequest;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
class TextController
{
public function __construct(
private TextRepository $textRepository,
) {}
public function getTexts(Response $response): Response
{
$texts = $this->textRepository->getAll();
$data = array_map(fn($text) => [
'id' => $text->getId(),
'name' => $text->getName(),
], $texts);
$response->getBody()->write(json_encode($data));
return $response->withHeader('Content-Type', 'application/json');
}
public function createText(
Request $request,
Response $response,
CreateText $createTextUseCase,
): Response {
$data = $request->getParsedBody();
$name = $data['name'] ?? '';
if (!empty($name)) {
$text = $createTextUseCase->execute(new CreateTextRequest(
name: $name,
));
$response->getBody()->write(json_encode([
'id' => $text->getId(),
'name' => $text->getName(),
]));
return $response->withHeader('Content-Type', 'application/json');
}
$response->getBody()->write(json_encode(['error' => 'Name is required']));
return $response->withStatus(400);
}
}

View file

@ -2,19 +2,10 @@
namespace App\View;
use App\Text\CreateTextDto;
use App\Text\TextRepository;
use App\Text\UseCases\CreateText;
use App\Text\UseCases\CreateTextRequest;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
class ViewController
{
public function __construct(
private TextRepository $textRepository,
) {}
public function admin(Response $response): Response
{
$html = file_get_contents(__DIR__.'/../../views/templates/admin.php', true);
@ -25,34 +16,9 @@ class ViewController
public function texts(Response $response): Response
{
$texts = $this->textRepository->getAll();
$textsList = '';
foreach ($texts as $text) {
$textsList .= '<li>' . htmlspecialchars($text->getName()) . '</li>';
}
$html = file_get_contents(__DIR__.'/../../views/templates/texts.php', true);
$html = str_replace('{{texts}}', $textsList, $html);
$response->getBody()->write($html);
return $response;
}
public function createText(
Request $request,
Response $response,
CreateText $createTextUseCase,
): Response {
$data = $request->getParsedBody();
$name = $data['name'] ?? '';
if (!empty($name)) {
$createTextUseCase->execute(new CreateTextRequest(
name: $name,
));
}
return $response->withHeader('Location', '/admin/texts')->withStatus(302);
}
}

View file

@ -4,6 +4,7 @@ use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use DI\Bridge\Slim\Bridge;
use App\View\ViewController;
use App\Text\TextController;
$container = require __DIR__.'/container.php';
$app = Bridge::create($container);
@ -13,6 +14,8 @@ $app->addErrorMiddleware(true, true, true);
$app->get('/admin', [ViewController::class, 'admin']);
$app->get('/admin/texts', [ViewController::class, 'texts']);
$app->post('/admin/texts', [ViewController::class, 'createText']);
$app->get('/api/texts', [TextController::class, 'getTexts']);
$app->post('/api/texts', [TextController::class, 'createText']);
return $app;

28
public/js/texts.js Normal file
View file

@ -0,0 +1,28 @@
document.addEventListener('DOMContentLoaded', () => {
const textsList = document.getElementById('texts-list');
const form = document.getElementById('texts-form');
async function loadTexts() {
const res = await fetch('/api/texts');
const texts = await res.json();
textsList.innerHTML = texts.map(text => '<li>' + text.name + '</li>').join('');
}
form.addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(form);
const res = await fetch('/api/texts', {
method: 'POST',
body: formData,
});
if (res.ok) {
const text = await res.json();
const li = document.createElement('li');
li.textContent = text.name;
textsList.appendChild(li);
form.reset();
}
});
loadTexts();
});

View file

@ -7,11 +7,11 @@
<h1>Texts</h1>
<a href="/admin" id="back">Back to Admin</a>
<ul id="texts-list">
{{texts}}
</ul>
<form action="/admin/texts" method="POST">
<form id="texts-form" action="/api/texts" method="POST">
<input id="newTextName" name="name"/>
<button id="submit">submit</button>
</form>
<script src="/js/texts.js"></script>
</body>
</html>
</html>