From 0ba5997fadd973d6ba1e700bbee33a4a504a60cc Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 17 Dec 2025 23:56:00 +0000 Subject: [PATCH] Auto commit: 2025-12-17T23:56:00.480Z --- admin/categories.php | 155 ++++++++++++++ admin/index.php | 83 ++++++++ admin/links.php | 99 +++++++++ admin/users.php | 105 +++++++++ assets/css/custom.css | 135 ++++++++++++ assets/js/main.js | 1 + db/migrations/001_initial_schema.sql | 58 +++++ export.mysql | 230 ++++++++++++++++++++ index.php | 305 ++++++++++++++------------- login.php | 100 +++++++++ logout.php | 6 + register.php | 107 ++++++++++ submit.php | 160 ++++++++++++++ 13 files changed, 1401 insertions(+), 143 deletions(-) create mode 100644 admin/categories.php create mode 100644 admin/index.php create mode 100644 admin/links.php create mode 100644 admin/users.php create mode 100644 assets/css/custom.css create mode 100644 assets/js/main.js create mode 100644 db/migrations/001_initial_schema.sql create mode 100644 export.mysql create mode 100644 login.php create mode 100644 logout.php create mode 100644 register.php create mode 100644 submit.php diff --git a/admin/categories.php b/admin/categories.php new file mode 100644 index 0000000..06d720a --- /dev/null +++ b/admin/categories.php @@ -0,0 +1,155 @@ +prepare("INSERT INTO categories (name) VALUES (?)"); + $stmt->execute([$name]); + } + } elseif (isset($_POST['update_category'])) { + $id = $_POST['category_id']; + $name = trim($_POST['category_name']); + $visibility = isset($_POST['visibility']) ? 1 : 0; + $order = (int)$_POST['display_order']; + $stmt = $pdo->prepare("UPDATE categories SET name = ?, visibility = ?, display_order = ? WHERE id = ?"); + $stmt->execute([$name, $visibility, $order, $id]); + } elseif (isset($_POST['delete_category'])) { + $id = $_POST['category_id']; + $stmt = $pdo->prepare("DELETE FROM categories WHERE id = ?"); + $stmt->execute([$id]); + } elseif (isset($_POST['add_subcategory'])) { + $name = trim($_POST['subcategory_name']); + $category_id = $_POST['category_id']; + if (!empty($name)) { + $stmt = $pdo->prepare("INSERT INTO subcategories (category_id, name) VALUES (?, ?)"); + $stmt->execute([$category_id, $name]); + } + } + header("Location: categories.php"); + exit; +} + +// Fetch all categories and subcategories +$categories = $pdo->query("SELECT * FROM categories ORDER BY display_order ASC, name ASC")->fetchAll(); +$subcategories = []; +$stmt = $pdo->query("SELECT * FROM subcategories ORDER BY name ASC"); +while ($row = $stmt->fetch()) { + $subcategories[$row['category_id']][] = $row; +} + +?> + + + + + + Manage Categories - Admin Panel + + + + + +
+

Admin Panel

+ +
+ +
+
+
+ +
+
+
+

Manage Categories

+ + +
+
Add New Category
+
+
+
+ + +
+
+
+
+ + + +
+
+
+ +
+ +
+
+ + > +
+
+ +
+
+ + +
+
+ + +
+
Subcategories
+
    + + +
  • + + +
  • No subcategories yet.
  • + +
+
+ + + +
+
+
+
+ + +
+
+
+
+ + + + + diff --git a/admin/index.php b/admin/index.php new file mode 100644 index 0000000..147462f --- /dev/null +++ b/admin/index.php @@ -0,0 +1,83 @@ +query("SELECT count(*) FROM users")->fetchColumn(); +$link_count = $pdo->query("SELECT count(*) FROM links")->fetchColumn(); +$category_count = $pdo->query("SELECT count(*) FROM categories")->fetchColumn(); + +?> + + + + + + Admin Panel - <?php echo htmlspecialchars($_SERVER['PROJECT_NAME'] ?? 'Web Directory'); ?> + + + + + +
+

Admin Panel

+ +
+ +
+
+
+ +
+
+
+

Dashboard

+
+
+
+

+

Total Users

+
+
+
+
+

+

Total Links

+
+
+
+
+

+

Total Categories

+
+
+
+
+
+
+
+ + + + + diff --git a/admin/links.php b/admin/links.php new file mode 100644 index 0000000..10272b0 --- /dev/null +++ b/admin/links.php @@ -0,0 +1,99 @@ +query("SELECT l.*, u.username, s.name as subcategory_name, c.name as category_name + FROM links l + JOIN users u ON l.user_id = u.id + JOIN subcategories s ON l.subcategory_id = s.id + JOIN categories c ON s.category_id = c.id + ORDER BY l.created_at DESC")->fetchAll(); + +?> + + + + + + Manage Links - Admin Panel + + + + + +
+

