diff --git a/all_requests.php b/all_requests.php new file mode 100644 index 0000000..9f542c9 --- /dev/null +++ b/all_requests.php @@ -0,0 +1,77 @@ +prepare('SELECT cr.*, u.username as requester_name FROM change_requests cr JOIN users u ON cr.requester_id = u.id ORDER BY cr.created_at DESC'); + $stmt->execute(); + $requests = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + $requests = []; + error_log("Database error: " . $e->getMessage()); +} + +?> + + + + + + <?= htmlspecialchars($pageTitle) ?> + + + + + + +
+

All Submitted Requests

+
+ +
No requests have been submitted yet.
+ + + + + + + + + + + + + + + + + + + + + + + + +
IDChange TitleRequesterStatusSubmitted OnActions
+ View +
+ +
+ + + + + + diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..69852e2 --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,39 @@ +body { + background-color: #f8f9fa; +} + +.form-container { + max-width: 900px; + margin: 2rem auto; + padding: 2rem; + background-color: #fff; + border-radius: 0.5rem; + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075); +} + +.form-section { + margin-bottom: 2rem; +} + +.section-title { + font-size: 1.5rem; + margin-bottom: 1rem; + border-bottom: 2px solid #0d6efd; + padding-bottom: 0.5rem; +} + +.approval-history-table th, +.approval-history-table td { + vertical-align: middle; + text-align: center; +} + +.stamp-cell { + height: 80px; + width: 80px; + border: 1px solid #dee2e6; + vertical-align: middle; + text-align: center; + font-size: 0.8rem; + color: #6c757d; +} diff --git a/auth.php b/auth.php new file mode 100644 index 0000000..70d4083 --- /dev/null +++ b/auth.php @@ -0,0 +1,47 @@ +prepare("SELECT * FROM users WHERE username = :username"); + $stmt->execute([':username' => $username]); + $user = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($user && password_verify($password, $user['password'])) { + // Password is correct, start session + session_regenerate_id(); // Prevents session fixation + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + $_SESSION['full_name'] = $user['full_name']; + $_SESSION['department'] = $user['department']; + + header("Location: index.php"); + exit(); + } else { + $_SESSION['error_message'] = 'Invalid username or password.'; + header("Location: login.php"); + exit(); + } +} catch (PDOException $e) { + // In a real app, you'd log this error + // error_log("Login error: " . $e->getMessage()); + $_SESSION['error_message'] = 'A database error occurred. Please try again later.'; + header('Location: login.php'); + exit(); +} diff --git a/auth_check.php b/auth_check.php new file mode 100644 index 0000000..b6b62fa --- /dev/null +++ b/auth_check.php @@ -0,0 +1,10 @@ +exec($sql); + echo "Applied successfully.\n"; + } + + echo "All migrations applied.\n"; + +} catch (PDOException $e) { + die("Database error: " . $e->getMessage()); +} + diff --git a/db/migrations/001_create_change_requests_table.sql b/db/migrations/001_create_change_requests_table.sql new file mode 100644 index 0000000..13d3691 --- /dev/null +++ b/db/migrations/001_create_change_requests_table.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS `change_requests` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `request_date` DATE, + `requester_dept` VARCHAR(255), + `requester_name` VARCHAR(255), + `requester_ext` VARCHAR(50), + `related_request_no` VARCHAR(255), + `system_name` VARCHAR(255), + `program_name` VARCHAR(255), + `change_category` VARCHAR(50), + `reason_for_change` TEXT, + `description_of_change` TEXT, + `status` VARCHAR(50) DEFAULT 'draft', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/db/migrations/002_create_users_table.sql b/db/migrations/002_create_users_table.sql new file mode 100644 index 0000000..79db964 --- /dev/null +++ b/db/migrations/002_create_users_table.sql @@ -0,0 +1,11 @@ +-- 002_create_users_table.sql +CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + full_name VARCHAR(100), + department VARCHAR(100), + position VARCHAR(100), + role ENUM('requester', 'approver', 'admin') NOT NULL DEFAULT 'requester', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); diff --git a/db/migrations/003_add_requester_id_to_change_requests.sql b/db/migrations/003_add_requester_id_to_change_requests.sql new file mode 100644 index 0000000..1440fcf --- /dev/null +++ b/db/migrations/003_add_requester_id_to_change_requests.sql @@ -0,0 +1,7 @@ +-- 003_add_requester_id_to_change_requests.sql +ALTER TABLE change_requests +ADD COLUMN requester_id INT NULL, +ADD CONSTRAINT fk_requester_id + FOREIGN KEY (requester_id) + REFERENCES users(id) + ON DELETE SET NULL; diff --git a/db/migrations/004_update_change_requests_table.sql b/db/migrations/004_update_change_requests_table.sql new file mode 100644 index 0000000..4e58534 --- /dev/null +++ b/db/migrations/004_update_change_requests_table.sql @@ -0,0 +1,8 @@ +-- Add change_title and admin_comment columns +ALTER TABLE `change_requests` +ADD COLUMN `change_title` VARCHAR(255) NOT NULL AFTER `program_name`, +ADD COLUMN `admin_comment` TEXT AFTER `description_of_change`; + +-- Modify status column +ALTER TABLE `change_requests` +MODIFY COLUMN `status` ENUM('Pending', 'Approved', 'In Development', 'Completed', 'Rejected') NOT NULL DEFAULT 'Pending'; diff --git a/db/seed_users.php b/db/seed_users.php new file mode 100644 index 0000000..fc6e0c2 --- /dev/null +++ b/db/seed_users.php @@ -0,0 +1,49 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Default users + $users = [ + [ + 'username' => 'admin', + 'password' => password_hash('admin_password', PASSWORD_DEFAULT), + 'full_name' => 'Admin User', + 'department' => 'RSS SA', + 'position' => 'System Administrator', + 'role' => 'admin' + ], + [ + 'username' => 'requester', + 'password' => password_hash('requester_password', PASSWORD_DEFAULT), + 'full_name' => 'Regular User', + 'department' => 'RSS JP Sales', + 'position' => 'Sales Rep', + 'role' => 'requester' + ] + ]; + + $stmt = $pdo->prepare( + "INSERT INTO users (username, password, full_name, department, position, role) + VALUES (:username, :password, :full_name, :department, :position, :role) + ON DUPLICATE KEY UPDATE password=VALUES(password), full_name=VALUES(full_name), role=VALUES(role);" + ); + + foreach ($users as $user) { + $stmt->execute([ + ':username' => $user['username'], + ':password' => $user['password'], + ':full_name' => $user['full_name'], + ':department' => $user['department'], + ':position' => $user['position'], + ':role' => $user['role'] + ]); + echo "User '{$user['username']}' seeded successfully.\n"; + } + +} catch (PDOException $e) { + die("Error seeding users: " . $e->getMessage()); +} + diff --git a/header.php b/header.php new file mode 100644 index 0000000..cade30b --- /dev/null +++ b/header.php @@ -0,0 +1,51 @@ + + diff --git a/includes/helpers.php b/includes/helpers.php new file mode 100644 index 0000000..a54c519 --- /dev/null +++ b/includes/helpers.php @@ -0,0 +1,22 @@ +' . htmlspecialchars(ucfirst($status)) . ''; +} diff --git a/index.php b/index.php index 7205f3d..710839b 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,33 @@ - + - - - New Style - - - - - - - - - - - - - - - - - - - + + + <?= htmlspecialchars($pageTitle) ?> + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

+ + +
+
+
+

Dashboard

+

Welcome to your Approval Workflow Application.

+ Create New Request + View My Requests +
+
-
- + + + + + diff --git a/login.php b/login.php new file mode 100644 index 0000000..06f5e9b --- /dev/null +++ b/login.php @@ -0,0 +1,66 @@ + + + + + + + Login + + + + + +
+
+
+
+
+

Login

+ + + + + +
+
+ + +
+
+ + +
+
+ +
+
+
+ +
+
+
+
+ + + + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..08badaa --- /dev/null +++ b/logout.php @@ -0,0 +1,21 @@ +prepare('SELECT * FROM change_requests WHERE requester_id = :requester_id ORDER BY created_at DESC'); + $stmt->bindParam(':requester_id', $userId, PDO::PARAM_INT); + $stmt->execute(); + $requests = $stmt->fetchAll(PDO::FETCH_ASSOC); +} catch (PDOException $e) { + // Handle DB error + $requests = []; + error_log("Database error: " . $e->getMessage()); +} + +?> + + + + + + <?= htmlspecialchars($pageTitle) ?> + + + + + + +
+

My Submitted Requests

+
+ +
You have not submitted any requests yet.
+ + + + + + + + + + + + + + + + + + + + +
IDChange TitleStatusSubmitted On
+ + Submit New Request +
+ + + + + + diff --git a/request_form.php b/request_form.php index 86bc7b4..96f87ac 100644 --- a/request_form.php +++ b/request_form.php @@ -6,6 +6,27 @@ $username = $_SESSION['username'] ?? 'User'; $full_name = $_SESSION['full_name'] ?? ''; $department = $_SESSION['department'] ?? ''; +// Autogenerate Related Change Request No. +require_once __DIR__ . '/db/config.php'; +$pdo = db(); + +$year = date('Y'); +$month = date('m'); + +$prefix = "$department/$year/$month/"; + +$stmt = $pdo->prepare("SELECT related_request_no FROM change_requests WHERE related_request_no LIKE ? ORDER BY related_request_no DESC LIMIT 1"); +$stmt->execute([$prefix . '%']); +$lastRequest = $stmt->fetch(); + +$running_no = 1; +if ($lastRequest) { + $last_no = (int)substr($lastRequest['related_request_no'], strlen($prefix)); + $running_no = $last_no + 1; +} + +$related_request_no = $prefix . str_pad($running_no, 3, '0', STR_PAD_LEFT); + ?> @@ -55,30 +76,17 @@ $department = $_SESSION['department'] ?? '';
- +
- +
- +
diff --git a/search.php b/search.php new file mode 100644 index 0000000..e9ba76a --- /dev/null +++ b/search.php @@ -0,0 +1,87 @@ +prepare("SELECT cr.*, u.username as requester_name FROM change_requests cr JOIN users u ON cr.requester_id = u.id WHERE cr.program_name LIKE :term OR cr.system_name LIKE :term ORDER BY cr.created_at DESC"); + $stmt->bindValue(':term', '%' . $searchTerm . '%', PDO::PARAM_STR); + $stmt->execute(); + $results = $stmt->fetchAll(PDO::FETCH_ASSOC); + } catch (PDOException $e) { + $results = []; + error_log("Database error: " . $e->getMessage()); + } +} +?> + + + + + + <?= htmlspecialchars($pageTitle) ?> + + + + + + +
+

