first commit
This commit is contained in:
60
views/pages/account/password-change.twig
Normal file
60
views/pages/account/password-change.twig
Normal file
@@ -0,0 +1,60 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}Mon compte – Changer le mot de passe{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-container form-container--narrow">
|
||||
<div class="form-container__panel">
|
||||
<div class="form-container__header">
|
||||
<h2 class="form-container__title">Changer le mot de passe</h2>
|
||||
</div>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert--danger">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if success %}
|
||||
<div class="alert alert--success">{{ success }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/account/password" class="form-container__form">
|
||||
<input type="hidden" name="{{ csrf.keys.name }}" value="{{ csrf.name }}">
|
||||
<input type="hidden" name="{{ csrf.keys.value }}" value="{{ csrf.value }}">
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="current_password" class="form-container__label">
|
||||
<span>Mot de passe actuel</span>
|
||||
<input type="password" id="current_password" name="current_password" required autofocus
|
||||
class="form-container__input">
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="new_password" class="form-container__label">
|
||||
<span>Nouveau mot de passe</span>
|
||||
<input type="password" id="new_password" name="new_password" required minlength="8"
|
||||
class="form-container__input">
|
||||
</label>
|
||||
<small class="form-container__hint">Minimum 8 caractères</small>
|
||||
</p>
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="new_password_confirm" class="form-container__label">
|
||||
<span>Confirmer le nouveau mot de passe</span>
|
||||
<input type="password" id="new_password_confirm" name="new_password_confirm" required minlength="8"
|
||||
class="form-container__input">
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<div class="form-container__actions">
|
||||
<div class="form-container__action">
|
||||
<button type="submit" class="btn btn--primary btn--lg btn--full">Mettre à jour</button>
|
||||
</div>
|
||||
<div class="form-container__action">
|
||||
<a href="{{ back_url }}" class="btn btn--secondary btn--lg btn--full">Annuler</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
50
views/pages/auth/login.twig
Normal file
50
views/pages/auth/login.twig
Normal file
@@ -0,0 +1,50 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}Connexion – Slim Blog{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-container form-container--narrow">
|
||||
<div class="form-container__panel">
|
||||
<div class="form-container__header">
|
||||
<h2 class="form-container__title">Connexion</h2>
|
||||
</div>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert--danger">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if success %}
|
||||
<div class="alert alert--success">{{ success }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/auth/login" class="form-container__form">
|
||||
<input type="hidden" name="{{ csrf.keys.name }}" value="{{ csrf.name }}">
|
||||
<input type="hidden" name="{{ csrf.keys.value }}" value="{{ csrf.value }}">
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="username" class="form-container__label">
|
||||
<span>Nom d'utilisateur</span>
|
||||
<input type="text" id="username" name="username" required autofocus class="form-container__input">
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="password" class="form-container__label">
|
||||
<span>Mot de passe</span>
|
||||
<input type="password" id="password" name="password" required class="form-container__input">
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<div class="form-container__actions">
|
||||
<div class="form-container__action">
|
||||
<button type="submit" class="btn btn--primary btn--lg btn--full">Se connecter</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="form-container__footer">
|
||||
<a href="/password/forgot">Mot de passe oublié ?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
44
views/pages/auth/password-forgot.twig
Normal file
44
views/pages/auth/password-forgot.twig
Normal file
@@ -0,0 +1,44 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}Mot de passe oublié – Slim Blog{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-container form-container--narrow">
|
||||
<div class="form-container__panel">
|
||||
<div class="form-container__header">
|
||||
<h2 class="form-container__title">Mot de passe oublié</h2>
|
||||
<p class="form-container__intro">Saisissez votre adresse email. Si elle est associée à un compte, vous recevrez un lien de réinitialisation.</p>
|
||||
</div>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert--danger">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
{% if success %}
|
||||
<div class="alert alert--success">{{ success }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/password/forgot" class="form-container__form">
|
||||
<input type="hidden" name="{{ csrf.keys.name }}" value="{{ csrf.name }}">
|
||||
<input type="hidden" name="{{ csrf.keys.value }}" value="{{ csrf.value }}">
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="email" class="form-container__label">
|
||||
<span>Adresse email</span>
|
||||
<input type="email" id="email" name="email" required autofocus class="form-container__input">
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<div class="form-container__actions">
|
||||
<div class="form-container__action">
|
||||
<button type="submit" class="btn btn--primary btn--lg btn--full">Envoyer le lien</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="form-container__footer">
|
||||
<a href="/auth/login">← Retour à la connexion</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
46
views/pages/auth/password-reset.twig
Normal file
46
views/pages/auth/password-reset.twig
Normal file
@@ -0,0 +1,46 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}Réinitialisation du mot de passe – Slim Blog{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="form-container form-container--narrow">
|
||||
<div class="form-container__panel">
|
||||
<div class="form-container__header">
|
||||
<h2 class="form-container__title">Nouveau mot de passe</h2>
|
||||
</div>
|
||||
|
||||
{% if error %}
|
||||
<div class="alert alert--danger">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/password/reset" class="form-container__form">
|
||||
<input type="hidden" name="{{ csrf.keys.name }}" value="{{ csrf.name }}">
|
||||
<input type="hidden" name="{{ csrf.keys.value }}" value="{{ csrf.value }}">
|
||||
<input type="hidden" name="token" value="{{ token }}">
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="new_password" class="form-container__label">
|
||||
<span>Nouveau mot de passe</span>
|
||||
<input type="password" id="new_password" name="new_password"
|
||||
required minlength="8" autofocus class="form-container__input">
|
||||
</label>
|
||||
<small class="form-container__hint">Minimum 8 caractères</small>
|
||||
</p>
|
||||
|
||||
<p class="form-container__field">
|
||||
<label for="new_password_confirm" class="form-container__label">
|
||||
<span>Confirmer le mot de passe</span>
|
||||
<input type="password" id="new_password_confirm" name="new_password_confirm"
|
||||
required minlength="8" class="form-container__input">
|
||||
</label>
|
||||
</p>
|
||||
|
||||
<div class="form-container__actions">
|
||||
<div class="form-container__action">
|
||||
<button type="submit" class="btn btn--primary btn--lg btn--full">Réinitialiser</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
11
views/pages/error.twig
Normal file
11
views/pages/error.twig
Normal file
@@ -0,0 +1,11 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}{{ status }} – Slim Blog{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="error-page">
|
||||
<h2 class="error-page__code">{{ status }}</h2>
|
||||
<p class="error-page__message">{{ message }}</p>
|
||||
<p><a href="/">← Retour à l'accueil</a></p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
94
views/pages/home.twig
Normal file
94
views/pages/home.twig
Normal file
@@ -0,0 +1,94 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}Slim Blog{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
<meta name="description" content="{% if activeCategory %}Articles de la catégorie {{ activeCategory.name }} — {% endif %}Slim Blog, un blog propulsé par Slim 4.">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Slim Blog">
|
||||
<meta property="og:description" content="Un blog propulsé par Slim 4.">
|
||||
<meta property="og:url" content="{{ app_url }}/">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="get" action="/" class="search-bar">
|
||||
{% if activeCategory %}
|
||||
<input type="hidden" name="categorie" value="{{ activeCategory.slug }}">
|
||||
{% endif %}
|
||||
<input type="search" name="q" value="{{ searchQuery }}"
|
||||
placeholder="Rechercher un article…" class="search-bar__input" aria-label="Recherche">
|
||||
<button type="submit" class="search-bar__btn">Rechercher</button>
|
||||
{% if searchQuery %}
|
||||
<a href="/{% if activeCategory %}?categorie={{ activeCategory.slug }}{% endif %}" class="search-bar__reset">✕</a>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% if searchQuery %}
|
||||
<p class="search-bar__info">
|
||||
{% if posts is not empty %}
|
||||
{{ posts|length }} résultat{{ posts|length > 1 ? 's' : '' }} pour « {{ searchQuery }} »
|
||||
{% else %}
|
||||
Aucun résultat pour « {{ searchQuery }} »
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% if categories is not empty %}
|
||||
<nav class="category-filter">
|
||||
<a href="/"
|
||||
class="category-filter__item{% if activeCategory is null %} category-filter__item--active{% endif %}">
|
||||
Tous
|
||||
</a>
|
||||
{% for category in categories %}
|
||||
<a href="/?categorie={{ category.slug }}"
|
||||
class="category-filter__item{% if activeCategory and activeCategory.id == category.id %} category-filter__item--active{% endif %}">
|
||||
{{ category.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</nav>
|
||||
{% endif %}
|
||||
|
||||
<div class="card-list card-list--contained">
|
||||
{% for post in posts %}
|
||||
{% set thumb = post_thumbnail(post) %}
|
||||
<article class="card">
|
||||
|
||||
<a href="{{ post_url(post) }}" class="card__thumb-link" tabindex="-1" aria-hidden="true">
|
||||
{% if thumb %}
|
||||
<img class="card__thumb" src="{{ thumb }}" alt="">
|
||||
{% else %}
|
||||
<span class="card__initials" aria-hidden="true">{{ post_initials(post) }}</span>
|
||||
{% endif %}
|
||||
</a>
|
||||
|
||||
<div class="card__content">
|
||||
<div class="card__body">
|
||||
<h2 class="card__title">
|
||||
<a href="{{ post_url(post) }}" class="card__title-link">{{ post.title }}</a>
|
||||
</h2>
|
||||
|
||||
<div class="card__meta">
|
||||
<small>
|
||||
Publié le {{ post.createdAt|date("d/m/Y à H:i") }}
|
||||
par <strong>{{ post.authorUsername ?? 'inconnu' }}</strong>
|
||||
</small>
|
||||
{% if post.categoryName %}
|
||||
<a href="/?categorie={{ post.categorySlug }}" class="badge badge--category">{{ post.categoryName }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<p class="card__excerpt">{{ post_excerpt(post) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="card__actions">
|
||||
<a href="{{ post_url(post) }}" class="card__actions-link">Lire la suite →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</article>
|
||||
{% else %}
|
||||
<p>Aucun article publié{% if searchQuery %} pour « {{ searchQuery }} »{% elseif activeCategory %} dans cette catégorie{% endif %}.</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
48
views/pages/post/detail.twig
Normal file
48
views/pages/post/detail.twig
Normal file
@@ -0,0 +1,48 @@
|
||||
{% extends "layout.twig" %}
|
||||
|
||||
{% block title %}{{ post.title }} – Slim Blog{% endblock %}
|
||||
|
||||
{% block meta %}
|
||||
{% set excerpt = post_excerpt(post, 160) %}
|
||||
{% set thumb = post_thumbnail(post) %}
|
||||
<meta name="description" content="{{ excerpt }}">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="og:title" content="{{ post.title }}">
|
||||
<meta property="og:description" content="{{ excerpt }}">
|
||||
<meta property="og:url" content="{{ app_url }}{{ post_url(post) }}">
|
||||
{% if thumb %}
|
||||
<meta property="og:image" content="{{ app_url }}{{ thumb }}">
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<article class="post">
|
||||
<h1>{{ post.title }}</h1>
|
||||
|
||||
<div class="post__meta">
|
||||
<small>
|
||||
Publié le {{ post.createdAt|date("d/m/Y à H:i") }}
|
||||
par <strong>{{ post.authorUsername ?? 'inconnu' }}</strong>
|
||||
</small>
|
||||
{% if post.categoryName %}
|
||||
<a href="/?categorie={{ post.categorySlug }}" class="badge badge--category">{{ post.categoryName }}</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if post.updatedAt != post.createdAt %}
|
||||
<div class="post__updated">
|
||||
<small><em>Mis à jour le {{ post.updatedAt|date("d/m/Y à H:i") }}</em></small>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="post__content">
|
||||
{# Le contenu est déjà sanitisé par HtmlSanitizer via PostService #}
|
||||
{{ post.content|raw }}
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<p>
|
||||
<a href="/">← Retour aux articles</a>
|
||||
</p>
|
||||
</article>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user