192 lines
7.9 KiB
PHP
192 lines
7.9 KiB
PHP
<?= $this->extend('layout/careers_layout') ?>
|
|
<?= $this->section('styles') ?>
|
|
<style>
|
|
body {
|
|
background-color: var(--sage);
|
|
}
|
|
|
|
.job-apply-page {
|
|
max-width: 920px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.job-apply-page h1 {
|
|
font-family: "Inter", sans-serif;
|
|
font-size: 2rem;
|
|
font-weight: 600;
|
|
line-height: 1.25;
|
|
margin-bottom: 2rem;
|
|
text-align: left;
|
|
}
|
|
|
|
.job-apply-page .form-label {
|
|
font-family: "Heebo", sans-serif;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.job-apply-page .btn-primary {
|
|
background-color: #198754;
|
|
border-color: #198754;
|
|
color: #fff;
|
|
}
|
|
|
|
.job-apply-page .btn-primary:hover {
|
|
background-color: #146c43;
|
|
border-color: #146c43;
|
|
color: #fff;
|
|
}
|
|
|
|
.job-apply-page .field-error {
|
|
min-height: 1.25rem;
|
|
}
|
|
</style>
|
|
<?= $this->endSection() ?>
|
|
|
|
<?= $this->section('content') ?>
|
|
|
|
<div class="container py-5">
|
|
<a href="<?= site_url('careers/' . $position['position_id']) ?>" class="btn btn-outline-secondary btn-sm mb-4">Back to position</a>
|
|
<div class="row justify-content-center">
|
|
<div class="col-lg-8 job-apply-page">
|
|
<h1>Apply: <?= esc($position['title']) ?></h1>
|
|
<?php if (session('error')): ?><div class="alert alert-danger"><?= esc(session('error')) ?></div><?php endif; ?>
|
|
<?php if (session('errors')): ?>
|
|
<div class="alert alert-danger">
|
|
<?php foreach ((array) session('errors') as $error): ?>
|
|
<div><?= esc($error) ?></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
<p class="text-secondary mb-3">(All fields with * are required)</p>
|
|
<form action="<?= site_url('careers/' . $position['position_id'] . '/apply') ?>" method="post" enctype="multipart/form-data" class="mt-4">
|
|
<?= csrf_field() ?>
|
|
<div class="row g-3">
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="first_name">First Name*</label>
|
|
<input id="first_name" name="first_name" class="form-control" maxlength="30" pattern="[A-Za-z\s-]{2,30}" placeholder="First Name*" title="2-30 characters. Letters, spaces, and dashes only." value="<?= esc(old('first_name')) ?>" required>
|
|
<div class="form-text text-muted">2-30 characters. Letters, spaces, and dashes only.</div>
|
|
<div id="first_name-error" class="text-danger small field-error"></div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="last_name">Last Name*</label>
|
|
<input id="last_name" name="last_name" class="form-control" maxlength="30" pattern="[A-Za-z\s-]{2,30}" placeholder="Last Name*" title="2-30 characters. Letters, spaces, and dashes only." value="<?= esc(old('last_name')) ?>" required>
|
|
<div class="form-text text-muted">2-30 characters. Letters, spaces, and dashes only.</div>
|
|
<div id="last_name-error" class="text-danger small field-error"></div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="email">Email*</label>
|
|
<input id="email" type="email" name="email" class="form-control" maxlength="50" placeholder="Email*" value="<?= esc(old('email')) ?>" required>
|
|
<div class="form-text text-muted">Valid email format, maximum 50 characters.</div>
|
|
<div id="email-error" class="text-danger small field-error"></div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label class="form-label" for="phone">Phone*</label>
|
|
<input id="phone" type="tel" name="phone" class="form-control" minlength="10" maxlength="20" inputmode="tel" pattern="[\d\s\-\(\)\.]+" placeholder="Phone*" title="Enter a valid 10-digit phone number, for example 123-456-7890" value="<?= esc(old('phone')) ?>" required>
|
|
<div class="form-text text-muted">Enter a 10-digit phone number, for example 123-456-7890.</div>
|
|
<div id="phone-error" class="text-danger small field-error"></div>
|
|
</div>
|
|
<div class="col-12">
|
|
<label class="form-label" for="resume">Resume*</label>
|
|
<input id="resume" type="file" name="resume" class="form-control" accept=".pdf,.doc,.docx" required>
|
|
<div class="form-text">PDF, DOC, or DOCX. Maximum size 5 MB.</div>
|
|
</div>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary mt-4">Submit Application</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const form = document.querySelector('.job-apply-page form');
|
|
const fields = {
|
|
first_name: {
|
|
element: document.getElementById('first_name'),
|
|
validate: value => /^[A-Za-z\s-]{2,30}$/.test(value),
|
|
message: 'First name must be 2-30 characters and use only letters, spaces, and dashes.'
|
|
},
|
|
last_name: {
|
|
element: document.getElementById('last_name'),
|
|
validate: value => /^[A-Za-z\s-]{2,30}$/.test(value),
|
|
message: 'Last name must be 2-30 characters and use only letters, spaces, and dashes.'
|
|
},
|
|
email: {
|
|
element: document.getElementById('email'),
|
|
validate: value => value.length <= 50 && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
|
|
message: 'Please enter a valid email address, maximum 50 characters.'
|
|
},
|
|
phone: {
|
|
element: document.getElementById('phone'),
|
|
validate: value => value.replace(/\D/g, '').length === 10,
|
|
message: 'Please enter a valid 10-digit phone number.'
|
|
}
|
|
};
|
|
|
|
function setFieldState(input, valid, message) {
|
|
const error = document.getElementById(input.id + '-error');
|
|
const hasValue = input.value.trim() !== '';
|
|
|
|
input.classList.toggle('is-valid', valid && hasValue);
|
|
input.classList.toggle('is-invalid', !valid && hasValue);
|
|
|
|
if (error) {
|
|
error.textContent = !valid && hasValue ? message : '';
|
|
}
|
|
}
|
|
|
|
function formatPhone(input) {
|
|
const digits = input.value.replace(/\D/g, '').slice(0, 10);
|
|
let formatted = digits;
|
|
if (digits.length > 3) {
|
|
formatted = digits.slice(0, 3) + '-' + digits.slice(3);
|
|
}
|
|
if (digits.length > 6) {
|
|
formatted = digits.slice(0, 3) + '-' + digits.slice(3, 6) + '-' + digits.slice(6);
|
|
}
|
|
input.value = formatted;
|
|
}
|
|
|
|
function validateField(name) {
|
|
const config = fields[name];
|
|
if (!config || !config.element) {
|
|
return true;
|
|
}
|
|
|
|
if (name === 'phone') {
|
|
formatPhone(config.element);
|
|
}
|
|
|
|
const value = config.element.value.trim();
|
|
const valid = config.validate(value);
|
|
setFieldState(config.element, valid, config.message);
|
|
return valid;
|
|
}
|
|
|
|
Object.keys(fields).forEach(name => {
|
|
const input = fields[name].element;
|
|
if (!input) {
|
|
return;
|
|
}
|
|
|
|
input.addEventListener('input', () => validateField(name));
|
|
input.addEventListener('blur', () => validateField(name));
|
|
});
|
|
|
|
if (form) {
|
|
form.addEventListener('submit', function (event) {
|
|
const ok = Object.keys(fields).every(validateField);
|
|
if (!ok) {
|
|
event.preventDefault();
|
|
const firstInvalid = form.querySelector('.is-invalid');
|
|
if (firstInvalid) {
|
|
firstInvalid.focus();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<?= $this->endSection() ?>
|