exec("CREATE TABLE IF NOT EXISTS `projects` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`description` text NOT NULL,
`client_name` varchar(150) DEFAULT '',
`location` varchar(255) DEFAULT '',
`budget` decimal(12,2) DEFAULT 0,
`materials` varchar(500) DEFAULT '',
`completion_date` date DEFAULT NULL,
`thumbnail` varchar(255) DEFAULT '',
`gallery_images` text DEFAULT NULL,
`is_featured` tinyint(1) DEFAULT 0,
`is_active` tinyint(1) DEFAULT 1,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
$pdo->exec("CREATE TABLE IF NOT EXISTS `project_images` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`project_id` int(11) NOT NULL,
`image` varchar(255) NOT NULL,
`sort_order` int(11) DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT current_timestamp(),
PRIMARY KEY (`id`),
KEY `project_id` (`project_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
} catch(Exception $e) {}
$upload_dir = '../uploads/projects/';
if (!is_dir($upload_dir)) {
@mkdir($upload_dir, 0777, true);
}
$upload_ok = is_writable($upload_dir);
// Handle Delete Single Image
if (isset($_GET['del_img']) && isset($_GET['pid'])) {
$img_id = (int)$_GET['del_img'];
$pid = (int)$_GET['pid'];
try {
$stmt = $pdo->prepare("SELECT image FROM project_images WHERE id=? AND project_id=?");
$stmt->execute([$img_id, $pid]);
$img = $stmt->fetch();
if ($img) {
@unlink($upload_dir . $img['image']);
$pdo->prepare("DELETE FROM project_images WHERE id=?")->execute([$img_id]);
$msg = "
Image deleted successfully.
";
}
} catch(Exception $e) {}
}
// Handle Delete Project
if (isset($_GET['delete'])) {
$id = (int)$_GET['delete'];
try {
// Remove project images files
$stmt = $pdo->prepare("SELECT image FROM project_images WHERE project_id=?");
$stmt->execute([$id]);
foreach($stmt->fetchAll() as $img) @unlink($upload_dir . $img['image']);
// Remove thumbnail
$stmt2 = $pdo->prepare("SELECT thumbnail FROM projects WHERE id=?");
$stmt2->execute([$id]);
$proj = $stmt2->fetch();
if ($proj) @unlink($upload_dir . $proj['thumbnail']);
// DB delete (cascades project_images)
$pdo->prepare("DELETE FROM projects WHERE id=?")->execute([$id]);
$msg = "Project deleted successfully.
";
} catch(Exception $e) {
$msg = "Error deleting project.
";
}
}
// Handle Add Project
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action']) && $_POST['action'] == 'add') {
$title = trim($_POST['title'] ?? '');
$desc = trim($_POST['description'] ?? '');
$client = trim($_POST['client_name'] ?? '');
$location = trim($_POST['location'] ?? '');
$budget = (float)($_POST['budget'] ?? 0);
$materials = trim($_POST['materials'] ?? '');
$date = !empty($_POST['completion_date']) ? $_POST['completion_date'] : null;
if (empty($title) || empty($desc)) {
$msg = "Please fill in the Title and Description fields.
";
} else {
$thumbnail = '';
$all_images = [];
$upload_errors = [];
// Handle image uploads
if (!empty($_FILES['images']['name'][0])) {
if (!$upload_ok) {
$upload_errors[] = 'Upload directory is not writable on the server.';
} else {
foreach ($_FILES['images']['name'] as $k => $name) {
if ($name && $_FILES['images']['error'][$k] == UPLOAD_ERR_OK) {
$ext = strtolower(pathinfo($name, PATHINFO_EXTENSION));
$allowed = ['jpg','jpeg','png','gif','webp'];
if (!in_array($ext, $allowed)) {
$upload_errors[] = "File '$name' is not an allowed image type.";
continue;
}
$fname = time() . '_' . $k . '_' . preg_replace('/[^a-zA-Z0-9._-]/', '_', $name);
if (move_uploaded_file($_FILES['images']['tmp_name'][$k], $upload_dir . $fname)) {
$all_images[] = $fname;
if (empty($thumbnail)) $thumbnail = $fname;
} else {
$upload_errors[] = "Failed to upload '$name'.";
}
} elseif ($_FILES['images']['error'][$k] != UPLOAD_ERR_NO_FILE) {
$upload_errors[] = "Upload error code " . $_FILES['images']['error'][$k] . " for file '$name'.";
}
}
}
}
try {
$stmt = $pdo->prepare("INSERT INTO projects (title, description, client_name, location, budget, materials, completion_date, thumbnail, gallery_images) VALUES (?,?,?,?,?,?,?,?,?)");
$stmt->execute([$title, $desc, $client, $location, $budget, $materials, $date, $thumbnail, json_encode($all_images)]);
$project_id = $pdo->lastInsertId();
// Insert images into project_images table
foreach ($all_images as $idx => $img) {
$pdo->prepare("INSERT INTO project_images (project_id, image, sort_order) VALUES (?,?,?)")->execute([$project_id, $img, $idx]);
}
$flash = 'Project added successfully!';
if (!empty($upload_errors)) {
$flash .= ' (Some images had issues: ' . implode(', ', $upload_errors) . ')';
}
$msg = "$flash
";
} catch(Exception $e) {
$msg = "Database Error: " . e($e->getMessage()) . "
";
}
}
}
// Handle Edit Project
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['action']) && $_POST['action'] == 'edit') {
$id = (int)$_POST['id'];
$title = $_POST['title'];
$desc = $_POST['description'];
$client = $_POST['client_name'];
$location = $_POST['location'];
$budget = (float)$_POST['budget'];
$materials= $_POST['materials'];
$date = $_POST['completion_date'] ?: null;
$new_images = [];
if (!empty($_FILES['images']['name'][0])) {
foreach ($_FILES['images']['name'] as $k => $name) {
if ($name && $_FILES['images']['error'][$k] == 0) {
$fname = time() . '_' . $k . '_' . preg_replace('/[^a-zA-Z0-9._-]/', '_', $name);
move_uploaded_file($_FILES['images']['tmp_name'][$k], $upload_dir . $fname);
$new_images[] = $fname;
}
}
}
try {
// Get current thumbnail
$stmt = $pdo->prepare("SELECT thumbnail FROM projects WHERE id=?");
$stmt->execute([$id]);
$existing = $stmt->fetch();
// Get current images
$stmt2 = $pdo->prepare("SELECT image FROM project_images WHERE project_id=? ORDER BY sort_order");
$stmt2->execute([$id]);
$current_imgs = array_column($stmt2->fetchAll(), 'image');
// Insert new images
$start_order = count($current_imgs);
foreach ($new_images as $idx => $img) {
$pdo->prepare("INSERT INTO project_images (project_id, image, sort_order) VALUES (?,?,?)")->execute([$id, $img, $start_order + $idx]);
}
// Get updated image list for gallery_images
$all_imgs = array_merge($current_imgs, $new_images);
$thumbnail = $existing['thumbnail'] ?: ($all_imgs[0] ?? '');
$pdo->prepare("UPDATE projects SET title=?, description=?, client_name=?, location=?, budget=?, materials=?, completion_date=?, thumbnail=?, gallery_images=? WHERE id=?")
->execute([$title, $desc, $client, $location, $budget, $materials, $date, $thumbnail, json_encode($all_imgs), $id]);
$msg = "Project updated successfully!
";
} catch(Exception $e) {
$msg = "Error: " . e($e->getMessage()) . "
";
}
}
// Fetch all projects
$projects = [];
try {
$stmt = $pdo->query("SELECT p.*, (SELECT COUNT(*) FROM project_images WHERE project_id=p.id) as img_count FROM projects p ORDER BY p.created_at DESC");
$projects = $stmt->fetchAll();
} catch(Exception $e) {}
// If editing, fetch edit data
$edit_project = null;
$edit_images = [];
if (isset($_GET['edit'])) {
$edit_id = (int)$_GET['edit'];
try {
$stmt = $pdo->prepare("SELECT * FROM projects WHERE id=?");
$stmt->execute([$edit_id]);
$edit_project = $stmt->fetch();
$stmt2 = $pdo->prepare("SELECT * FROM project_images WHERE project_id=? ORDER BY sort_order");
$stmt2->execute([$edit_id]);
$edit_images = $stmt2->fetchAll();
} catch(Exception $e) {}
}
?>
Our Projects
= $msg ?>
| Photo |
Title |
Location |
Budget |
Photos |
Date |
Actions |
|
No projects added yet. Click Add Project to get started.
|
>
|
= e($p['title']) ?> |
= e($p['location']) ?> |
= format_currency($p['budget']) ?> |
= $p['img_count'] ?> photos |
= $p['completion_date'] ? date('M Y', strtotime($p['completion_date'])) : '-' ?> |
|