<?php
declare(strict_types=1);
require_once 'includes/config.php';
require_once 'includes/functions.php';
init_storage();
session_start_safe();
// Redirect if already logged in
if (get_session_user()) {
redirect('dashboard.php');
}
$error_login = $error_reg = '';
$captcha_q = '';
/* ── Handle login ─────────────────────────────────────────────── */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['form'] ?? '') === 'login') {
if (!verify_csrf()) {
$error_login = 'Invalid request. Please try again.';
} else {
$username = trim($_POST['username'] ?? '');
$password = $_POST['password'] ?? '';
$result = authenticate($username, $password);
if (is_array($result)) {
login_user($result);
redirect('dashboard.php');
} else {
$error_login = $result;
}
}
}
/* ── Handle registration ──────────────────────────────────────── */
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['form'] ?? '') === 'register') {
if (!verify_csrf()) {
$error_reg = 'Invalid request. Please try again.';
} else {
$username = strtolower(trim($_POST['username'] ?? ''));
$display_name = trim($_POST['display_name'] ?? '');
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
$password2 = $_POST['password2'] ?? '';
if (!verify_captcha($_POST['captcha_answer'] ?? '')) {
$error_reg = 'Incorrect math answer. Please try again.';
} elseif ($password !== $password2) {
$error_reg = 'Passwords do not match';
} else {
$result = create_user($username, $password, $display_name, $email);
if ($result === true) {
$user = authenticate($username, $password);
login_user($user);
flash('success', 'Welcome to TaskGram, ' . $display_name .'! Your account is ready.');
redirect('dashboard.php');
} else {
$error_reg = $result;
}
}
}
}
// Always generate a fresh captcha for the registration form
$captcha_q = set_captcha();
$page_title = 'Sign In';
require_once 'includes/header.php';
?>
<div class="page-wrap" style="max-width:760px; padding-top:20px;">
<div style="text-align:center; margin-bottom:16px;">
<div style="font-size:28px; font-weight:bold; color:#FFFFFF; text-shadow:2px 2px 0 #004040;">
<?= APP_NAME ?>
</div>
<div style="font-size:13px; color:#C0FFFF;">Task list manager</div>
</div>
<div style="display:flex; gap:10px; flex-wrap:wrap; align-items:flex-start;">
<!-- ── Sign In ────────────────────────────────────── -->
<div class="window" style="flex:1; min-width:280px;">
<div class="window-title">
<span>Sign In</span>
</div>
<div class="window-body">
<?php if ($error_login): ?>
<div class="flash flash-error" style="margin:0 0 8px 0;"><?= h($error_login) ?></div>
<?php endif; ?>
<form method="post" action="index.php">
<?= csrf_field() ?>
<input type="hidden" name="form" value="login">
<div class="form-row">
<label for="login_username">Username</label>
<input type="text" id="login_username" name="username"
value="<?= h($_POST['username'] ?? '') ?>"
autocomplete="username" maxlength="32" required>
</div>
<div class="form-row">
<label for="login_password">Password</label>
<input type="password" id="login_password" name="password"
autocomplete="current-password" maxlength="128" required>
</div>
<div class="form-row" style="margin-top:10px;">
<button type="submit" class="btn btn-primary" style="width:100%;">Sign In</button>
</div>
</form>
</div>
</div>
<!-- ── Register ───────────────────────────────────── -->
<div class="window" style="flex:1; min-width:280px;">
<div class="window-title">
<span>Create Account</span>
</div>
<div class="window-body">
<?php if ($error_reg): ?>
<div class="flash flash-error" style="margin:0 0 8px 0;"><?= h($error_reg) ?></div>
<?php endif; ?>
<form method="post" action="index.php">
<?= csrf_field() ?>
<input type="hidden" name="form" value="register">
<div class="form-row">
<label for="reg_username">Username <span style="font-weight:normal;font-size:11px;">(3-32 chars, a-z 0-9 _ -)</span></label>
<input type="text" id="reg_username" name="username"
value="<?= h($_POST['username'] ?? '') ?>"
pattern="[a-z][a-z0-9_-]{2,31}" autocomplete="username"
maxlength="32" required>
</div>
<div class="form-row">
<label for="reg_display">Display Name</label>
<input type="text" id="reg_display" name="display_name"
value="<?= h($_POST['display_name'] ?? '') ?>"
maxlength="64">
</div>
<div class="form-row">
<label for="reg_email">Email <span style="font-weight:normal;font-size:11px;">(optional)</span></label>
<input type="email" id="reg_email" name="email"
value="<?= h($_POST['email'] ?? '') ?>"
autocomplete="email" maxlength="128">
</div>
<div class="form-row">
<label for="reg_password">Password <span style="font-weight:normal;font-size:11px;">(min <?= MIN_PASSWORD_LEN ?> chars)</span></label>
<input type="password" id="reg_password" name="password"
autocomplete="new-password" minlength="<?= MIN_PASSWORD_LEN ?>" maxlength="128" required>
</div>
<div class="form-row">
<label for="reg_password2">Confirm Password</label>
<input type="password" id="reg_password2" name="password2"
autocomplete="new-password" maxlength="128" required>
</div>
<div class="form-row">
<label for="reg_captcha">What is <?= h($captcha_q) ?>?
<span style="font-weight:normal;font-size:11px;">(anti-bot check)</span>
</label>
<input type="text" id="reg_captcha" name="captcha_answer"
maxlength="8" required autocomplete="off"
placeholder="Enter the answer">
</div>
<div class="form-row" style="margin-top:10px;">
<button type="submit" class="btn btn-primary" style="width:100%;">Create Account</button>
</div>
</form>
</div>
</div>
</div><!-- /flex -->
</div>
<?php require_once 'includes/footer.php'; ?>