Admin Panel

+ +
+ +
+
+
+ +
+
+
+

Manage Links

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TitleURLCategoryUserStatusCreatedActions
No links submitted yet.
... > + +
+
+
+
+
+
+ + + + + diff --git a/admin/users.php b/admin/users.php new file mode 100644 index 0000000..24a5967 --- /dev/null +++ b/admin/users.php @@ -0,0 +1,105 @@ +prepare("UPDATE users SET role = ? WHERE id = ?"); + $stmt->execute([$role, $user_id]); + } + header("Location: users.php"); + exit; +} + +$users = $pdo->query("SELECT id, username, role, created_at FROM users ORDER BY created_at DESC")->fetchAll(); + +?> + + + + + + Manage Users - Admin Panel + + + + + +
+

Admin Panel

+ +
+ +
+
+
+ +
+
+
+

Manage Users

+ + + + + + + + + + + + + + + + + + + +
UsernameRoleRegisteredAction
+
+ + + +
+
+ +
+
+
+
+
+ + + + + diff --git a/assets/css/custom.css b/assets/css/custom.css new file mode 100644 index 0000000..7ffdf9b --- /dev/null +++ b/assets/css/custom.css @@ -0,0 +1,135 @@ + +body { + background: #f0f0f0 url('https://www.transparenttextures.com/patterns/lined-paper.png'); + font-family: Verdana, Geneva, sans-serif; + color: #333; +} + +.header { + background: linear-gradient(to bottom, #eaeaea, #cccccc); + border-bottom: 1px solid #999; + padding: 15px 20px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.header h1 { + font-family: Georgia, Times, 'Times New Roman', serif; + font-size: 2.5em; + color: #000080; /* Classic Blue */ + margin: 0; + text-shadow: 2px 2px 3px #aaa; +} + +.auth-links a { + margin-left: 15px; + color: #000080; + text-decoration: none; +} + +.container { + background-color: #fff; + border: 1px solid #ccc; + box-shadow: 0 0 10px rgba(0,0,0,0.1); + border-radius: 5px; +} + +.category-list { + background-color: #f8f9fa; + border-right: 1px solid #dee2e6; + padding: 15px; +} + +.category-list h3 { + font-family: Georgia, Times, "Times New Roman", serif; + font-size: 1.5rem; + color: #0048ad; + border-bottom: 2px solid #f2c94c; + padding-bottom: 10px; + margin-bottom: 15px; +} + +.category-list .nav-link { + color: #0000FF; + padding: 5px 0; + font-size: 0.9rem; + text-decoration: none; +} + +.category-list .nav-link:hover { + text-decoration: underline; +} + +.content { + padding: 20px; +} + +.content h2 { + font-family: Georgia, Times, "Times New Roman", serif; + color: #0048ad; + border-bottom: 2px solid #ccc; + padding-bottom: 10px; + margin-bottom: 20px; +} + +.link-item { + margin-bottom: 20px; + border: 1px solid #ddd; + padding: 15px; + border-radius: 4px; + background-color: #fff; + transition: box-shadow 0.3s ease; +} + +.link-item:hover { + box-shadow: 0 4px 8px rgba(0,0,0,0.1); +} + +.link-item .thumbnail { + width: 120px; + height: 90px; + object-fit: cover; + border: 1px solid #ccc; + margin-right: 15px; + float: left; +} + +.link-item-body { + overflow: hidden; +} + +.link-item-title { + font-size: 1.2rem; + font-weight: bold; + margin-bottom: 5px; +} + +.link-item-title a { + color: #0000FF; + text-decoration: none; +} + +.link-item-title a:hover { + text-decoration: underline; +} + +.link-item-url { + font-size: 0.8rem; + color: #006400; /* Dark Green */ + margin-bottom: 5px; + display: block; +} + +.link-item-description { + font-size: 0.9rem; + color: #555; +} + +.footer { + text-align: center; + padding: 20px 0; + background-color: #343a40; + color: white; + font-size: 0.9rem; +} diff --git a/assets/js/main.js b/assets/js/main.js new file mode 100644 index 0000000..770c9b5 --- /dev/null +++ b/assets/js/main.js @@ -0,0 +1 @@ +// Future javascript for interactivity diff --git a/db/migrations/001_initial_schema.sql b/db/migrations/001_initial_schema.sql new file mode 100644 index 0000000..ca31d9b --- /dev/null +++ b/db/migrations/001_initial_schema.sql @@ -0,0 +1,58 @@ + +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('regular', 'power_user', 'admin') NOT NULL DEFAULT 'regular', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS `categories` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(255) NOT NULL, + `visibility` BOOLEAN NOT NULL DEFAULT TRUE, + `display_order` INT NOT NULL DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS `subcategories` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `category_id` INT NOT NULL, + `name` VARCHAR(255) NOT NULL, + FOREIGN KEY (`category_id`) REFERENCES `categories`(`id`) ON DELETE CASCADE +); + +CREATE TABLE IF NOT EXISTS `links` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `user_id` INT NOT NULL, + `subcategory_id` INT NOT NULL, + `title` VARCHAR(255) NOT NULL, + `url` VARCHAR(2083) NOT NULL, + `description` TEXT, + `thumbnail_url` VARCHAR(2083), + `status` ENUM('pending', 'approved', 'rejected') NOT NULL DEFAULT 'pending', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`), + FOREIGN KEY (`subcategory_id`) REFERENCES `subcategories`(`id`) +); + +CREATE TABLE IF NOT EXISTS `moderation_logs` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `link_id` INT NOT NULL, + `moderator_id` INT NOT NULL, + `action` ENUM('approved', 'rejected') NOT NULL, + `notes` TEXT, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`link_id`) REFERENCES `links`(`id`), + FOREIGN KEY (`moderator_id`) REFERENCES `users`(`id`) +); + +CREATE TABLE IF NOT EXISTS `visits` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `link_id` INT, + `user_id` INT, + `ip_address` VARCHAR(45), + `user_agent` TEXT, + `visited_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (`link_id`) REFERENCES `links`(`id`), + FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) +); diff --git a/export.mysql b/export.mysql new file mode 100644 index 0000000..393fb4b --- /dev/null +++ b/export.mysql @@ -0,0 +1,230 @@ +/*M!999999\- enable the sandbox mode */ +-- MariaDB dump 10.19 Distrib 10.11.14-MariaDB, for debian-linux-gnu (x86_64) +-- +-- Host: 127.0.0.1 Database: app_37018 +-- ------------------------------------------------------ +-- Server version 10.11.14-MariaDB-0+deb12u2 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `categories` +-- + +DROP TABLE IF EXISTS `categories`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `categories` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `visibility` tinyint(1) NOT NULL DEFAULT 1, + `display_order` int(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `categories` +-- + +LOCK TABLES `categories` WRITE; +/*!40000 ALTER TABLE `categories` DISABLE KEYS */; +INSERT INTO `categories` VALUES +(1,'Arts & Entertainment',1,0), +(2,'Business & Economy',1,0), +(3,'Computers & Internet',1,0), +(4,'Education',1,0), +(5,'Government',1,0), +(6,'Health & Fitness',1,0), +(7,'Home & Garden',1,0), +(8,'News & Media',1,0), +(9,'Recreation & Sports',1,0), +(10,'Reference',1,0), +(11,'Science & Technology',1,0), +(12,'Shopping',1,0), +(13,'Society & Culture',1,0), +(14,'Travel & Tourism',1,0), +(15,'Cars & Vehicles',1,0), +(16,'Food & Drink',1,0), +(17,'Law & Legal Issues',1,0), +(18,'Pets & Animals',1,0), +(19,'Real Estate',1,0), +(20,'Games',1,0); +/*!40000 ALTER TABLE `categories` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `links` +-- + +DROP TABLE IF EXISTS `links`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `links` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `subcategory_id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `url` varchar(2083) NOT NULL, + `description` text DEFAULT NULL, + `thumbnail_url` varchar(2083) DEFAULT NULL, + `status` enum('pending','approved','rejected') NOT NULL DEFAULT 'pending', + `created_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`), + KEY `subcategory_id` (`subcategory_id`), + CONSTRAINT `links_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`), + CONSTRAINT `links_ibfk_2` FOREIGN KEY (`subcategory_id`) REFERENCES `subcategories` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `links` +-- + +LOCK TABLES `links` WRITE; +/*!40000 ALTER TABLE `links` DISABLE KEYS */; +INSERT INTO `links` VALUES +(1,1,1,'test title','https://title.com','this is a test description',NULL,'approved','2025-12-17 15:34:06'); +/*!40000 ALTER TABLE `links` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `moderation_logs` +-- + +DROP TABLE IF EXISTS `moderation_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `moderation_logs` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `link_id` int(11) NOT NULL, + `moderator_id` int(11) NOT NULL, + `action` enum('approved','rejected') NOT NULL, + `notes` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + KEY `link_id` (`link_id`), + KEY `moderator_id` (`moderator_id`), + CONSTRAINT `moderation_logs_ibfk_1` FOREIGN KEY (`link_id`) REFERENCES `links` (`id`), + CONSTRAINT `moderation_logs_ibfk_2` FOREIGN KEY (`moderator_id`) REFERENCES `users` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `moderation_logs` +-- + +LOCK TABLES `moderation_logs` WRITE; +/*!40000 ALTER TABLE `moderation_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `moderation_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `subcategories` +-- + +DROP TABLE IF EXISTS `subcategories`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `subcategories` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `category_id` int(11) NOT NULL, + `name` varchar(255) NOT NULL, + PRIMARY KEY (`id`), + KEY `category_id` (`category_id`), + CONSTRAINT `subcategories_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `subcategories` +-- + +LOCK TABLES `subcategories` WRITE; +/*!40000 ALTER TABLE `subcategories` DISABLE KEYS */; +INSERT INTO `subcategories` VALUES +(1,1,'test Arts & Entertainment'), +(2,11,'Science & Technology syb'); +/*!40000 ALTER TABLE `subcategories` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL, + `password` varchar(255) NOT NULL, + `role` enum('regular','power_user','admin') NOT NULL DEFAULT 'regular', + `created_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `username` (`username`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `users` +-- + +LOCK TABLES `users` WRITE; +/*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` VALUES +(1,'admin','$2y$10$ZXgcZZeRqeZmt3gD1hqnVedgdgGwQ4R5dFoY6YRT.GY0StKYwnx5.','admin','2025-12-17 15:27:26'); +/*!40000 ALTER TABLE `users` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `visits` +-- + +DROP TABLE IF EXISTS `visits`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8mb4 */; +CREATE TABLE `visits` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `link_id` int(11) DEFAULT NULL, + `user_id` int(11) DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `visited_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + KEY `link_id` (`link_id`), + KEY `user_id` (`user_id`), + CONSTRAINT `visits_ibfk_1` FOREIGN KEY (`link_id`) REFERENCES `links` (`id`), + CONSTRAINT `visits_ibfk_2` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `visits` +-- + +LOCK TABLES `visits` WRITE; +/*!40000 ALTER TABLE `visits` DISABLE KEYS */; +/*!40000 ALTER TABLE `visits` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2025-12-17 23:45:53 diff --git a/index.php b/index.php index 7205f3d..4a8592d 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,169 @@ - - + + - - - New Style - - - - - - - - - - - - - - - - - - - + + + + <?php echo htmlspecialchars($_SERVER['PROJECT_NAME'] ?? 'Web Directory'); ?> + + + + + + + + + + + + + + + + + -
-
-

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

+ +query("SELECT * FROM categories WHERE visibility = 1 ORDER BY display_order ASC, name ASC"); +$categories = $stmt->fetchAll(); + +// Determine the current category +$current_category_id = null; +$current_category_name = 'All Categories'; +if (isset($_GET['category']) && filter_var($_GET['category'], FILTER_VALIDATE_INT)) { + $category_id_from_get = (int)$_GET['category']; + $stmt = $pdo->prepare("SELECT id, name FROM categories WHERE id = ? AND visibility = 1"); + $stmt->execute([$category_id_from_get]); + $cat = $stmt->fetch(); + if ($cat) { + $current_category_id = $cat['id']; + $current_category_name = $cat['name']; + } +} + +// Fetch links for the current category +$link_stmt = null; +if ($current_category_id) { + $link_stmt = $pdo->prepare( + "SELECT l.*, s.name as subcategory_name FROM links l " . + "JOIN subcategories s ON l.subcategory_id = s.id " . + "WHERE s.category_id = ? AND l.status = \'approved\' ORDER BY s.name ASC, l.created_at DESC" + ); + $link_stmt->execute([$current_category_id]); +} else { + $link_stmt = $pdo->query( + "SELECT l.*, s.name as subcategory_name, c.name as category_name " . + "FROM links l " . + "JOIN subcategories s ON l.subcategory_id = s.id " . + "JOIN categories c ON s.category_id = c.id " . + "WHERE l.status = 'approved' " . + "ORDER BY c.name ASC, s.name ASC, l.created_at DESC" + ); +} +$current_links = $link_stmt->fetchAll(); + +error_log("DEBUG: GET Parameters: " . json_encode($_GET)); +error_log("DEBUG: Current Category ID: " . ($current_category_id ?? "NULL")); +error_log("DEBUG: Current Category Name: " . $current_category_name); +error_log("DEBUG: SQL Query for links: " . ($current_category_id ? $link_stmt->queryString : "All Categories Query")); +error_log("DEBUG: Current Links Count: " . count($current_links)); + + + +?> + +
+

+ -
- + + +
+
+ +
+ +
+ + +
+
+

+ + +

No links found in this category yet.

+ + ' . htmlspecialchars($current_category_for_display) . ''; + $current_subcategory = null; // Reset subcategory when category changes + } + + if ($link['subcategory_name'] !== $current_subcategory) { + $current_subcategory = $link['subcategory_name']; + echo '

' . htmlspecialchars($current_subcategory) . '

'; + } + ?> + + + + +
+
+
+
+ + + + + + diff --git a/login.php b/login.php new file mode 100644 index 0000000..638e8a5 --- /dev/null +++ b/login.php @@ -0,0 +1,100 @@ +prepare("SELECT id, username, password, role FROM users WHERE username = ?"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['user_role'] = $user['role']; + header("Location: index.php"); + exit; + } else { + $errors[] = 'Invalid username or password.'; + } + } catch (PDOException $e) { + $errors[] = "Database error: " . $e->getMessage(); + } + } +} +?> + + + + + + Login - <?php echo htmlspecialchars($_SERVER['PROJECT_NAME'] ?? 'Web Directory'); ?> + + + + + +
+

