36293-vm/projects.php
2025-11-25 21:46:02 +00:00

341 lines
17 KiB
PHP

<?php
// --- FORM PROCESSING ---
$form_error = null;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'create_project') {
if (empty($_POST['name'])) {
$form_error = "Project Name is required.";
} else {
try {
require_once __DIR__ . '/db/config.php';
$pdo_form = db();
$insert_sql = "INSERT INTO projects (name, wbs, startDate, endDate, budget, recoverability, targetMargin) VALUES (:name, :wbs, :startDate, :endDate, :budget, :recoverability, :targetMargin)";
$stmt = $pdo_form->prepare($insert_sql);
$stmt->execute([
':name' => $_POST['name'],
':wbs' => $_POST['wbs'] ?? null,
':startDate' => empty($_POST['startDate']) ? null : $_POST['startDate'],
':endDate' => empty($_POST['endDate']) ? null : $_POST['endDate'],
':budget' => (float)($_POST['budget'] ?? 0),
':recoverability' => (float)($_POST['recoverability'] ?? 100),
':targetMargin' => (float)($_POST['targetMargin'] ?? 0),
]);
// Create initial forecasting version
$projectId = $pdo_form->lastInsertId();
$forecast_sql = "INSERT INTO forecasting (projectId, versionNumber, createdAt) VALUES (:projectId, 1, NOW())";
$forecast_stmt = $pdo_form->prepare($forecast_sql);
$forecast_stmt->execute([':projectId' => $projectId]);
header("Location: " . $_SERVER['PHP_SELF']);
exit();
} catch (PDOException $e) {
$form_error = "Database error: " . $e->getMessage();
}
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'delete_project') {
try {
require_once __DIR__ . '/db/config.php';
$pdo_delete = db();
$delete_sql = "DELETE FROM projects WHERE id = :id";
$stmt = $pdo_delete->prepare($delete_sql);
$stmt->execute([':id' => $_POST['id']]);
header("Location: " . $_SERVER['PHP_SELF']);
exit();
} catch (PDOException $e) {
$form_error = "Database error: " . $e->getMessage();
}
}
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'update_project') {
if (empty($_POST['id']) || empty($_POST['name'])) {
$form_error = "ID and Project Name are required for an update.";
} else {
try {
require_once __DIR__ . '/db/config.php';
$pdo_update = db();
$update_sql = "UPDATE projects SET
name = :name,
wbs = :wbs,
startDate = :startDate,
endDate = :endDate,
budget = :budget,
recoverability = :recoverability,
targetMargin = :targetMargin
WHERE id = :id";
$stmt = $pdo_update->prepare($update_sql);
$stmt->execute([
':id' => $_POST['id'],
':name' => $_POST['name'],
':wbs' => $_POST['wbs'] ?? null,
':startDate' => empty($_POST['startDate']) ? null : $_POST['startDate'],
':endDate' => empty($_POST['endDate']) ? null : $_POST['endDate'],
':budget' => (float)($_POST['budget'] ?? 0),
':recoverability' => (float)($_POST['recoverability'] ?? 100),
':targetMargin' => (float)($_POST['targetMargin'] ?? 0),
]);
header("Location: " . $_SERVER['PHP_SELF']);
exit();
} catch (PDOException $e) {
$form_error = "Database error: " . $e->getMessage();
}
}
}
// --- DATABASE INITIALIZATION ---
require_once __DIR__ . '/db/config.php';
function execute_sql_from_file($pdo, $filepath) {
try {
$sql = file_get_contents($filepath);
$pdo->exec($sql);
return true;
} catch (PDOException $e) {
if (strpos($e->getMessage(), 'already exists') === false) {
error_log("SQL Execution Error: " . $e->getMessage());
}
return false;
}
}
$projects_data = [];
try {
$pdo = db();
// Apply all migrations
$migration_files = glob(__DIR__ . '/db/migrations/*.sql');
sort($migration_files);
foreach ($migration_files as $file) {
execute_sql_from_file($pdo, $file);
}
$stmt = $pdo->query("SELECT * FROM projects ORDER BY name");
$projects_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$db_error = "Database connection failed: " . $e->getMessage();
}
// --- RENDER PAGE ---
?>
<!DOCTYPE html>
<html lang="en" data-bs-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Projects - Project Financials</title>
<meta name="description" content="Manage Projects - Project Financials Management Tool">
<meta property="og:title" content="Projects - Project Financials">
<meta property="og:description" content="Manage your project financials, roster, and budget.">
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
<meta name="twitter:card" content="summary_large_image">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<div class="top-navbar">
Project Financials
</div>
<div class="main-wrapper">
<nav class="sidebar">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link" href="index.php"><i class="bi bi-people-fill me-2"></i>Roster</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="projects.php"><i class="bi bi-briefcase-fill me-2"></i>Projects</a>
</li>
</ul>
</nav>
<main class="content-wrapper">
<?php if (isset($db_error)): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($db_error); ?></div>
<?php elseif (isset($form_error)): ?>
<div class="alert alert-danger"><?php echo htmlspecialchars($form_error); ?></div>
<?php endif; ?>
<div class="page-header">
<h1 class="h2">Projects</h1>
<div class="header-actions">
<button class="btn btn-secondary disabled" disabled><i class="bi bi-upload me-2"></i>Import Excel</button>
<button class="btn btn-secondary disabled" disabled><i class="bi bi-download me-2"></i>Export Excel</button>
<button class="btn btn-primary" id="newProjectBtn"><i class="bi bi-plus-circle-fill me-2"></i>New Project</button>
</div>
</div>
<div class="card">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Name</th>
<th>WBS</th>
<th>Start Date</th>
<th>End Date</th>
<th>Budget</th>
<th>Recoverability</th>
<th>Target Margin</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php if (empty($projects_data)): ?>
<tr>
<td colspan="8" class="text-center text-secondary">No projects found.</td>
</tr>
<?php else: ?>
<?php foreach ($projects_data as $row): ?>
<tr>
<td><?php echo htmlspecialchars($row['name']); ?></td>
<td><?php echo htmlspecialchars($row['wbs']); ?></td>
<td><?php echo htmlspecialchars($row['startDate']); ?></td>
<td><?php echo htmlspecialchars($row['endDate']); ?></td>
<td>&euro;<?php echo number_format($row['budget'], 2); ?></td>
<td><?php echo number_format($row['recoverability'], 2); ?>%</td>
<td><?php echo number_format($row['targetMargin'], 2); ?>%</td>
<td>
<div class="d-flex">
<a href="project_details.php?id=<?php echo $row['id']; ?>" class="btn btn-sm btn-outline-info me-2">View</a>
<button class="btn btn-sm btn-outline-primary me-2 edit-btn"
data-row='<?php echo htmlspecialchars(json_encode($row), ENT_QUOTES, 'UTF-8'); ?>'>
Edit
</button>
<form action="projects.php" method="POST" onsubmit="return confirm('Are you sure you want to delete this item?');">
<input type="hidden" name="action" value="delete_project">
<input type="hidden" name="id" value="<?php echo $row['id']; ?>">
<button type="submit" class="btn btn-sm btn-outline-danger">Delete</button>
</form>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</main>
</div>
<!-- New Project Modal -->
<div class="modal fade" id="newProjectModal" tabindex="-1" aria-labelledby="newProjectModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form action="projects.php" method="POST">
<input type="hidden" name="action" value="create_project">
<div class="modal-header">
<h5 class="modal-title" id="newProjectModalLabel">New Project</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="name" class="form-label">Project Name</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="mb-3">
<label for="wbs" class="form-label">WBS</label>
<input type="text" class="form-control" id="wbs" name="wbs">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="startDate" class="form-label">Start Date</label>
<input type="date" class="form-control" id="startDate" name="startDate">
</div>
<div class="col-md-6 mb-3">
<label for="endDate" class="form-label">End Date</label>
<input type="date" class="form-control" id="endDate" name="endDate">
</div>
</div>
<div class="mb-3">
<label for="budget" class="form-label">Budget (&euro;)</label>
<input type="number" step="0.01" class="form-control" id="budget" name="budget" value="0">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="recoverability" class="form-label">Recoverability (%)</label>
<input type="number" step="0.01" class="form-control" id="recoverability" name="recoverability" value="100">
</div>
<div class="col-md-6 mb-3">
<label for="targetMargin" class="form-label">Target Margin (%)</label>
<input type="number" step="0.01" class="form-control" id="targetMargin" name="targetMargin" value="0">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save Project</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/projects.js?v=<?php echo time(); ?>"></script>
<!-- Edit Project Modal -->
<div class="modal fade" id="editProjectModal" tabindex="-1" aria-labelledby="editProjectModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<form action="projects.php" method="POST">
<input type="hidden" name="action" value="update_project">
<input type="hidden" name="id" id="edit-id">
<div class="modal-header">
<h5 class="modal-title" id="editProjectModalLabel">Edit Project</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="edit-name" class="form-label">Project Name</label>
<input type="text" class="form-control" id="edit-name" name="name" required>
</div>
<div class="mb-3">
<label for="edit-wbs" class="form-label">WBS</label>
<input type="text" class="form-control" id="edit-wbs" name="wbs">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit-startDate" class="form-label">Start Date</label>
<input type="date" class="form-control" id="edit-startDate" name="startDate">
</div>
<div class="col-md-6 mb-3">
<label for="edit-endDate" class="form-label">End Date</label>
<input type="date" class="form-control" id="edit-endDate" name="endDate">
</div>
</div>
<div class="mb-3">
<label for="edit-budget" class="form-label">Budget (&euro;)</label>
<input type="number" step="0.01" class="form-control" id="edit-budget" name="budget">
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="edit-recoverability" class="form-label">Recoverability (%)</label>
<input type="number" step="0.01" class="form-control" id="edit-recoverability" name="recoverability">
</div>
<div class="col-md-6 mb-3">
<label for="edit-targetMargin" class="form-label">Target Margin (%)</label>
<input type="number" step="0.01" class="form-control" id="edit-targetMargin" name="targetMargin">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
</div>
</body>
</html>