Search Change Requests

+
+
+
+ +
+ +
+
+
+ + +

Results for ""

+ +
No requests found matching your search term.
+ + + + + + + + + + + + + + + + + + + + + + + + +
IDChange TitleRequesterStatusSubmitted OnActions
+ View +
+ + +
+ + + + + + diff --git a/submit_request.php b/submit_request.php new file mode 100644 index 0000000..2c16fa1 --- /dev/null +++ b/submit_request.php @@ -0,0 +1,72 @@ +prepare($sql); + + $stmt->bindValue(':requester_id', $requester_id, PDO::PARAM_INT); + $stmt->bindValue(':request_date', !empty($_POST['request_date']) ? $_POST['request_date'] : null); + $stmt->bindValue(':requester_dept', $_POST['requester_dept'] ?? null); + $stmt->bindValue(':requester_name', $_POST['requester_name'] ?? null); + $stmt->bindValue(':requester_ext', $_POST['requester_ext'] ?? null); + $stmt->bindValue(':related_request_no', $_POST['related_request_no'] ?? null); + $stmt->bindValue(':system_name', $_POST['system_name'] ?? null); + $stmt->bindValue(':program_name', $_POST['program_name'] ?? null); + $stmt->bindValue(':change_title', $_POST['change_title'] ?? null); + $stmt->bindValue(':change_category', $_POST['change_category'] ?? null); + $stmt->bindValue(':reason_for_change', $_POST['reason_for_change'] ?? null); + $stmt->bindValue(':description_of_change', $_POST['description_of_change'] ?? null); + $stmt->bindValue(':status', $status); + + $stmt->execute(); + + $_SESSION['success_message'] = "Request submitted successfully with status: $status."; + +} catch (PDOException $e) { + $_SESSION['error_message'] = "Error submitting request: " . $e->getMessage(); +} + +header('Location: request_form.php'); +exit; diff --git a/update_request_status.php b/update_request_status.php new file mode 100644 index 0000000..b030390 --- /dev/null +++ b/update_request_status.php @@ -0,0 +1,92 @@ +prepare("SELECT cr.status, cr.change_title FROM change_requests cr WHERE cr.id = :id"); + $stmt->bindParam(':id', $requestId, PDO::PARAM_INT); + $stmt->execute(); + $request = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$request) { + $_SESSION['error_message'] = "Request not found."; + header('Location: all_requests.php'); + exit; + } + + // Update the request status and/or comment + $sql = "UPDATE change_requests SET status = :status, admin_comment = :comment WHERE id = :id"; + $stmt = $pdoconn->prepare($sql); + $stmt->bindParam(':status', $newStatus, PDO::PARAM_STR); + $stmt->bindParam(':comment', $adminComment, PDO::PARAM_STR); + $stmt->bindParam(':id', $requestId, PDO::PARAM_INT); + $stmt->execute(); + + if ($stmt->rowCount() > 0) { + $_SESSION['success_message'] = "Request status updated successfully."; + + // Send email notification if the status has changed + if ($request['status'] !== $newStatus) { + // NOTE: Email sending is disabled because requester email is not available in the users table. + /* + $to = $request['requester_email']; // This column does not exist + $subject = "Update on your Change Request #{$requestId}"; + $body = "

