From 6908213cbc5b58df10c97b5a58c2b5d178163571 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 15 Feb 2026 21:17:22 +0000 Subject: [PATCH] init --- add_log.php | 26 ++ cls/class.pef.php | 137 +++++++ db/migrations/20260215_init.sql | 20 + db/migrations/20260216_auth_and_status.sql | 30 ++ index.php | 447 +++++++++++++++------ login.php | 63 +++ logout.php | 5 + manage_project.php | 32 ++ migrate.php | 23 ++ seed.php | 18 + 10 files changed, 673 insertions(+), 128 deletions(-) create mode 100644 add_log.php create mode 100644 cls/class.pef.php create mode 100644 db/migrations/20260215_init.sql create mode 100644 db/migrations/20260216_auth_and_status.sql create mode 100644 login.php create mode 100644 logout.php create mode 100644 manage_project.php create mode 100644 migrate.php create mode 100644 seed.php diff --git a/add_log.php b/add_log.php new file mode 100644 index 0000000..1b18b03 --- /dev/null +++ b/add_log.php @@ -0,0 +1,26 @@ +addLog($projectId, $version, $logEntry, $author); + } + + header("Location: index.php?view=projects&project_id=$projectId"); + exit; +} + +header('Location: index.php'); +exit; diff --git a/cls/class.pef.php b/cls/class.pef.php new file mode 100644 index 0000000..e8dd6a6 --- /dev/null +++ b/cls/class.pef.php @@ -0,0 +1,137 @@ +db = db(); + } + + /** + * Get all projects, optionally filtered by industry or status. + */ + public function getProjects(?string $industry = null, ?string $status = null): array { + $sql = "SELECT * FROM projects WHERE 1=1"; + $params = []; + if ($industry) { + $sql .= " AND industry = :industry"; + $params['industry'] = $industry; + } + if ($status) { + $sql .= " AND status = :status"; + $params['status'] = $status; + } + $sql .= " ORDER BY updated_at DESC"; + + $stmt = $this->db->prepare($sql); + $stmt->execute($params); + return $stmt->fetchAll(); + } + + /** + * User authentication. + */ + public function login(string $username, string $password): ?array { + $stmt = $this->db->prepare("SELECT * FROM users WHERE username = :username"); + $stmt->execute(['username' => $username]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + unset($user['password']); + return $user; + } + return null; + } + + /** + * Update project status or details. + */ + public function updateProject(int $id, array $data): bool { + $fields = []; + foreach ($data as $key => $value) { + $fields[] = "$key = :$key"; + } + $sql = "UPDATE projects SET " . implode(', ', $fields) . " WHERE id = :id"; + $data['id'] = $id; + $stmt = $this->db->prepare($sql); + return $stmt->execute($data); + } + + /** + * Delete project. + */ + public function deleteProject(int $id): bool { + $stmt = $this->db->prepare("DELETE FROM projects WHERE id = :id"); + return $stmt->execute(['id' => $id]); + } + + /** + * Dashboard stats. + */ + public function getStats(): array { + $stats = []; + $stats['total_projects'] = $this->db->query("SELECT COUNT(*) FROM projects")->fetchColumn(); + $stats['active_projects'] = $this->db->query("SELECT COUNT(*) FROM projects WHERE status = 'active'")->fetchColumn(); + $stats['latest_logs'] = $this->db->query("SELECT pl.*, p.name as project_name FROM project_logs pl JOIN projects p ON pl.project_id = p.id ORDER BY pl.created_at DESC LIMIT 5")->fetchAll(); + return $stats; + } + + /** + * Get a single project by ID. + */ + public function getProject(int $id): ?array { + $stmt = $this->db->prepare("SELECT * FROM projects WHERE id = :id"); + $stmt->execute(['id' => $id]); + return $stmt->fetch() ?: null; + } + + /** + * Get all logs for a specific project. + */ + public function getProjectLogs(int $projectId): array { + $stmt = $this->db->prepare("SELECT * FROM project_logs WHERE project_id = :project_id ORDER BY created_at DESC"); + $stmt->execute(['project_id' => $projectId]); + return $stmt->fetchAll(); + } + + /** + * Create a new project. + */ + public function createProject(string $name, string $description, string $industry, string $version = '1.0.0'): int { + $stmt = $this->db->prepare("INSERT INTO projects (name, description, industry, current_version) VALUES (:name, :description, :industry, :version)"); + $stmt->execute([ + 'name' => $name, + 'description' => $description, + 'industry' => $industry, + 'version' => $version + ]); + return (int)$this->db->lastInsertId(); + } + + /** + * Add a log entry for a project and update its current version. + */ + public function addLog(int $projectId, string $version, string $logEntry, string $author = 'System'): bool { + try { + $this->db->beginTransaction(); + + $stmt = $this->db->prepare("INSERT INTO project_logs (project_id, version, log_entry, author) VALUES (:project_id, :version, :log_entry, :author)"); + $stmt->execute([ + 'project_id' => $projectId, + 'version' => $version, + 'log_entry' => $logEntry, + 'author' => $author + ]); + + $stmt = $this->db->prepare("UPDATE projects SET current_version = :version WHERE id = :id"); + $stmt->execute(['version' => $version, 'id' => $projectId]); + + $this->db->commit(); + return true; + } catch (Exception $e) { + $this->db->rollBack(); + return false; + } + } +} diff --git a/db/migrations/20260215_init.sql b/db/migrations/20260215_init.sql new file mode 100644 index 0000000..38070d5 --- /dev/null +++ b/db/migrations/20260215_init.sql @@ -0,0 +1,20 @@ +-- Initial schema for Construction and Education CMS +CREATE TABLE IF NOT EXISTS projects ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(255) NOT NULL, + description TEXT, + industry ENUM('Construction', 'Education', 'Other') DEFAULT 'Construction', + current_version VARCHAR(50) DEFAULT '1.0.0', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS project_logs ( + id INT AUTO_INCREMENT PRIMARY KEY, + project_id INT NOT NULL, + version VARCHAR(50) NOT NULL, + log_entry TEXT NOT NULL, + author VARCHAR(255), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE +); diff --git a/db/migrations/20260216_auth_and_status.sql b/db/migrations/20260216_auth_and_status.sql new file mode 100644 index 0000000..c47272a --- /dev/null +++ b/db/migrations/20260216_auth_and_status.sql @@ -0,0 +1,30 @@ +-- Add users table +CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(50) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + role ENUM('admin', 'editor', 'viewer') DEFAULT 'viewer', + full_name VARCHAR(100), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +-- Safely add status column +SET @dbname = DATABASE(); +SET @tablename = "projects"; +SET @columnname = "status"; +SET @preparedStatement = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = @dbname + AND TABLE_NAME = @tablename + AND COLUMN_NAME = @columnname) > 0, + "SELECT 1", + "ALTER TABLE projects ADD COLUMN status ENUM('active', 'completed', 'on_hold', 'archived') DEFAULT 'active' AFTER industry" +)); +PREPARE stmt FROM @preparedStatement; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- Create default admin user (password: admin123) +INSERT INTO users (username, password, role, full_name) +VALUES ('admin', '$2y$10$Tsw26nakbueEO40q9tx8Pe4g1yQuWfQFhKXjyVYvbNakTgBi/7NkG', 'admin', 'System Administrator') +ON DUPLICATE KEY UPDATE password = VALUES(password); diff --git a/index.php b/index.php index 7205f3d..8c34ad0 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,341 @@ getStats(); +$projects = $pef->getProjects(); + +$selectedProjectId = isset($_GET['project_id']) ? (int)$_GET['project_id'] : null; +$selectedProject = $selectedProjectId ? $pef->getProject($selectedProjectId) : null; +$logs = $selectedProjectId ? $pef->getProjectLogs($selectedProjectId) : []; + +$view = $_GET['view'] ?? 'dashboard'; ?> - New Style - - - - - - - - - - - - - - - + CMS Dashboard - Construction & Education - + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… + + +
+
+

