159 lines
6.5 KiB
HTML
159 lines
6.5 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Create your workspace — JQC</title>
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
|
<style>
|
|
body { background: #f6f7f9; }
|
|
.signup-card { max-width: 520px; margin: 2.5rem auto; }
|
|
.brand { font-weight: 700; color: #1a56db; font-size: 1.1rem; }
|
|
.subdomain-preview { font-size: .8rem; color: #6b7280; margin-top: .25rem; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="signup-card px-3">
|
|
<div class="text-center mb-4 mt-4">
|
|
<div class="brand mb-1"><i class="bi bi-check2-circle me-1"></i>Janitorial QC</div>
|
|
<h1 class="h4 mb-0">Create your workspace</h1>
|
|
<p class="text-muted" style="font-size:.9rem;">14-day free trial · No credit card required</p>
|
|
</div>
|
|
|
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
{% for cat, msg in messages %}
|
|
<div class="alert alert-{{ 'danger' if cat == 'danger' else cat }} alert-dismissible fade show" role="alert">
|
|
{{ msg }}
|
|
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
|
</div>
|
|
{% endfor %}
|
|
{% endwith %}
|
|
|
|
<div class="card border-0 shadow-sm">
|
|
<div class="card-body p-4">
|
|
<form method="post" novalidate>
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Company Name</label>
|
|
<input type="text" name="company_name" id="company_name"
|
|
class="form-control {{ 'is-invalid' if form.company_name.errors }}"
|
|
value="{{ form.company_name.data or '' }}"
|
|
placeholder="Acme Cleaning Co." autofocus>
|
|
{% for e in form.company_name.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Your Full Name</label>
|
|
<input type="text" name="full_name"
|
|
class="form-control {{ 'is-invalid' if form.full_name.errors }}"
|
|
value="{{ form.full_name.data or '' }}"
|
|
placeholder="Jane Smith">
|
|
{% for e in form.full_name.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Work Email</label>
|
|
<input type="email" name="email"
|
|
class="form-control {{ 'is-invalid' if form.email.errors }}"
|
|
value="{{ form.email.data or '' }}"
|
|
placeholder="you@company.com">
|
|
{% for e in form.email.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Subdomain</label>
|
|
<div class="input-group">
|
|
<input type="text" name="subdomain" id="subdomain"
|
|
class="form-control {{ 'is-invalid' if form.subdomain.errors }}"
|
|
value="{{ form.subdomain.data or '' }}"
|
|
placeholder="acme"
|
|
pattern="[a-z0-9][a-z0-9\-]{0,30}[a-z0-9]"
|
|
style="text-transform:lowercase;">
|
|
<span class="input-group-text text-muted" style="font-size:.85rem;">.{{ base_domain }}</span>
|
|
{% for e in form.subdomain.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
<div class="subdomain-preview" id="subdomain_preview"></div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Plan</label>
|
|
<select name="plan" class="form-select {{ 'is-invalid' if form.plan.errors }}">
|
|
{% for value, label in form.plan.choices %}
|
|
<option value="{{ value }}" {{ 'selected' if form.plan.data == value }}>{{ label }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
{% for e in form.plan.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Password</label>
|
|
<input type="password" name="password"
|
|
class="form-control {{ 'is-invalid' if form.password.errors }}"
|
|
placeholder="Minimum 8 characters">
|
|
{% for e in form.password.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<div class="mb-4">
|
|
<label class="form-label fw-semibold" style="font-size:.875rem;">Confirm Password</label>
|
|
<input type="password" name="confirm"
|
|
class="form-control {{ 'is-invalid' if form.confirm.errors }}">
|
|
{% for e in form.confirm.errors %}
|
|
<div class="invalid-feedback">{{ e }}</div>
|
|
{% endfor %}
|
|
</div>
|
|
|
|
<button type="submit" class="btn btn-primary w-100">
|
|
<i class="bi bi-rocket-takeoff me-1"></i> Create Workspace
|
|
</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<p class="text-center text-muted mt-3" style="font-size:.82rem;">
|
|
Already have a workspace?
|
|
<a href="https://{{ base_domain }}">Sign in</a>
|
|
</p>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script>
|
|
// Auto-suggest subdomain from company name
|
|
var BASE_DOMAIN = {{ base_domain | tojson }};
|
|
document.getElementById('company_name').addEventListener('input', function () {
|
|
var sub = document.getElementById('subdomain');
|
|
if (sub.dataset.userEdited) return;
|
|
var slug = this.value.toLowerCase()
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '')
|
|
.slice(0, 32);
|
|
sub.value = slug;
|
|
updatePreview(slug);
|
|
});
|
|
document.getElementById('subdomain').addEventListener('input', function () {
|
|
this.dataset.userEdited = '1';
|
|
this.value = this.value.toLowerCase().replace(/[^a-z0-9-]/g, '');
|
|
updatePreview(this.value);
|
|
});
|
|
function updatePreview(slug) {
|
|
var el = document.getElementById('subdomain_preview');
|
|
el.textContent = slug ? 'Your workspace: ' + slug + '.' + BASE_DOMAIN : '';
|
|
}
|
|
updatePreview(document.getElementById('subdomain').value);
|
|
</script>
|
|
</body>
|
|
</html>
|