The status of your change request '{$request['change_title']}' has been updated to " . htmlspecialchars(ucfirst($newStatus)) . ".

"; + if (!empty($adminComment)) { + $body .= "

Admin Comment: " . htmlspecialchars($adminComment) . "

"; + } + $body .= "

You can view the request here: View Request

"; + + MailService::sendMail($to, $subject, $body, strip_tags($body)); + + $_SESSION['success_message'] = "Request status updated and notification sent."; + */ + } + } else { + $_SESSION['info_message'] = "No changes were made to the request."; + } + +} catch (PDOException $e) { + $_SESSION['error_message'] = "Database error: " . $e->getMessage(); + error_log("DB Error: " . $e->getMessage()); +} catch (Exception $e) { + $_SESSION['error_message'] = "Error: " . $e->getMessage(); + error_log("General Error: " . $e->getMessage()); +} + +header('Location: view_request.php?id=' . $requestId); +exit; diff --git a/view_request.php b/view_request.php new file mode 100644 index 0000000..31f9b97 --- /dev/null +++ b/view_request.php @@ -0,0 +1,115 @@ +prepare('SELECT cr.*, u.full_name as requester_full_name, u.username as requester_username, cr.related_request_id FROM change_requests cr JOIN users u ON cr.requester_id = u.id WHERE cr.id = :id'); + $stmt->bindParam(':id', $requestId, PDO::PARAM_INT); + $stmt->execute(); + $request = $stmt->fetch(PDO::FETCH_ASSOC); + var_dump($request); +} catch (PDOException $e) { + $request = null; + error_log("DB Error: " . $e->getMessage()); +} + +if (!$request) { + $_SESSION['error_message'] = "Request not found."; + header("Location: all_requests.php"); + exit; +} + +?> + + + + + + <?= htmlspecialchars($pageTitle) ?> - #<?= htmlspecialchars($request['id']) ?> + + + + + + +
+
+
+

Change Request #

+ +
+
+
+
+ + +
+
+

Requester:

+

Department:

+

System Name:

+
+
+

Submission Date:

+

Category:

+

Program Name:

+ +

Related Change Request No:

+ +
+
+ +
+
Reason for Change:
+

+
+ +
+
Description of Change:
+

+
+ + +
+
+

Approval Action

+
+ +
+ + +
+
+ + +
+ +
+
+ + +
+
+
+ + + + + +