+
+ +
+
+ +
+ +
+
+
Total Projects
+
+
+
+
Active Projects
+
+
+
+ +
+

Recent Activity

+
+ +

No recent activity. Start by creating a project or adding a log.

+ + +
+
+ (v) + +
+
+
By:
+
+ + +
+
+ + + + + + +
+
+

+
+ + + + +
+
+
+

+
+ Industry: | Current Version: v +
+
+
+ + +
+

Add New Log & Version

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

Version History

+
+ +

No logs available.

+ + +
+
+ Version + +
+
+
Author:
+
+ + +
+
+ + + +
+
+

Managed Projects

+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
Project NameIndustryStatusVersionLast UpdatedActions
v + View +
+
+
+ +
-
- Page updated: (UTC) -
+ + + + + + + + + diff --git a/login.php b/login.php new file mode 100644 index 0000000..c486746 --- /dev/null +++ b/login.php @@ -0,0 +1,63 @@ +login($_POST['username'] ?? '', $_POST['password'] ?? ''); + if ($user) { + $_SESSION['user'] = $user; + header('Location: index.php'); + exit; + } else { + $error = 'Invalid username or password.'; + } +} +?> + + + + + + Login - Construction & Education CMS + + + + + + + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..37bc5ab --- /dev/null +++ b/logout.php @@ -0,0 +1,5 @@ +createProject( + $_POST['name'], + $_POST['description'], + $_POST['industry'], + $_POST['version'] ?: '1.0.0' + ); +} elseif ($action === 'update') { + $pef->updateProject((int)$_POST['id'], [ + 'name' => $_POST['name'], + 'description' => $_POST['description'], + 'industry' => $_POST['industry'], + 'status' => $_POST['status'] + ]); +} elseif ($action === 'delete') { + $id = (int)($_POST['id'] ?? $_GET['id'] ?? 0); + $pef->deleteProject($id); +} + +header('Location: index.php'); +exit; diff --git a/migrate.php b/migrate.php new file mode 100644 index 0000000..9f5ede3 --- /dev/null +++ b/migrate.php @@ -0,0 +1,23 @@ +exec($sql); + echo "Successfully ran migration: " . basename($file) . "\n"; + } catch (PDOException $e) { + echo "Error running migration " . basename($file) . ": " . $e->getMessage() . "\n"; + } + } +} + +if (php_sapi_name() === 'cli' || isset($_GET['run'])) { + runMigrations(); +} diff --git a/seed.php b/seed.php new file mode 100644 index 0000000..de0148c --- /dev/null +++ b/seed.php @@ -0,0 +1,18 @@ +getProjects()) === 0) { + $p1 = $pef->createProject('Bridge Construction A1', 'Main bridge construction for the highway project.', 'Construction', '1.0.0'); + $pef->addLog($p1, '1.0.0', 'Project initiated.', 'Admin'); + $pef->addLog($p1, '1.1.0', 'Foundation completed.', 'Site Manager'); + + $p2 = $pef->createProject('Online Learning Platform', 'LMS for local schools.', 'Education', '0.9.0'); + $pef->addLog($p2, '0.9.0', 'Beta version launched for testing.', 'Dev Team'); + + echo "Sample data seeded.\n"; +} else { + echo "Database already contains data.\n"; +}