diff --git a/admin.php b/admin.php new file mode 100644 index 0000000..2e8617a --- /dev/null +++ b/admin.php @@ -0,0 +1,37 @@ + + +
+
+

Admin Panel

+

Manage your application from here.

+
+
+ +
+
+
+
+
+

Admin Menu

+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/admin_product_edit.php b/admin_product_edit.php new file mode 100644 index 0000000..05cb351 --- /dev/null +++ b/admin_product_edit.php @@ -0,0 +1,108 @@ + null, + 'name' => '', + 'description' => '', + 'price' => '', + 'image' => '' +]; +$errors = []; +$page_title = 'Add New Product'; + +if (isset($_GET['id']) && is_numeric($_GET['id'])) { + $page_title = 'Edit Product'; + $product_id = $_GET['id']; + $stmt = $pdo->prepare("SELECT * FROM products WHERE id = ?"); + $stmt->execute([$product_id]); + $product = $stmt->fetch(); + if (!$product) { + header("Location: admin_products.php"); + exit; + } +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $product['name'] = $_POST['name']; + $product['description'] = $_POST['description']; + $product['price'] = $_POST['price']; + $product['image'] = $_POST['image']; + + if (empty($product['name'])) { + $errors[] = 'Name is required'; + } + if (empty($product['price']) || !is_numeric($product['price'])) { + $errors[] = 'Price must be a number'; + } + + if (empty($errors)) { + if ($product['id']) { + // Update + $stmt = $pdo->prepare("UPDATE products SET name = ?, description = ?, price = ?, image = ? WHERE id = ?"); + $stmt->execute([$product['name'], $product['description'], $product['price'], $product['image'], $product['id']]); + } else { + // Insert + $stmt = $pdo->prepare("INSERT INTO products (name, description, price, image) VALUES (?, ?, ?, ?)"); + $stmt->execute([$product['name'], $product['description'], $product['price'], $product['image']]); + } + header("Location: admin_products.php"); + exit; + } +} +?> + +
+
+

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

+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + Cancel +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/admin_products.php b/admin_products.php new file mode 100644 index 0000000..e19dcf2 --- /dev/null +++ b/admin_products.php @@ -0,0 +1,71 @@ +prepare("DELETE FROM products WHERE id = ?"); + $stmt->execute([$product_id]); + header("Location: admin_products.php"); + exit; +} + +$stmt = $pdo->query("SELECT * FROM products ORDER BY created_at DESC"); +$products = $stmt->fetchAll(); +?> + +
+
+

Manage Products

+
+
+ +
+
+ Add New Product +
+ +
+
+ + + + + + + + + + + + + + + + + + + +
ImageNamePriceActions
+ <?php echo htmlspecialchars($product['name']); ?> + $ + Edit +
+ + +
+
+
+
+
+ + \ No newline at end of file diff --git a/admin_user_edit.php b/admin_user_edit.php new file mode 100644 index 0000000..ff5fec3 --- /dev/null +++ b/admin_user_edit.php @@ -0,0 +1,54 @@ +prepare("SELECT * FROM users WHERE id = ?"); +$stmt->execute([$user_id]); +$user = $stmt->fetch(); + +if (!$user) { + header("Location: admin_users.php"); + exit; +} + +// For now, this is just a placeholder page. +// Full edit functionality will be added later. +?> + +
+
+

+

Editing user:

+
+
+ +
+
+
+
+
+

Full user editing functionality will be implemented here soon.

+ Back to Users List +
+
+
+
+
+ + \ No newline at end of file diff --git a/admin_users.php b/admin_users.php new file mode 100644 index 0000000..e3a1a3b --- /dev/null +++ b/admin_users.php @@ -0,0 +1,108 @@ +prepare("UPDATE users SET role = ? WHERE id = ?"); + $stmt->execute([$role, $user_id]); + } elseif (isset($_POST['update_balance'])) { + $user_id = $_POST['user_id']; + $balance = $_POST['balance']; + $stmt = $pdo->prepare("UPDATE users SET balance = ? WHERE id = ?"); + $stmt->execute([$balance, $user_id]); + } elseif (isset($_POST['update_status'])) { + $user_id = $_POST['user_id']; + $status = $_POST['status']; + $stmt = $pdo->prepare("UPDATE users SET status = ? WHERE id = ?"); + $stmt->execute([$status, $user_id]); + } + header("Location: admin_users.php"); + exit; +} + +$stmt = $pdo->query("SELECT * FROM users ORDER BY created_at DESC"); +$users = $stmt->fetchAll(); +?> + +
+
+

Manage Users

