Replace v1 with v2 codebase
Full rewrite: swap out the v1 framework (src/, controllers/, views/, twig/, sass/, skeleton/) for the working v2 codebase from phpproject (App/, novaconium/, public/).
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
{% extends layout %}
|
||||
|
||||
{% block title %}Contact{% endblock %}
|
||||
{% block description %}Get in touch — send a message using the contact form.{% endblock %}
|
||||
|
||||
{# Every block below is optional — the layout already supplies a sensible
|
||||
default for each (see /admin/docs/seo). Shown here uncommented as a
|
||||
reference for every override a page can make; delete what you don't
|
||||
need. #}
|
||||
{% block robots %}index, follow{% endblock %}
|
||||
{% block canonical %}{{ request_path|default('/') }}{% endblock %}
|
||||
|
||||
{% block og_type %}website{% endblock %}
|
||||
{% block og_title %}{{ block('title') }}{% endblock %}
|
||||
{% block og_description %}{{ block('description') }}{% endblock %}
|
||||
{% block og_url %}{{ block('canonical') }}{% endblock %}
|
||||
|
||||
{% block twitter_card %}summary{% endblock %}
|
||||
{% block twitter_title %}{{ block('title') }}{% endblock %}
|
||||
{% block twitter_description %}{{ block('description') }}{% endblock %}
|
||||
|
||||
{% import '_layout/icons.twig' as icons %}
|
||||
|
||||
{% block content %}
|
||||
<article>
|
||||
<h1 class="icon-heading">{{ icons.email() }}Contact</h1>
|
||||
|
||||
<p>This form is handled entirely by <code>App/pages/contact/index.php</code>, a sidecar demonstrating the classic POST/redirect/GET pattern: it validates <code>$_POST</code>, calls <code>Lib\Mailer::send()</code> on success, and redirects to <code>/contact?sent=1</code> — so refreshing the page after submitting never resubmits the form. Because this page has a sidecar, it's never served from the static cache; see <a class="icon-link" href="/admin/docs/sidecars">{{ icons.book() }}Sidecars</a> and <a class="icon-link" href="/admin/docs/libraries">{{ icons.book() }}Libraries</a> for the full contract. It's also a working example of self-hosted spam prevention (honeypot field + submission-timing check, no external CAPTCHA service) — see <a class="icon-link" href="/admin/docs/sidecars">{{ icons.book() }}Sidecars</a>' "Spam prevention" section.</p>
|
||||
|
||||
{% if sent %}
|
||||
<p><strong>Thanks — your message has been sent.</strong></p>
|
||||
{% endif %}
|
||||
|
||||
{% if securityError %}
|
||||
<p><strong>Your session expired before submitting — please try again.</strong></p>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/contact">
|
||||
<input type="hidden" name="{{ csrfField }}" value="{{ csrfToken }}">
|
||||
<div class="hp-field" aria-hidden="true">
|
||||
<label for="website">Leave this field blank</label>
|
||||
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off">
|
||||
</div>
|
||||
<input type="hidden" name="rendered_at" value="{{ renderedAt }}">
|
||||
<p>
|
||||
<label for="name">Name</label><br>
|
||||
<input type="text" id="name" name="name" value="{{ old.name }}">
|
||||
{% if errors.name %}<br><small>{{ errors.name }}</small>{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
<label for="email">Email</label><br>
|
||||
<input type="text" id="email" name="email" value="{{ old.email }}">
|
||||
{% if errors.email %}<br><small>{{ errors.email }}</small>{% endif %}
|
||||
</p>
|
||||
<p>
|
||||
<label for="message">Message</label><br>
|
||||
<textarea id="message" name="message" rows="5">{{ old.message }}</textarea>
|
||||
{% if errors.message %}<br><small>{{ errors.message }}</small>{% endif %}
|
||||
</p>
|
||||
<button type="submit">Send</button>
|
||||
</form>
|
||||
</article>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user