+ +
+ +
+
+
+
+

Login

+ + +
+ +

+ +
+ + +
+
+ + +
+
+ + +
+ +
+ +
+
+
+
+ + + + + diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..f83284d --- /dev/null +++ b/logout.php @@ -0,0 +1,6 @@ +prepare("SELECT id FROM users WHERE username = ?"); + $stmt->execute([$username]); + if ($stmt->fetch()) { + $errors[] = 'Username already taken.'; + } else { + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + $stmt = $pdo->prepare("INSERT INTO users (username, password, role) VALUES (?, ?, ?)"); + // For now, all new users are 'regular'. The first admin will be created manually. + $stmt->execute([$username, $hashed_password, 'regular']); + $success = true; + } + } catch (PDOException $e) { + $errors[] = "Database error: " . $e->getMessage(); + } + } +} +?> + + + + + + Register - <?php echo htmlspecialchars($_SERVER['PROJECT_NAME'] ?? 'Web Directory'); ?> + + + + + +
+

+ +
+ +
+
+
+
+

Register

+ + +
+ +

+ +
+ + + +
+

Registration successful! You can now login.

+
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+
+
+
+ + + + + diff --git a/submit.php b/submit.php new file mode 100644 index 0000000..aae7963 --- /dev/null +++ b/submit.php @@ -0,0 +1,160 @@ +query("SELECT * FROM categories WHERE visibility = 1 ORDER BY display_order ASC, name ASC")->fetchAll(); +$subcategories = []; +if (!empty($categories)) { + $stmt = $pdo->query("SELECT * FROM subcategories ORDER BY name ASC"); + while ($row = $stmt->fetch()) { + $subcategories[$row['category_id']][] = $row; + } +} + +if ($_SERVER["REQUEST_METHOD"] == "POST") { + $title = trim($_POST['title'] ?? ''); + $url = trim($_POST['url'] ?? ''); + $description = trim($_POST['description'] ?? ''); + $subcategory_id = $_POST['subcategory_id'] ?? null; + + if (empty($title)) $errors[] = 'Title is required.'; + if (empty($url)) $errors[] = 'URL is required.'; + if (!filter_var($url, FILTER_VALIDATE_URL)) $errors[] = 'Invalid URL.'; + if (empty($subcategory_id)) $errors[] = 'Subcategory is required.'; + + if (empty($errors)) { + // Determine status based on user role + $status = ($_SESSION['user_role'] === 'admin' || $_SESSION['user_role'] === 'power_user') ? 'approved' : 'pending'; + + // For now, thumbnail is not implemented + $thumbnail_url = null; + + try { + $stmt = $pdo->prepare("INSERT INTO links (user_id, subcategory_id, title, url, description, thumbnail_url, status) VALUES (?, ?, ?, ?, ?, ?, ?)"); + $stmt->execute([$_SESSION['user_id'], $subcategory_id, $title, $url, $description, $thumbnail_url, $status]); + $success = true; + } catch (PDOException $e) { + $errors[] = "Database error: " . $e->getMessage(); + } + } +} +?> + + + + + + Submit a Link - <?php echo htmlspecialchars($_SERVER['PROJECT_NAME'] ?? 'Web Directory'); ?> + + + + + +
+

+ +
+ +
+
+
+
+

Submit a New Link

+ + +
+

+
+ + + +
+

Thank you for your submission! It will be reviewed shortly.

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