+
+
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
IDUsernameEmailRoleBalanceStatusActions
+
+ + + +
+
+
+ +
+ + +
+
+
+
+ + + +
+
+ Edit +
+
+
+
+
+ + \ No newline at end of file diff --git a/cart.php b/cart.php new file mode 100644 index 0000000..7442087 --- /dev/null +++ b/cart.php @@ -0,0 +1,169 @@ +prepare("SELECT * FROM products WHERE id IN ($placeholders)"); + $stmt->execute($product_ids); + $products = $stmt->fetchAll(); + + foreach ($products as $product) { + $product_id = $product['id']; + $quantity = $_SESSION['cart'][$product_id]; + $subtotal = $product['price'] * $quantity; + $total += $subtotal; + + $cart_items[] = [ + 'id' => $product_id, + 'name' => $product['name'], + 'price' => $product['price'], + 'quantity' => $quantity, + 'subtotal' => $subtotal + ]; + } +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['update_cart'])) { + foreach ($_POST['quantities'] as $product_id => $quantity) { + if ($quantity > 0) { + $_SESSION['cart'][$product_id] = (int)$quantity; + } else { + unset($_SESSION['cart'][$product_id]); + } + } + header("Location: cart.php"); + exit; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['checkout'])) { + if (!isset($_SESSION['user_id'])) { + header("Location: login.php"); + exit; + } + + if (empty($cart_items)) { + header("Location: shop.php"); + exit; + } + + $pdo = db(); + + try { + $pdo->beginTransaction(); + + // Check if user has enough balance + $stmt = $pdo->prepare("SELECT balance FROM users WHERE id = ?"); + $stmt->execute([$_SESSION['user_id']]); + $user = $stmt->fetch(); + + if ($user['balance'] < $total) { + // Not enough balance + $pdo->rollBack(); + // Redirect to cart with an error message + header("Location: cart.php?error=balance"); + exit; + } + + // Create order + $stmt = $pdo->prepare("INSERT INTO orders (user_id, total) VALUES (?, ?)"); + $stmt->execute([$_SESSION['user_id'], $total]); + $order_id = $pdo->lastInsertId(); + + // Create order items + $stmt = $pdo->prepare("INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)"); + foreach ($cart_items as $item) { + $stmt->execute([$order_id, $item['id'], $item['quantity'], $item['price']]); + } + + // Deduct balance from user + $new_balance = $user['balance'] - $total; + $stmt = $pdo->prepare("UPDATE users SET balance = ? WHERE id = ?"); + $stmt->execute([$new_balance, $_SESSION['user_id']]); + + $pdo->commit(); + + // Clear cart + unset($_SESSION['cart']); + + // Redirect to a success page + header("Location: order_success.php?order_id=" . $order_id); + exit; + + } catch (Exception $e) { + $pdo->rollBack(); + // Log the error + error_log($e->getMessage()); + // Redirect to cart with a generic error + header("Location: cart.php?error=checkout"); + exit; + } +} +?> + +
+
+

Shopping Cart

+
+
+ +
+ +
+ + You do not have enough balance to complete this purchase. + + An error occurred during checkout. Please try again. + +
+ + + +
+

Your cart is empty.

+ Continue Shopping +
+ +
+ + + + + + + + + + + + + + + + + + + +
ProductPriceQuantitySubtotal
$ + + $
+ +
+ +

Total: $

+
+
+ +
+ +
+ +
+ + \ No newline at end of file diff --git a/chat.php b/chat.php new file mode 100644 index 0000000..3eae82c --- /dev/null +++ b/chat.php @@ -0,0 +1,121 @@ +prepare("SELECT id, username FROM users WHERE id != ?"); +$stmt->execute([$_SESSION['user_id']]); +$users = $stmt->fetchAll(); +?> + +
+
+

Chat

+
+
+ +
+
+
+
+
Users
+
+ + + + + +
+
+
+
+
+
+ Chat with prepare("SELECT username FROM users WHERE id = ?"); + $stmt->execute([$_GET['user_id']]); + $chat_user = $stmt->fetch(); + echo htmlspecialchars($chat_user['username']); + } else { + echo '...'; + } + ?> +
+
+ +
+ +
+
+
+
+ + + + \ No newline at end of file diff --git a/db/migrate.php b/db/migrate.php new file mode 100644 index 0000000..8253dec --- /dev/null +++ b/db/migrate.php @@ -0,0 +1,45 @@ +exec("CREATE TABLE IF NOT EXISTS `migrations` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `migration` VARCHAR(255) NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP + )"); + + // Get all migration files + $migrations_dir = __DIR__ . '/migrations'; + $migration_files = glob($migrations_dir . '/*.sql'); + sort($migration_files); + + // Get already run migrations + $stmt = $pdo->query("SELECT migration FROM migrations"); + $run_migrations = $stmt->fetchAll(PDO::FETCH_COLUMN); + + foreach ($migration_files as $file) { + $migration_name = basename($file); + + if (in_array($migration_name, $run_migrations)) { + continue; // Skip already run migration + } + + $sql = file_get_contents($file); + $pdo->exec($sql); + + // Record the migration + $stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)"); + $stmt->execute([$migration_name]); + + echo "Executed migration: " . $migration_name . "\n"; + } + + echo "All new migrations successful!\n"; + +} catch (PDOException $e) { + die("Migration failed: " . $e->getMessage() . "\n"); +} + diff --git a/db/migrations/000_create_migrations_table.sql b/db/migrations/000_create_migrations_table.sql new file mode 100644 index 0000000..1c7db71 --- /dev/null +++ b/db/migrations/000_create_migrations_table.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS `migrations` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `migration` VARCHAR(255) NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/db/migrations/001_create_users_table.sql b/db/migrations/001_create_users_table.sql new file mode 100644 index 0000000..a438f99 --- /dev/null +++ b/db/migrations/001_create_users_table.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS `users` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `username` VARCHAR(50) NOT NULL UNIQUE, + `email` VARCHAR(100) NOT NULL UNIQUE, + `password` VARCHAR(255) NOT NULL, + `role` ENUM('user', 'admin') NOT NULL DEFAULT 'user', + `balance` DECIMAL(10, 2) NOT NULL DEFAULT 0.00, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); \ No newline at end of file diff --git a/db/migrations/002_create_shop_tables.sql b/db/migrations/002_create_shop_tables.sql new file mode 100644 index 0000000..ced26cb --- /dev/null +++ b/db/migrations/002_create_shop_tables.sql @@ -0,0 +1,26 @@ +CREATE TABLE IF NOT EXISTS `products` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(255) NOT NULL, + `description` TEXT, + `price` DECIMAL(10, 2) NOT NULL, + `image` VARCHAR(255), + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE IF NOT EXISTS `orders` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `user_id` INT NOT NULL, + `total` DECIMAL(10, 2) NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) +); + +CREATE TABLE IF NOT EXISTS `order_items` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `order_id` INT NOT NULL, + `product_id` INT NOT NULL, + `quantity` INT NOT NULL, + `price` DECIMAL(10, 2) NOT NULL, + FOREIGN KEY (order_id) REFERENCES orders(id), + FOREIGN KEY (product_id) REFERENCES products(id) +); \ No newline at end of file diff --git a/db/migrations/003_add_status_to_users.sql b/db/migrations/003_add_status_to_users.sql new file mode 100644 index 0000000..de46985 --- /dev/null +++ b/db/migrations/003_add_status_to_users.sql @@ -0,0 +1 @@ +ALTER TABLE `users` ADD `status` ENUM('active', 'banned') NOT NULL DEFAULT 'active'; \ No newline at end of file diff --git a/db/migrations/004_create_chat_tables.sql b/db/migrations/004_create_chat_tables.sql new file mode 100644 index 0000000..3c959d9 --- /dev/null +++ b/db/migrations/004_create_chat_tables.sql @@ -0,0 +1,30 @@ +CREATE TABLE IF NOT EXISTS `messages` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `sender_id` INT NOT NULL, + `receiver_id` INT, -- For private messages + `group_id` INT, -- For group messages + `message` TEXT NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (sender_id) REFERENCES users(id), + FOREIGN KEY (receiver_id) REFERENCES users(id) + -- FOREIGN KEY (group_id) REFERENCES chat_groups(id) -- This will be added later to avoid circular dependency +); + +CREATE TABLE IF NOT EXISTS `chat_groups` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `name` VARCHAR(255) NOT NULL, + `creator_id` INT NOT NULL, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (creator_id) REFERENCES users(id) +); + +CREATE TABLE IF NOT EXISTS `chat_group_members` ( + `id` INT AUTO_INCREMENT PRIMARY KEY, + `group_id` INT NOT NULL, + `user_id` INT NOT NULL, + `role` ENUM('member', 'admin') NOT NULL DEFAULT 'member', + FOREIGN KEY (group_id) REFERENCES chat_groups(id), + FOREIGN KEY (user_id) REFERENCES users(id) +); + +ALTER TABLE `messages` ADD CONSTRAINT `fk_messages_group_id` FOREIGN KEY (`group_id`) REFERENCES `chat_groups`(`id`); diff --git a/footer.php b/footer.php new file mode 100644 index 0000000..591e0ae --- /dev/null +++ b/footer.php @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/header.php b/header.php new file mode 100644 index 0000000..2db619b --- /dev/null +++ b/header.php @@ -0,0 +1,71 @@ + + + + + + + Interactive Calculator + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/index.php b/index.php index 5eec5e4..6aea661 100644 --- a/index.php +++ b/index.php @@ -1,31 +1,4 @@ - - - - - - Interactive Calculator - - - - - - - - - - - - - - - - - - +
@@ -65,13 +38,4 @@
- - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..c648a99 --- /dev/null +++ b/login.php @@ -0,0 +1,81 @@ +prepare("SELECT * FROM users WHERE email = ?"); + $stmt->execute([$email]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password'])) { + if ($user['status'] === 'banned') { + $errors[] = 'Your account has been banned.'; + } else { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['role'] = $user['role']; + + header("Location: profile.php"); + exit; + } + } else { + $errors[] = 'Invalid email or password'; + } + } +} +?> + +
+
+

Login

+

Access your account.

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

+ +
+ +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..ec5b31a --- /dev/null +++ b/logout.php @@ -0,0 +1,6 @@ +prepare("SELECT * FROM orders WHERE id = ? AND user_id = ?"); +$stmt->execute([$order_id, $_SESSION['user_id']]); +$order = $stmt->fetch(); + +if (!$order) { + header("Location: profile.php"); + exit; +} +?> + +
+
+

Order Successful!

+

Thank you for your purchase.

+
+
+ +
+
+
+
+
+

Order Details

+

Your order # has been placed successfully.

+

Total amount: $

+ View Profile + Continue Shopping +
+
+
+
+
+ + \ No newline at end of file diff --git a/product.php b/product.php new file mode 100644 index 0000000..93528e1 --- /dev/null +++ b/product.php @@ -0,0 +1,70 @@ +prepare("SELECT * FROM products WHERE id = ?"); +$stmt->execute([$product_id]); +$product = $stmt->fetch(); + +if (!$product) { + header("Location: shop.php"); + exit; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_to_cart'])) { + $quantity = isset($_POST['quantity']) && is_numeric($_POST['quantity']) && $_POST['quantity'] > 0 ? (int)$_POST['quantity'] : 1; + + if (!isset($_SESSION['cart'])) { + $_SESSION['cart'] = []; + } + + if (isset($_SESSION['cart'][$product_id])) { + $_SESSION['cart'][$product_id] += $quantity; + } else { + $_SESSION['cart'][$product_id] = $quantity; + } + + header("Location: cart.php"); + exit; +} + +?> + +
+
+

+
+
+ +
+
+
+ <?php echo htmlspecialchars($product['name']); ?> +
+
+

+

+

$

+ +
+
+
+ + +
+
+ +
+
+
+
+ + \ No newline at end of file diff --git a/profile.php b/profile.php new file mode 100644 index 0000000..9f01c97 --- /dev/null +++ b/profile.php @@ -0,0 +1,67 @@ +prepare("SELECT * FROM users WHERE id = ?"); +$stmt->execute([$user_id]); +$user = $stmt->fetch(); + +if (!$user) { + // User not found, destroy session and redirect to login + session_destroy(); + header("Location: login.php"); + exit; +} +?> + +
+
+

Welcome, !

+

This is your profile page.

+
+
+ +
+
+
+
+
+

Profile Information

+ + + + + + + + + + + + + + + + + +
Username
Email
Role
Balance$
+ + + Admin Panel + +
+
+
+
+
+ + \ No newline at end of file diff --git a/register.php b/register.php new file mode 100644 index 0000000..0620e8e --- /dev/null +++ b/register.php @@ -0,0 +1,114 @@ +prepare("SELECT * FROM users WHERE username = ? OR email = ?"); + $stmt->execute([$username, $email]); + $existing_user = $stmt->fetch(); + + if ($existing_user) { + if ($existing_user['username'] === $username) { + $errors[] = 'Username already exists'; + } + if ($existing_user['email'] === $email) { + $errors[] = 'Email already exists'; + } + } else { + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + + $stmt = $pdo->prepare("INSERT INTO users (username, email, password) VALUES (?, ?, ?)"); + if ($stmt->execute([$username, $email, $hashed_password])) { + // Get the new user's ID + $user_id = $pdo->lastInsertId(); + + // Start session and store user info + $_SESSION['user_id'] = $user_id; + $_SESSION['username'] = $username; + $_SESSION['role'] = 'user'; // Default role + + header("Location: profile.php"); + exit; + } else { + $errors[] = 'Failed to register user. Please try again.'; + } + } + } +} +?> + +
+
+

Register

+

Create an account to get started.

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

+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/shop.php b/shop.php new file mode 100644 index 0000000..c8ee70f --- /dev/null +++ b/shop.php @@ -0,0 +1,35 @@ +query("SELECT * FROM products"); +$products = $stmt->fetchAll(); +?> + +
+
+

Shop

+

Browse our collection of amazing products.

+
+
+ +
+
+ +
+
+ <?php echo htmlspecialchars($product['name']); ?> +
+
+

+

$

+ View Product +
+
+
+ +
+
+ + \ No newline at end of file