12/28/25 V.18
This commit is contained in:
parent
7f34b50ab8
commit
f87d8bee23
106
apply.php
Normal file
106
apply.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/db/config.php';
|
||||||
|
require_once __DIR__ . '/mail/MailService.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
$response = ['success' => false, 'message' => 'An unknown error occurred.'];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
$response['message'] = 'Invalid request method.';
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
|
|
||||||
|
if (empty($data)) {
|
||||||
|
$response['message'] = 'No data received.';
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanitize and validate data
|
||||||
|
$companyName = htmlspecialchars($data['companyName'] ?? '');
|
||||||
|
$yourName = htmlspecialchars($data['yourName'] ?? '');
|
||||||
|
$workEmail = filter_var($data['workEmail'] ?? '', FILTER_SANITIZE_EMAIL);
|
||||||
|
$role = htmlspecialchars($data['role'] ?? '');
|
||||||
|
$employees = filter_var($data['employees'] ?? '', FILTER_SANITIZE_NUMBER_INT);
|
||||||
|
$rolesPerMonth = filter_var($data['rolesPerMonth'] ?? '', FILTER_SANITIZE_NUMBER_INT);
|
||||||
|
$candidatesPerRole = filter_var($data['candidatesPerRole'] ?? '', FILTER_SANITIZE_NUMBER_INT);
|
||||||
|
$ats = htmlspecialchars($data['ats'] ?? '');
|
||||||
|
$scheduling = htmlspecialchars($data['scheduling'] ?? '');
|
||||||
|
$painPoints = htmlspecialchars($data['painPoints'] ?? '');
|
||||||
|
$successMetrics = htmlspecialchars($data['successMetrics'] ?? '');
|
||||||
|
$hiringFocus = htmlspecialchars($data['hiringFocus'] ?? '');
|
||||||
|
|
||||||
|
if (!filter_var($workEmail, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
$response['message'] = 'Invalid email address.';
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($companyName) || empty($yourName)) {
|
||||||
|
$response['message'] = 'Please fill out all required fields.';
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert into database
|
||||||
|
$pdo = db();
|
||||||
|
$stmt = $pdo->prepare("
|
||||||
|
INSERT INTO applications (name, company, email, role, employees, roles_per_month, candidates_per_role, ats, scheduling, pain_points, success_metrics, hiring_focus)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
");
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute([
|
||||||
|
$yourName,
|
||||||
|
$companyName,
|
||||||
|
$workEmail,
|
||||||
|
$role,
|
||||||
|
$employees,
|
||||||
|
$rolesPerMonth,
|
||||||
|
$candidatesPerRole,
|
||||||
|
$ats,
|
||||||
|
$scheduling,
|
||||||
|
$painPoints,
|
||||||
|
$successMetrics,
|
||||||
|
$hiringFocus
|
||||||
|
]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
error_log('Database Error: ' . $e->getMessage());
|
||||||
|
$response['message'] = 'There was an error saving your application. Please try again later.';
|
||||||
|
echo json_encode($response);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$to = getenv('MAIL_TO') ?: 'default-recipient@example.com'; // Fallback recipient
|
||||||
|
$subject = 'New FinMox Beta Application';
|
||||||
|
|
||||||
|
$htmlBody = ""
|
||||||
|
. "<h1>New FinMox Beta Application</h1>"
|
||||||
|
. "<p><strong>Company Name:</strong> {$companyName}</p>"
|
||||||
|
. "<p><strong>Name:</strong> {$yourName}</p>"
|
||||||
|
. "<p><strong>Email:</strong> {$workEmail}</p>"
|
||||||
|
. "<p><strong>Role:</strong> {$role}</p>"
|
||||||
|
. "<p><strong>Employees:</strong> {$employees}</p>"
|
||||||
|
. "<p><strong>Roles Per Month:</strong> {$rolesPerMonth}</p>"
|
||||||
|
. "<p><strong>Candidates Per Role:</strong> {$candidatesPerRole}</p>"
|
||||||
|
. "<p><strong>ATS:</strong> {$ats}</p>"
|
||||||
|
. "<p><strong>Scheduling:</strong> {$scheduling}</p>"
|
||||||
|
. "<p><strong>Pain Points:</strong> {$painPoints}</p>"
|
||||||
|
. "<p><strong>Success Metrics:</strong> {$successMetrics}</p>"
|
||||||
|
. "<p><strong>Hiring Focus:</strong> {$hiringFocus}</p>";
|
||||||
|
|
||||||
|
$res = MailService::sendMail($to, $subject, $htmlBody);
|
||||||
|
|
||||||
|
if (!empty($res['success'])) {
|
||||||
|
$response['success'] = true;
|
||||||
|
$response['message'] = 'Application submitted successfully!';
|
||||||
|
} else {
|
||||||
|
error_log('MailService Error: ' . ($res['error'] ?? 'Unknown error'));
|
||||||
|
$response['message'] = 'There was an error submitting your application. Please try again later.';
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($response);
|
||||||
@ -118,4 +118,116 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const applyNowBtn = document.getElementById('applyNowBtn');
|
||||||
|
if (applyNowBtn) {
|
||||||
|
applyNowBtn.addEventListener('click', applyForBeta);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function signIn(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
const emailEl = document.getElementById('signinEmail');
|
||||||
|
const passwordEl = document.getElementById('signinPassword');
|
||||||
|
const msgEl = document.getElementById('signinMsg');
|
||||||
|
|
||||||
|
if (!emailEl || !passwordEl || !msgEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const email = emailEl.value.trim();
|
||||||
|
const password = passwordEl.value.trim();
|
||||||
|
|
||||||
|
msgEl.classList.add('hidden');
|
||||||
|
msgEl.textContent = '';
|
||||||
|
|
||||||
|
if (!email || !password) {
|
||||||
|
msgEl.textContent = 'Please enter both email and password.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch('login.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify({ email, password }),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
window.location.href = 'dashboard.php';
|
||||||
|
} else {
|
||||||
|
msgEl.textContent = data.message || 'An unknown error occurred.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
msgEl.textContent = 'A network error occurred. Please try again.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyForBeta(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const form = document.getElementById('applyForm');
|
||||||
|
const msgEl = document.getElementById('applyMsg');
|
||||||
|
|
||||||
|
if (!form || !msgEl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
companyName: document.getElementById('companyName').value,
|
||||||
|
yourName: document.getElementById('yourName').value,
|
||||||
|
workEmail: document.getElementById('workEmail').value,
|
||||||
|
role: document.getElementById('role').value,
|
||||||
|
employees: document.getElementById('employees').value,
|
||||||
|
rolesPerMonth: document.getElementById('rolesPerMonth').value,
|
||||||
|
candidatesPerRole: document.getElementById('candidatesPerRole').value,
|
||||||
|
ats: document.getElementById('ats').value,
|
||||||
|
scheduling: document.getElementById('scheduling').value,
|
||||||
|
painPoints: document.getElementById('painPoints').value,
|
||||||
|
successMetrics: document.getElementById('successMetrics').value,
|
||||||
|
hiringFocus: document.getElementById('hiringFocus').value,
|
||||||
|
};
|
||||||
|
|
||||||
|
msgEl.classList.add('hidden');
|
||||||
|
msgEl.textContent = '';
|
||||||
|
|
||||||
|
// Basic validation
|
||||||
|
if (!data.workEmail || !data.companyName || !data.yourName) {
|
||||||
|
msgEl.textContent = 'Please fill out all required fields.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch('apply.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(result => {
|
||||||
|
if (result.success) {
|
||||||
|
msgEl.textContent = 'Thank you for your application! We will be in touch shortly.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
msgEl.classList.remove('text-red-600');
|
||||||
|
msgEl.classList.add('text-green-600');
|
||||||
|
form.reset();
|
||||||
|
} else {
|
||||||
|
msgEl.textContent = result.message || 'An unknown error occurred.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
msgEl.textContent = 'A network error occurred. Please try again.';
|
||||||
|
msgEl.classList.remove('hidden');
|
||||||
|
});
|
||||||
|
}
|
||||||
BIN
assets/pasted-20251228-074747-5baef672.png
Normal file
BIN
assets/pasted-20251228-074747-5baef672.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
7
check_auth.php
Normal file
7
check_auth.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
if (!isset($_SESSION['user'])) {
|
||||||
|
header('Location: index.php#signin');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
2
dashboard.php
Normal file
2
dashboard.php
Normal file
File diff suppressed because one or more lines are too long
31
db/migrate.php
Normal file
31
db/migrate.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
require_once __DIR__ . '/config.php';
|
||||||
|
|
||||||
|
function run_migrations() {
|
||||||
|
$pdo = db();
|
||||||
|
$pdo->exec("CREATE TABLE IF NOT EXISTS `migrations` ( `id` INT AUTO_INCREMENT PRIMARY KEY, `migration` VARCHAR(255) NOT NULL, `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP );");
|
||||||
|
|
||||||
|
$ran_migrations = $pdo->query("SELECT migration FROM migrations")->fetchAll(PDO::FETCH_COLUMN);
|
||||||
|
|
||||||
|
$migration_files = glob(__DIR__ . '/migrations/*.sql');
|
||||||
|
sort($migration_files);
|
||||||
|
|
||||||
|
foreach ($migration_files as $file) {
|
||||||
|
$migration_name = basename($file);
|
||||||
|
|
||||||
|
if (!in_array($migration_name, $ran_migrations)) {
|
||||||
|
$sql = file_get_contents($file);
|
||||||
|
$pdo->exec($sql);
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
|
||||||
|
$stmt->execute([$migration_name]);
|
||||||
|
|
||||||
|
echo "Migration run: " . $migration_name . "\n";
|
||||||
|
} else {
|
||||||
|
echo "Migration already run: " . $migration_name . "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
run_migrations();
|
||||||
|
|
||||||
5
db/migrations/00_create_migrations_table.sql
Normal file
5
db/migrations/00_create_migrations_table.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS `migrations` (
|
||||||
|
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
`migration` VARCHAR(255) NOT NULL,
|
||||||
|
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
9
db/migrations/02_alter_applications_table.sql
Normal file
9
db/migrations/02_alter_applications_table.sql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
ALTER TABLE `applications`
|
||||||
|
ADD COLUMN `employees` INT NULL,
|
||||||
|
ADD COLUMN `roles_per_month` INT NULL,
|
||||||
|
ADD COLUMN `candidates_per_role` INT NULL,
|
||||||
|
ADD COLUMN `ats` VARCHAR(255) NULL,
|
||||||
|
ADD COLUMN `scheduling` VARCHAR(255) NULL,
|
||||||
|
ADD COLUMN `pain_points` TEXT NULL,
|
||||||
|
ADD COLUMN `success_metrics` TEXT NULL,
|
||||||
|
ADD COLUMN `hiring_focus` VARCHAR(255) NULL;
|
||||||
39
index.php
39
index.php
@ -1,3 +1,4 @@
|
|||||||
|
<?php session_start(); ?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@ -635,7 +636,14 @@
|
|||||||
<section class="max-w-7xl mx-auto px-6 py-24 text-center"> <h2 class="text-3xl font-semibold mb-4"> Still have questions? </h2> <p class="text-gray-600 mb-8"> We’d rather answer them directly than hide behind marketing. </p> <div class="flex justify-center gap-4"> <a href="/apply.php" class="bg-black text-white px-8 py-4 rounded-xl"> Apply for access </a> <a href="/trust.php" class="border px-8 py-4 rounded-xl"> Security & Trust → </a> </div> </section>
|
<section class="max-w-7xl mx-auto px-6 py-24 text-center"> <h2 class="text-3xl font-semibold mb-4"> Still have questions? </h2> <p class="text-gray-600 mb-8"> We’d rather answer them directly than hide behind marketing. </p> <div class="flex justify-center gap-4"> <a href="/apply.php" class="bg-black text-white px-8 py-4 rounded-xl"> Apply for access </a> <a href="/trust.php" class="border px-8 py-4 rounded-xl"> Security & Trust → </a> </div> </section>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- SIGNIN PAGE (PART 1/2) --> <section id="page-signin" class="page fade hidden"> <section class="panel-strong p-8 lg:p-10"> <div class="grid lg:grid-cols-12 gap-10 items-start"> <!-- Left: Trust / context --> <div class="lg:col-span-5"> <div class="chip inline-flex px-3 py-1 text-xs">Account</div> <h1 class="mt-5 text-4xl font-extrabold tracking-tight"> Sign in to FinMox </h1> <p class="mt-5 text-gray-700"> Access your workspace to review hiring execution, decision trails, and audit-ready outputs. </p> <div class="mt-7 panel p-6"> <div class="text-sm font-semibold">What you can do inside</div> <ul class="mt-3 text-sm text-gray-700 space-y-2"> <li>✔ Review ranked candidates + structured scoring</li> <li>✔ See interview summaries + recommendations</li> <li>✔ Track movement + SLA nudges</li> <li>✔ Export decision logs for audits</li> </ul> <div class="mt-4 flex flex-wrap gap-2"> <span class="chip px-3 py-1 text-xs">Role-based access</span> <span class="chip px-3 py-1 text-xs">Least privilege</span> <span class="chip px-3 py-1 text-xs">Audit trail</span> </div> </div> <div class="mt-7 panel p-6"> <div class="text-sm font-semibold">Need access?</div> <p class="mt-2 text-sm text-gray-700"> FinMox is onboarding teams through private beta. Apply and we’ll confirm fit. </p> <div class="mt-4 flex flex-wrap gap-3"> <a href="#apply" onclick="openPage('apply'); return false;" class="bg-black text-white px-6 py-3 rounded-2xl text-sm hoverlift"> Apply for Access </a> <a href="#trust" onclick="openPage('trust'); return false;" class="chip px-6 py-3 rounded-2xl text-sm hoverlift"> Security & Trust → </a> </div> </div> </div><!-- SIGNIN PAGE (PART 2/2) --> <!-- Right: Sign in card --> <div class="lg:col-span-7"> <div class="panel p-7"> <div class="flex items-center justify-between gap-4"> <div> <div class="text-sm font-semibold">Welcome back</div> <div class="text-sm text-gray-600 mt-1">Sign in to continue.</div> </div> <span class="chip px-3 py-1 text-xs">Private beta</span> </div> <form class="mt-6 grid gap-3" onsubmit="return false;"> <div class="grid md:grid-cols-2 gap-3"> <input type="email" placeholder="Work email" class="panel-strong px-4 py-3 rounded-2xl" autocomplete="email" /> <input type="password" placeholder="Password" class="panel-strong px-4 py-3 rounded-2xl" autocomplete="current-password" /> </div> <div class="flex items-center justify-between gap-4 text-sm"> <label class="flex items-center gap-2 text-gray-700"> <input type="checkbox" class="accent-black" /> Remember me </label> <a href="#forgot" onclick="openPage('forgot'); return false;" class="underline text-sm text-gray-700"> Forgot access? </a> </div> <button type="button" class="bg-black text-white py-3 rounded-2xl hoverlift" > Sign In </button> <div class="text-xs text-gray-600"> Demo placeholder. Wire this to your auth later (AppWizzy auth, Supabase, Clerk, etc.). </div> </form> <div class="mt-6 grid md:grid-cols-3 gap-3"> <div class="panel-strong p-5"> <div class="text-xs text-gray-500">Access control</div> <div class="mt-2 text-sm text-gray-700">Role-based permissions supported.</div> </div> <div class="panel-strong p-5"> <div class="text-xs text-gray-500">Session security</div> <div class="mt-2 text-sm text-gray-700">Least-privilege by default.</div> </div> <div class="panel-strong p-5"> <div class="text-xs text-gray-500">Auditability</div> <div class="mt-2 text-sm text-gray-700">Actions map to decision trail.</div> </div> </div> <div class="mt-6 panel-strong p-6"> <div class="text-sm font-semibold">New here?</div> <div class="mt-2 text-sm text-gray-700"> Apply for beta access and we’ll onboard your team with a short process.</div></div></div></div></section></section>
|
<!-- SIGNIN PAGE (PART 1/2) --> <section id="page-signin" class="page fade hidden"> <section class="panel-strong p-8 lg:p-10"> <div class="grid lg:grid-cols-12 gap-10 items-start"> <!-- Left: Trust / context --> <div class="lg:col-span-5"> <div class="chip inline-flex px-3 py-1 text-xs">Account</div> <h1 class="mt-5 text-4xl font-extrabold tracking-tight"> Sign in to FinMox </h1> <p class="mt-5 text-gray-700"> Access your workspace to review hiring execution, decision trails, and audit-ready outputs. </p> <div class="mt-7 panel p-6"> <div class="text-sm font-semibold">What you can do inside</div> <ul class="mt-3 text-sm text-gray-700 space-y-2"> <li>✔ Review ranked candidates + structured scoring</li> <li>✔ See interview summaries + recommendations</li> <li>✔ Track movement + SLA nudges</li> <li>✔ Export decision logs for audits</li> </ul> <div class="mt-4 flex flex-wrap gap-2"> <span class="chip px-3 py-1 text-xs">Role-based access</span> <span class="chip px-3 py-1 text-xs">Least privilege</span> <span class="chip px-3 py-1 text-xs">Audit trail</span> </div> </div> <div class="mt-7 panel p-6"> <div class="text-sm font-semibold">Need access?</div> <p class="mt-2 text-sm text-gray-700"> FinMox is onboarding teams through private beta. Apply and we’ll confirm fit. </p> <div class="mt-4 flex flex-wrap gap-3"> <a href="#apply" onclick="openPage('apply'); return false;" class="bg-black text-white px-6 py-3 rounded-2xl text-sm hoverlift"> Apply for Access </a> <a href="#trust" onclick="openPage('trust'); return false;" class="chip px-6 py-3 rounded-2xl text-sm hoverlift"> Security & Trust → </a> </div> </div> </div><!-- SIGNIN PAGE (PART 2/2) --> <!-- Right: Sign in card --> <div class="lg:col-span-7"> <div class="panel p-7"> <div class="flex items-center justify-between gap-4"> <div> <div class="text-sm font-semibold">Welcome back</div> <div class="text-sm text-gray-600 mt-1">Sign in to continue.</div> </div> <span class="chip px-3 py-1 text-xs">Private beta</span> </div> <form class="mt-6 grid gap-3">
|
||||||
|
<input type="email" id="signinEmail" placeholder="Work email" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
|
<input type="password" id="signinPassword" placeholder="Password" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
|
<button type="button" onclick="signIn(event)" class="bg-black text-white py-3 rounded-2xl hoverlift">
|
||||||
|
Sign in
|
||||||
|
</button>
|
||||||
|
<div id="signinMsg" class="hidden text-sm text-red-600"></div>
|
||||||
|
</form> <div class="mt-6 grid md:grid-cols-3 gap-3"> <div class="panel-strong p-5"> <div class="text-xs text-gray-500">Access control</div> <div class="mt-2 text-sm text-gray-700">Role-based permissions supported.</div> </div> <div class="panel-strong p-5"> <div class="text-xs text-gray-500">Session security</div> <div class="mt-2 text-sm text-gray-700">Least-privilege by default.</div> </div> <div class="panel-strong p-5"> <div class="text-xs text-gray-500">Auditability</div> <div class="mt-2 text-sm text-gray-700">Actions map to decision trail.</div> </div> </div> <div class="mt-6 panel-strong p-6"> <div class="text-sm font-semibold">New here?</div> <div class="mt-2 text-sm text-gray-700"> Apply for beta access and we’ll onboard your team with a short process.</div></div></div></div></section></section>
|
||||||
|
|
||||||
<!-- APPLY PAGE (PART 1/3) -->
|
<!-- APPLY PAGE (PART 1/3) -->
|
||||||
<section id="page-apply" class="page fade hidden">
|
<section id="page-apply" class="page fade hidden">
|
||||||
@ -692,35 +700,36 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="chip px-3 py-1 text-xs">Pilot-first</span>
|
<span class="chip px-3 py-1 text-xs">Pilot-first</span>
|
||||||
</div>
|
</div>
|
||||||
<form class="mt-6 grid gap-3" onsubmit="return false;">
|
<form id="applyForm" class="mt-6 grid gap-3" onsubmit="return false;">
|
||||||
<div class="grid md:grid-cols-2 gap-3">
|
<div class="grid md:grid-cols-2 gap-3">
|
||||||
<input type="text" placeholder="Company name" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="companyName" type="text" placeholder="Company name" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
<input type="text" placeholder="Your name" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="yourName" type="text" placeholder="Your name" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid md:grid-cols-2 gap-3">
|
<div class="grid md:grid-cols-2 gap-3">
|
||||||
<input type="email" placeholder="Work email" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="workEmail" type="email" placeholder="Work email" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
<input type="text" placeholder="Role / title" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="role" type="text" placeholder="Role / title" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid md:grid-cols-3 gap-3">
|
<div class="grid md:grid-cols-3 gap-3">
|
||||||
<input type="number" placeholder="Employees" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="employees" type="number" placeholder="Employees" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
<input type="number" placeholder="Roles per month" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="rolesPerMonth" type="number" placeholder="Roles per month" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
<input type="number" placeholder="Candidates per role" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="candidatesPerRole" type="number" placeholder="Candidates per role" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
</div>
|
</div>
|
||||||
<div class="grid md:grid-cols-2 gap-3">
|
<div class="grid md:grid-cols-2 gap-3">
|
||||||
<input type="text" placeholder="ATS (Greenhouse, Lever, etc.)" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="ats" type="text" placeholder="ATS (Greenhouse, Lever, etc.)" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
<input type="text" placeholder="Scheduling (Calendly, Google, etc.)" class="panel-strong px-4 py-3 rounded-2xl" />
|
<input id="scheduling" type="text" placeholder="Scheduling (Calendly, Google, etc.)" class="panel-strong px-4 py-3 rounded-2xl" />
|
||||||
</div>
|
</div>
|
||||||
<textarea rows="4" placeholder="Where does hiring execution break today? (drift, delays, inconsistency, documentation)" class="panel-strong px-4 py-3 rounded-2xl"></textarea>
|
<textarea id="painPoints" rows="4" placeholder="Where does hiring execution break today? (drift, delays, inconsistency, documentation)" class="panel-strong px-4 py-3 rounded-2xl"></textarea>
|
||||||
<textarea rows="3" placeholder="What does success look like in 30 days? (faster decisions, less chasing, audit trail, etc.)" class="panel-strong px-4 py-3 rounded-2xl"></textarea>
|
<textarea id="successMetrics" rows="3" placeholder="What does success look like in 30 days? (faster decisions, less chasing, audit trail, etc.)" class="panel-strong px-4 py-3 rounded-2xl"></textarea>
|
||||||
|
<div id="applyMsg" class="hidden text-sm text-red-600"></div>
|
||||||
<div class="grid md:grid-cols-2 gap-3">
|
<div class="grid md:grid-cols-2 gap-3">
|
||||||
<select class="panel-strong px-4 py-3 rounded-2xl">
|
<select id="hiringFocus" class="panel-strong px-4 py-3 rounded-2xl">
|
||||||
<option>Primary hiring focus</option>
|
<option>Primary hiring focus</option>
|
||||||
<option>Engineering</option>
|
<option>Engineering</option>
|
||||||
<option>Sales</option>
|
<option>Sales</option>
|
||||||
<option>Marketing</option>
|
<option>Marketing</option>
|
||||||
<option>Other</option>
|
<option>Other</option>
|
||||||
</select>
|
</select>
|
||||||
<button type="button" class="bg-black text-white py-3 rounded-2xl hoverlift" > Apply Now </button>
|
<button type="button" id="applyNowBtn" class="bg-black text-white py-3 rounded-2xl hoverlift" > Apply Now </button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
29
login.php
Normal file
29
login.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
session_start();
|
||||||
|
|
||||||
|
// Hardcoded credentials for demonstration.
|
||||||
|
// In a real application, you should fetch user from a database and verify the password hash.
|
||||||
|
$valid_email = 'test@example.com';
|
||||||
|
$valid_password = 'password';
|
||||||
|
|
||||||
|
$response = ['success' => false, 'message' => ''];
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
$data = json_decode(file_get_contents('php://input'), true);
|
||||||
|
$email = $data['email'] ?? null;
|
||||||
|
$password = $data['password'] ?? null;
|
||||||
|
|
||||||
|
if (empty($email) || empty($password)) {
|
||||||
|
$response['message'] = 'Please enter both email and password.';
|
||||||
|
} elseif ($email === $valid_email && $password === $valid_password) {
|
||||||
|
$_SESSION['user'] = ['email' => $email];
|
||||||
|
$response['success'] = true;
|
||||||
|
} else {
|
||||||
|
$response['message'] = 'Invalid credentials.';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$response['message'] = 'Invalid request method.';
|
||||||
|
}
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
echo json_encode($response);
|
||||||
Loading…
x
Reference in New Issue
Block a user