diff --git a/create-job.php b/create-job.php new file mode 100644 index 0000000..3c6661b --- /dev/null +++ b/create-job.php @@ -0,0 +1,132 @@ +prepare("SELECT id, name FROM clients WHERE company_id = ? AND is_active = 1 ORDER BY name ASC"); +$stmt->execute([$companyId]); +$clients = $stmt->fetchAll(); + +// Fetch statuses for selection +$stmt = db()->prepare("SELECT id, name, is_default FROM job_statuses WHERE company_id = ? ORDER BY sort_order ASC"); +$stmt->execute([$companyId]); +$statuses = $stmt->fetchAll(); + +// Fetch company settings +$stmt = db()->prepare("SELECT uprn_required FROM companies WHERE id = ?"); +$stmt->execute([$companyId]); +$company = $stmt->fetch(); + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $clientId = $_POST['client_id'] ?? ''; + $statusId = $_POST['status_id'] ?? ''; + $uprn = $_POST['uprn'] ?? ''; + $address = $_POST['address'] ?? ''; + $description = $_POST['description'] ?? ''; + + if (empty($clientId) || empty($statusId) || empty($address)) { + $error = 'Please fill in all required fields.'; + } elseif ($company['uprn_required'] && empty($uprn)) { + $error = 'UPRN is required for this company.'; + } else { + try { + db()->beginTransaction(); + + // 1. Insert Job + $stmt = db()->prepare(" + INSERT INTO jobs (company_id, client_id, status_id, uprn, address, description) + VALUES (?, ?, ?, ?, ?, ?) + "); + $stmt->execute([$companyId, $clientId, $statusId, $uprn, $address, $description]); + $jobId = db()->lastInsertId(); + + // 2. Add Mandatory Folders + $stmt = db()->prepare("SELECT name FROM required_folders WHERE company_id = ?"); + $stmt->execute([$companyId]); + $reqFolders = $stmt->fetchAll(); + + $folderStmt = db()->prepare("INSERT INTO job_folders (job_id, name, is_required) VALUES (?, ?, ?)"); + foreach ($reqFolders as $rf) { + $folderStmt->execute([$jobId, $rf['name'], 1]); + } + + // 3. Log activity + $logStmt = db()->prepare("INSERT INTO job_logs (job_id, user_id, action, details) VALUES (?, ?, ?, ?)"); + $logStmt->execute([$jobId, $user['id'], 'created', 'Job created manually by user.']); + + db()->commit(); + header('Location: dashboard.php'); + exit; + } catch (Exception $e) { + db()->rollBack(); + $error = "Database error: " . $e->getMessage(); + } + } +} + +$pageTitle = "Create New Job"; +require_once __DIR__ . '/includes/header.php'; +?> + +
+
+
+
+

Create New Job

+
+
+ +
+ + +
+
+
+ + +
+
+ + +
+
+ + > +
+
+ + +
+
+ + +
+
+ +
+ Cancel + +
+
+
+
+
+
+ + diff --git a/dashboard.php b/dashboard.php new file mode 100644 index 0000000..e096e46 --- /dev/null +++ b/dashboard.php @@ -0,0 +1,82 @@ +prepare(" + SELECT j.*, c.name as client_name, s.name as status_name + FROM jobs j + JOIN clients c ON j.client_id = c.id + JOIN job_statuses s ON j.status_id = s.id + WHERE j.company_id = ? + ORDER BY j.created_at DESC +"); +$stmt->execute([$companyId]); +$jobs = $stmt->fetchAll(); + +require_once __DIR__ . '/includes/header.php'; +?> + +
+

Jobs Overview

+ + Create New Job + +
+ + +
+
+ +
+

No jobs found

+

Get started by creating your first repair job.

+
+ Create First Job +
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Job IDClientAddressStatusUPRNCreatedActions
# + + + View Details +
+
+
+ + + diff --git a/db/init.sql b/db/init.sql index 50405f2..cf71c7b 100644 --- a/db/init.sql +++ b/db/init.sql @@ -56,4 +56,58 @@ CREATE TABLE IF NOT EXISTS clients ( updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE, UNIQUE KEY (company_id, name) -- Ensure client names are unique per company -); \ No newline at end of file +); + +-- Jobs Table: Core entity for the application. +CREATE TABLE IF NOT EXISTS jobs ( + id INT AUTO_INCREMENT PRIMARY KEY, + company_id INT NOT NULL, + client_id INT NOT NULL, + status_id INT NOT NULL, + uprn VARCHAR(255) DEFAULT NULL, -- Unique Property Reference Number + address TEXT NOT NULL, + description TEXT, + works_approved BOOLEAN DEFAULT FALSE, + is_completed BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE, + FOREIGN KEY (client_id) REFERENCES clients(id), + FOREIGN KEY (status_id) REFERENCES job_statuses(id) +); + +-- Job Folders Table: Mandatory and custom folders for each job. +CREATE TABLE IF NOT EXISTS job_folders ( + id INT AUTO_INCREMENT PRIMARY KEY, + job_id INT NOT NULL, + name VARCHAR(255) NOT NULL, + is_required BOOLEAN DEFAULT FALSE, -- If true, it's a company-wide mandatory folder. + is_completed BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE +); + +-- Job Files Table: Files uploaded to job folders. +CREATE TABLE IF NOT EXISTS job_files ( + id INT AUTO_INCREMENT PRIMARY KEY, + folder_id INT NOT NULL, + user_id INT NOT NULL, + filename VARCHAR(255) NOT NULL, + file_path VARCHAR(255) NOT NULL, + file_size INT NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (folder_id) REFERENCES job_folders(id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users(id) +); + +-- Job Logs Table: Server-side logging for all job activities. +CREATE TABLE IF NOT EXISTS job_logs ( + id INT AUTO_INCREMENT PRIMARY KEY, + job_id INT NOT NULL, + user_id INT NOT NULL, + action VARCHAR(255) NOT NULL, -- e.g., 'created', 'status_updated', 'file_uploaded' + details TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users(id) +); diff --git a/includes/auth.php b/includes/auth.php new file mode 100644 index 0000000..e8b9360 --- /dev/null +++ b/includes/auth.php @@ -0,0 +1,35 @@ +prepare("SELECT u.*, c.name as company_name FROM users u JOIN companies c ON u.company_id = c.id WHERE u.id = ?"); + $stmt->execute([$_SESSION['user_id']]); + $user = $stmt->fetch(); + } + return $user; +} + +function logout(): void { + session_destroy(); + header('Location: login.php'); + exit; +} diff --git a/includes/footer.php b/includes/footer.php new file mode 100644 index 0000000..05471db --- /dev/null +++ b/includes/footer.php @@ -0,0 +1,8 @@ + + + + + + diff --git a/includes/header.php b/includes/header.php new file mode 100644 index 0000000..ba1aa8e --- /dev/null +++ b/includes/header.php @@ -0,0 +1,40 @@ + + + + + + + <?= $pageTitle ?? 'RepairsPro' ?> + + + + + + + +
diff --git a/index.php b/index.php index cac0d41..73511db 100644 --- a/index.php +++ b/index.php @@ -1,6 +1,7 @@ query("SELECT COUNT(*) FROM companies"); @@ -11,52 +12,65 @@ if ($companyCount == 0) { exit; } -$pageTitle = "Repairs Multi-Tenant App"; +if (isLoggedIn()) { + header('Location: dashboard.php'); + exit; +} + +$pageTitle = "RepairsPro - Multi-Tenant Management"; ?> - <?= $pageTitle ?> - Landing + <?= $pageTitle ?> + -