chg: dev: refactor all forms to have Symfony Form Types & Validation Constrainsts - & implement Google ReCapthca v3 #4
This commit is contained in:
@@ -4,7 +4,6 @@
|
||||
|
||||
{% block body %}
|
||||
<div class="auth-page">
|
||||
|
||||
{% for email in app.flashes('reset_sent') %}
|
||||
<div class="auth-card auth-card--sent">
|
||||
<div class="auth-sent-icon"><i class="fa fa-envelope-o"></i></div>
|
||||
@@ -21,40 +20,62 @@
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Forgot Password</h2>
|
||||
<p class="auth-sub">Enter your email and we'll send you a reset link</p>
|
||||
|
||||
<form class="auth-form" method="post" action="{{ path('MineSeekerBundle_forgot_password') }}">
|
||||
{{ form_start(form, {attr: {class: 'auth-form'}}) }}
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="email" class="auth-label">Email</label>
|
||||
<label for="{{ form.email.vars.id }}" class="auth-label">Email</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-envelope auth-input-icon"></i>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="_email"
|
||||
class="auth-input"
|
||||
autocomplete="email"
|
||||
autofocus
|
||||
required
|
||||
/>
|
||||
{{ form_widget(form.email, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.email.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'email',
|
||||
autofocus: true,
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
{% if not form.email.vars.valid %}
|
||||
{% for error in form.email.vars.errors %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ error.message }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-paper-plane"></i> Send Reset Link
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{{ form_end(form) }}
|
||||
|
||||
<p class="auth-switch">
|
||||
Remembered it?
|
||||
<a href="{{ path('MineSeekerBundle_login') }}">Sign in</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script src="https://www.google.com/recaptcha/api.js?render={{ recaptcha_site_key }}" async defer></script>
|
||||
<script>
|
||||
(function () {
|
||||
const form = document.querySelector('.auth-form');
|
||||
if (!form) return;
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
grecaptcha.ready(function () {
|
||||
grecaptcha.execute('{{ recaptcha_site_key }}', {action: 'forgot_password'}).then(function (token) {
|
||||
document.getElementById('{{ form.recaptcha.vars.id }}').value = token;
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
<span>Remember me</span>
|
||||
</label>
|
||||
|
||||
<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response"/>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-sign-in"></i> Sign In
|
||||
</button>
|
||||
@@ -85,3 +87,20 @@
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script src="https://www.google.com/recaptcha/api.js?render={{ recaptcha_site_key }}" async defer></script>
|
||||
<script>
|
||||
document.querySelector('.auth-form').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const form = this;
|
||||
grecaptcha.ready(function () {
|
||||
grecaptcha.execute('{{ recaptcha_site_key }}', {action: 'login'}).then(function (token) {
|
||||
document.getElementById('g-recaptcha-response').value = token;
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,108 +3,106 @@
|
||||
{% block title %} - Profile{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="profile-page">
|
||||
|
||||
<div class="profile-header">
|
||||
<div class="profile-avatar">
|
||||
{{ app.user.username|slice(0, 2)|upper }}
|
||||
</div>
|
||||
<div class="profile-info">
|
||||
<h1 class="profile-name">{{ app.user.username }}</h1>
|
||||
{% if app.user.email %}
|
||||
<p class="profile-email">
|
||||
<i class="fa fa-envelope"></i>
|
||||
{{ app.user.email }}
|
||||
</p>
|
||||
{% endif %}
|
||||
<p class="profile-role">
|
||||
<i class="fa fa-shield"></i> Registered commander
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="profile-stats">
|
||||
<div class="profile-stat">
|
||||
<i class="fa fa-gamepad profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.total }}</span>
|
||||
<span class="profile-stat__label">Games played</span>
|
||||
</div>
|
||||
<div class="profile-stat profile-stat--win">
|
||||
<i class="fa fa-trophy profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.wins }}</span>
|
||||
<span class="profile-stat__label">Victories</span>
|
||||
</div>
|
||||
<div class="profile-stat profile-stat--loss">
|
||||
<i class="fa fa-flag profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.losses }}</span>
|
||||
<span class="profile-stat__label">Defeats</span>
|
||||
</div>
|
||||
<div class="profile-stat profile-stat--bomb">
|
||||
<i class="fa fa-bomb profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.bombs }}</span>
|
||||
<span class="profile-stat__label">Mines hit</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if recent|length > 0 %}
|
||||
<div class="profile-section">
|
||||
<h2 class="profile-section__title">
|
||||
<i class="fa fa-history"></i> Recent battles
|
||||
</h2>
|
||||
<div class="profile-games">
|
||||
{% for game in recent %}
|
||||
{% set is_red = game.red and game.red.id == app.user.id %}
|
||||
{% set my_points = is_red ? game.redPoints : game.bluePoints %}
|
||||
{% set opp_points = is_red ? game.bluePoints : game.redPoints %}
|
||||
{% set opp = is_red ? game.blue : game.red %}
|
||||
{% set opp_anon = is_red ? game.blueAnon : game.redAnon %}
|
||||
|
||||
{% set result = 'draw' %}
|
||||
{% if game.resign == (is_red ? 'red' : 'blue') %}
|
||||
{% set result = 'loss' %}
|
||||
{% elseif game.resign == (is_red ? 'blue' : 'red') %}
|
||||
{% set result = 'win' %}
|
||||
{% elseif my_points is not null and opp_points is not null %}
|
||||
{% if my_points > opp_points %}
|
||||
{% set result = 'win' %}
|
||||
{% elseif my_points < opp_points %}
|
||||
{% set result = 'loss' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div class="profile-game profile-game--{{ result }}">
|
||||
<span class="profile-game__badge">
|
||||
{{ result == 'win' ? 'W' : (result == 'loss' ? 'L' : 'D') }}
|
||||
</span>
|
||||
<span class="profile-game__score">
|
||||
{{ my_points ?? '—' }} : {{ opp_points ?? '—' }}
|
||||
</span>
|
||||
<span class="profile-game__vs">vs</span>
|
||||
<span class="profile-game__opponent">
|
||||
{% if opp %}
|
||||
{{ opp.username }}
|
||||
{% elseif opp_anon %}
|
||||
{{ opp_anon.userName }}
|
||||
{% else %}
|
||||
Guest
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="profile-game__color">
|
||||
<i class="fa fa-circle" style="color: {{ is_red ? '#c0392b' : '#2980b9' }}"></i>
|
||||
</span>
|
||||
<span class="profile-game__date">
|
||||
{{ game.updated ? game.updated|date('Y-m-d') : '' }}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="profile-empty">
|
||||
<i class="fa fa-inbox"></i>
|
||||
<p>No games recorded yet. <a href="{{ path('MineSeekerBundle_gamePlay') }}">Start playing!</a></p>
|
||||
</div>
|
||||
<div class="profile-page">
|
||||
<div class="profile-header">
|
||||
<div class="profile-avatar">
|
||||
{{ app.user.username|slice(0, 2)|upper }}
|
||||
</div>
|
||||
<div class="profile-info">
|
||||
<h1 class="profile-name">{{ app.user.username }}</h1>
|
||||
{% if app.user.email %}
|
||||
<p class="profile-email">
|
||||
<i class="fa fa-envelope"></i>
|
||||
{{ app.user.email }}
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p class="profile-role">
|
||||
<i class="fa fa-shield"></i> Registered commander
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<div class="profile-stats">
|
||||
<div class="profile-stat">
|
||||
<i class="fa fa-gamepad profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.total }}</span>
|
||||
<span class="profile-stat__label">Games played</span>
|
||||
</div>
|
||||
<div class="profile-stat profile-stat--win">
|
||||
<i class="fa fa-trophy profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.wins }}</span>
|
||||
<span class="profile-stat__label">Victories</span>
|
||||
</div>
|
||||
<div class="profile-stat profile-stat--loss">
|
||||
<i class="fa fa-flag profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.losses }}</span>
|
||||
<span class="profile-stat__label">Defeats</span>
|
||||
</div>
|
||||
<div class="profile-stat profile-stat--bomb">
|
||||
<i class="fa fa-bomb profile-stat__icon"></i>
|
||||
<span class="profile-stat__value">{{ stats.bombs }}</span>
|
||||
<span class="profile-stat__label">Mines hit</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if recent|length > 0 %}
|
||||
<div class="profile-section">
|
||||
<h2 class="profile-section__title">
|
||||
<i class="fa fa-history"></i> Recent battles
|
||||
</h2>
|
||||
<div class="profile-games">
|
||||
{% for game in recent %}
|
||||
{% set is_red = game.red and game.red.id == app.user.id %}
|
||||
{% set my_points = is_red ? game.redPoints : game.bluePoints %}
|
||||
{% set opp_points = is_red ? game.bluePoints : game.redPoints %}
|
||||
{% set opp = is_red ? game.blue : game.red %}
|
||||
{% set opp_anon = is_red ? game.blueAnon : game.redAnon %}
|
||||
|
||||
{% set result = 'draw' %}
|
||||
{% if game.resign == (is_red ? 'red' : 'blue') %}
|
||||
{% set result = 'loss' %}
|
||||
{% elseif game.resign == (is_red ? 'blue' : 'red') %}
|
||||
{% set result = 'win' %}
|
||||
{% elseif my_points is not null and opp_points is not null %}
|
||||
{% if my_points > opp_points %}
|
||||
{% set result = 'win' %}
|
||||
{% elseif my_points < opp_points %}
|
||||
{% set result = 'loss' %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<div class="profile-game profile-game--{{ result }}">
|
||||
<span class="profile-game__badge">
|
||||
{{ result == 'win' ? 'W' : (result == 'loss' ? 'L' : 'D') }}
|
||||
</span>
|
||||
<span class="profile-game__score">
|
||||
{{ my_points ?? '—' }} : {{ opp_points ?? '—' }}
|
||||
</span>
|
||||
<span class="profile-game__vs">vs</span>
|
||||
<span class="profile-game__opponent">
|
||||
{% if opp %}
|
||||
{{ opp.username }}
|
||||
{% elseif opp_anon %}
|
||||
{{ opp_anon.userName }}
|
||||
{% else %}
|
||||
Guest
|
||||
{% endif %}
|
||||
</span>
|
||||
<span class="profile-game__color">
|
||||
<i class="fa fa-circle" style="color: {{ is_red ? '#c0392b' : '#2980b9' }}"></i>
|
||||
</span>
|
||||
<span class="profile-game__date">
|
||||
{{ game.updated ? game.updated|date('Y-m-d') : '' }}
|
||||
</span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="profile-empty">
|
||||
<i class="fa fa-inbox"></i>
|
||||
<p>No games recorded yet. <a href="{{ path('MineSeekerBundle_gamePlay') }}">Start playing!</a></p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -3,118 +3,133 @@
|
||||
{% block title %} - Register{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="auth-page">
|
||||
<div class="auth-page">
|
||||
{% for email in app.flashes('verify_email') %}
|
||||
<div class="auth-card auth-card--sent">
|
||||
<div class="auth-sent-icon"><i class="fa fa-envelope-o"></i></div>
|
||||
<h2 class="auth-title">Check your inbox</h2>
|
||||
<p class="auth-sub">We sent an activation link to</p>
|
||||
<p class="auth-sent-email">{{ email }}</p>
|
||||
<p class="auth-sent-note">
|
||||
Click the link in the email to activate your account.<br>
|
||||
The link expires in <strong>24 hours</strong>.
|
||||
</p>
|
||||
<a
|
||||
href="{{ path('MineSeekerBundle_login') }}"
|
||||
class="auth-submit"
|
||||
style="text-decoration:none; margin-top:16px;"
|
||||
>
|
||||
Go to Sign In
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Create Account</h2>
|
||||
<p class="auth-sub">Join the battle — no subscription required</p>
|
||||
|
||||
{% for email in app.flashes('verify_email') %}
|
||||
<div class="auth-card auth-card--sent">
|
||||
<div class="auth-sent-icon"><i class="fa fa-envelope-o"></i></div>
|
||||
<h2 class="auth-title">Check your inbox</h2>
|
||||
<p class="auth-sub">We sent an activation link to</p>
|
||||
<p class="auth-sent-email">{{ email }}</p>
|
||||
<p class="auth-sent-note">
|
||||
Click the link in the email to activate your account.<br>
|
||||
The link expires in <strong>24 hours</strong>.
|
||||
</p>
|
||||
<a href="{{ path('MineSeekerBundle_login') }}" class="auth-submit" style="text-decoration:none; margin-top:16px;">
|
||||
Go to Sign In
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ form_start(form, {attr: {class: 'auth-form'}}) }}
|
||||
|
||||
<div class="auth-card">
|
||||
<h2 class="auth-title">Create Account</h2>
|
||||
<p class="auth-sub">Join the battle — no subscription required</p>
|
||||
<div class="auth-field">
|
||||
<label for="{{ form.username.vars.id }}" class="auth-label">Username</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-user auth-input-icon"></i>
|
||||
{{ form_widget(form.username, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.username.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'username',
|
||||
autofocus: true,
|
||||
minlength: '3',
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
{% if not form.username.vars.valid %}
|
||||
{% for error in form.username.vars.errors %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ error.message }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<form class="auth-form" method="post" action="{{ path('MineSeekerBundle_register') }}">
|
||||
<div class="auth-field">
|
||||
<label for="{{ form.email.vars.id }}" class="auth-label">Email</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-envelope auth-input-icon"></i>
|
||||
{{ form_widget(form.email, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.email.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'email',
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
{% if not form.email.vars.valid %}
|
||||
{% for error in form.email.vars.errors %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ error.message }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="username" class="auth-label">Username</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-user auth-input-icon"></i>
|
||||
<input
|
||||
type="text"
|
||||
id="username"
|
||||
name="_username"
|
||||
class="auth-input{% if errors.username is defined %} auth-input--error{% endif %}"
|
||||
value="{{ last_username }}"
|
||||
autocomplete="username"
|
||||
autofocus
|
||||
required
|
||||
minlength="3"
|
||||
/>
|
||||
</div>
|
||||
{% if errors.username is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.username }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="auth-field">
|
||||
<label for="{{ form.plainPassword.first.vars.id }}" class="auth-label">Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
{{ form_widget(form.plainPassword.first, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.plainPassword.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'new-password',
|
||||
minlength: '6',
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
{% if not form.plainPassword.vars.valid %}
|
||||
{% for error in form.plainPassword.vars.errors %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ error.message }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="email" class="auth-label">Email</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-envelope auth-input-icon"></i>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="_email"
|
||||
class="auth-input{% if errors.email is defined %} auth-input--error{% endif %}"
|
||||
value="{{ last_email }}"
|
||||
autocomplete="email"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{% if errors.email is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.email }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="auth-field">
|
||||
<label for="{{ form.plainPassword.second.vars.id }}" class="auth-label">Confirm Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
{{ form_widget(form.plainPassword.second, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.plainPassword.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'new-password',
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password" class="auth-label">Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="_password"
|
||||
class="auth-input{% if errors.password is defined %} auth-input--error{% endif %}"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
minlength="6"
|
||||
/>
|
||||
</div>
|
||||
{% if errors.password is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.password }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-user-plus"></i> Create Account
|
||||
</button>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password_confirm" class="auth-label">Confirm Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password_confirm"
|
||||
name="_password_confirm"
|
||||
class="auth-input{% if errors.password_confirm is defined %} auth-input--error{% endif %}"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{% if errors.password_confirm is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.password_confirm }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-user-plus"></i> Create Account
|
||||
</button>
|
||||
</form>
|
||||
<p class="auth-switch">
|
||||
Already have an account?
|
||||
<a href="{{ path('MineSeekerBundle_login') }}">Sign in</a>
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
<p class="auth-switch">
|
||||
Already have an account?
|
||||
<a href="{{ path('MineSeekerBundle_login') }}">Sign in</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script src="https://www.google.com/recaptcha/api.js?render={{ recaptcha_site_key }}" async defer></script>
|
||||
<script>
|
||||
(function () {
|
||||
const form = document.querySelector('.auth-form');
|
||||
if (!form) return;
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
grecaptcha.ready(function () {
|
||||
grecaptcha.execute('{{ recaptcha_site_key }}', {action: 'register'}).then(function (token) {
|
||||
document.getElementById('{{ form.recaptcha.vars.id }}').value = token;
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
@@ -8,50 +8,65 @@
|
||||
<h2 class="auth-title">Reset Password</h2>
|
||||
<p class="auth-sub">Choose a new password for your account</p>
|
||||
|
||||
<form class="auth-form" method="post">
|
||||
{{ form_start(form, {attr: {class: 'auth-form'}}) }}
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password" class="auth-label">New Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="_password"
|
||||
class="auth-input{% if errors.password is defined %} auth-input--error{% endif %}"
|
||||
autocomplete="new-password"
|
||||
autofocus
|
||||
required
|
||||
minlength="6"
|
||||
/>
|
||||
</div>
|
||||
{% if errors.password is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.password }}</p>
|
||||
{% endif %}
|
||||
<div class="auth-field">
|
||||
<label for="{{ form.plainPassword.first.vars.id }}" class="auth-label">New Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
{{ form_widget(form.plainPassword.first, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.plainPassword.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'new-password',
|
||||
autofocus: true,
|
||||
minlength: '6',
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
{% if not form.plainPassword.vars.valid %}
|
||||
{% for error in form.plainPassword.vars.errors %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ error.message }}</p>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="auth-field">
|
||||
<label for="password_confirm" class="auth-label">Confirm New Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
<input
|
||||
type="password"
|
||||
id="password_confirm"
|
||||
name="_password_confirm"
|
||||
class="auth-input{% if errors.password_confirm is defined %} auth-input--error{% endif %}"
|
||||
autocomplete="new-password"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{% if errors.password_confirm is defined %}
|
||||
<p class="auth-field-error"><i class="fa fa-exclamation-circle"></i> {{ errors.password_confirm }}</p>
|
||||
{% endif %}
|
||||
<div class="auth-field">
|
||||
<label for="{{ form.plainPassword.second.vars.id }}" class="auth-label">Confirm New Password</label>
|
||||
<div class="auth-input-wrap">
|
||||
<i class="fa fa-lock auth-input-icon"></i>
|
||||
{{ form_widget(form.plainPassword.second, {
|
||||
attr: {
|
||||
class: 'auth-input' ~ (not form.plainPassword.vars.valid ? ' auth-input--error' : ''),
|
||||
autocomplete: 'new-password',
|
||||
}
|
||||
}) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-key"></i> Set New Password
|
||||
</button>
|
||||
</form>
|
||||
<button type="submit" class="auth-submit">
|
||||
<i class="fa fa-key"></i> Set New Password
|
||||
</button>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascripts %}
|
||||
{{ parent() }}
|
||||
<script src="https://www.google.com/recaptcha/api.js?render={{ recaptcha_site_key }}" async defer></script>
|
||||
<script>
|
||||
(function () {
|
||||
document.querySelector('.auth-form').addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
const form = this;
|
||||
grecaptcha.ready(function () {
|
||||
grecaptcha.execute('{{ recaptcha_site_key }}', {action: 'reset_password'}).then(function (token) {
|
||||
document.getElementById('{{ form.recaptcha.vars.id }}').value = token;
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
});
|
||||
}());
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user