diff --git a/add_book.php b/add_book.php
new file mode 100644
index 0000000..af9ca3d
--- /dev/null
+++ b/add_book.php
@@ -0,0 +1,153 @@
+Could not connect to Google Books API.';
+ }
+ } elseif (empty($search_query)) {
+ $message = '
Please enter a search term.
';
+ } else {
+ $message = 'Google Books API key is not configured. Please ask the administrator to set it up.
';
+ }
+}
+
+// Handle Add Book from Google Books
+if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['add_google_book'])) {
+ $title = trim($_POST['title']);
+ $author_name = trim($_POST['author']);
+ $google_books_id = trim($_POST['google_books_id']);
+ $description = trim($_POST['description']);
+ $cover_image_url = trim($_POST['cover_image_url']);
+
+ if (!empty($title) && !empty($author_name)) {
+ try {
+ // Check if book with this Google ID already exists
+ $stmt = db()->prepare("SELECT id FROM books WHERE google_books_id = :google_books_id");
+ $stmt->execute(['google_books_id' => $google_books_id]);
+ $book = $stmt->fetch();
+
+ if ($book) {
+ $book_id = $book['id'];
+ } else {
+ // Insert new book
+ $stmt = db()->prepare(
+ "INSERT INTO books (title, author_name, description, cover_image_url, google_books_id, added_by_user_id)
+ VALUES (:title, :author_name, :description, :cover_image_url, :google_books_id, :user_id)"
+ );
+ $stmt->execute([
+ 'title' => $title,
+ 'author_name' => $author_name,
+ 'description' => $description,
+ 'cover_image_url' => $cover_image_url,
+ 'google_books_id' => $google_books_id,
+ 'user_id' => $user_id
+ ]);
+ $book_id = db()->lastInsertId();
+ }
+
+ // Check if the book is already in the user's library
+ $stmt = db()->prepare("SELECT * FROM user_libraries WHERE user_id = :user_id AND book_id = :book_id");
+ $stmt->execute(['user_id' => $user_id, 'book_id' => $book_id]);
+ if ($stmt->fetch()) {
+ $message = 'This book is already in your library.
';
+ } else {
+ // Add book to user's library
+ $stmt = db()->prepare("INSERT INTO user_libraries (user_id, book_id) VALUES (:user_id, :book_id)");
+ $stmt->execute(['user_id' => $user_id, 'book_id' => $book_id]);
+ $message = '';
+ }
+
+ } catch (PDOException $e) {
+ $message = 'Database Error: ' . $e->getMessage() . '
';
+ }
+ } else {
+ $message = 'Title and Author are required.
';
+ }
+}
+
+?>
+
+
+
Add Book from Google
+
Search for a book to add it to your library automatically.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
; ?>)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/admin.php b/admin.php
new file mode 100644
index 0000000..01a7353
--- /dev/null
+++ b/admin.php
@@ -0,0 +1,93 @@
+prepare("UPDATE writer_applications SET status = 'approved' WHERE id = ?");
+ $stmt->execute([$application_id]);
+
+ // Update user role
+ $stmt = $pdo->prepare("UPDATE users SET role = 'writer' WHERE id = ?");
+ $stmt->execute([$user_id]);
+
+ $message = 'Application approved. User is now a writer.
';
+ } elseif (isset($_POST['reject'])) {
+ // Update application status
+ $stmt = $pdo->prepare("UPDATE writer_applications SET status = 'rejected' WHERE id = ?");
+ $stmt->execute([$application_id]);
+
+ $message = 'Application rejected.
';
+ }
+}
+
+// Fetch pending applications
+$stmt = $pdo->prepare("SELECT wa.*, u.username FROM writer_applications wa JOIN users u ON wa.user_id = u.id WHERE wa.status = 'pending'");
+$stmt->execute();
+$applications = $stmt->fetchAll();
+
+?>
+
+
+Admin Panel - Writer Applications
+
+
+
+To test this page, you need to manually set a user's role to 'admin' in your database. For example:
UPDATE users SET role = 'admin' WHERE id = 1;
+
+
+
+
+
+
+
+ | Username |
+ Bio |
+ Action |
+
+
+
+
+
+ | No pending applications. |
+
+
+
+
+ |
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
diff --git a/apply_writer.php b/apply_writer.php
new file mode 100644
index 0000000..4b8fb8a
--- /dev/null
+++ b/apply_writer.php
@@ -0,0 +1,79 @@
+prepare("SELECT is_writer FROM users WHERE id = :user_id");
+$stmt->execute(['user_id' => $user_id]);
+$is_writer = $stmt->fetchColumn();
+
+$stmt = db()->prepare("SELECT status FROM writer_applications WHERE user_id = :user_id");
+$stmt->execute(['user_id' => $user_id]);
+$application = $stmt->fetch();
+
+if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['apply'])) {
+ if (!$is_writer && (!$application || $application['status'] == 'rejected')) {
+ $bio = trim($_POST['bio']);
+ if (!empty($bio)) {
+ try {
+ $stmt = db()->prepare("INSERT INTO writer_applications (user_id, bio, status) VALUES (:user_id, :bio, 'pending') ON DUPLICATE KEY UPDATE bio = :bio, status = 'pending'");
+ $stmt->execute(['user_id' => $user_id, 'bio' => $bio]);
+ $message = 'Your application has been submitted for review.
';
+ // Refresh application status
+ $stmt = db()->prepare("SELECT status FROM writer_applications WHERE user_id = :user_id");
+ $stmt->execute(['user_id' => $user_id]);
+ $application = $stmt->fetch();
+ } catch (PDOException $e) {
+ $message = 'Error: ' . $e->getMessage() . '
';
+ }
+ } else {
+ $message = 'Please provide a short bio or reason for your application.
';
+ }
+ }
+}
+
+?>
+
+
+
Become a Writer
+
+
+
+
+
You are already a writer.
+
+
You have a pending application. Please wait for an admin to review it.
+
+
Your application was approved! You are now a writer.
+
+
+
Your previous application was rejected. You may reapply with more information.
+
+
+
+
+
Tell us a bit about yourself and why you'd like to be a writer on our platform.
+
+
+
+
+
+
+
diff --git a/assets/pasted-20251108-120139-9f8bf321.png b/assets/pasted-20251108-120139-9f8bf321.png
new file mode 100644
index 0000000..e335496
Binary files /dev/null and b/assets/pasted-20251108-120139-9f8bf321.png differ
diff --git a/author.php b/author.php
new file mode 100644
index 0000000..9b6697e
--- /dev/null
+++ b/author.php
@@ -0,0 +1,69 @@
+prepare("SELECT u.username, wa.bio FROM users u LEFT JOIN writer_applications wa ON u.id = wa.user_id WHERE u.id = ? AND u.role = 'writer'");
+$stmt->execute([$author_id]);
+$author = $stmt->fetch();
+
+if (!$author) {
+ // Redirect if not a writer or doesn't exist
+ // You might want to show a generic "user not found" page instead
+ header("Location: index.php");
+ exit;
+}
+
+// Fetch author's books, assuming the user who added the book is the author
+$stmt = $pdo->prepare("SELECT id, title, author_name, description FROM books WHERE added_by_user_id = ? ORDER BY created_at DESC");
+$stmt->execute([$author_id]);
+$books = $stmt->fetchAll();
+
+?>
+
+
+
+
+
Books by
+
+
+
+
+
This author has not published any books yet.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/book.php b/book.php
new file mode 100644
index 0000000..2c33a13
--- /dev/null
+++ b/book.php
@@ -0,0 +1,36 @@
+prepare("SELECT b.*, u.username FROM books b JOIN users u ON b.user_id = u.id WHERE b.id = ?");
+$stmt->execute([$book_id]);
+$book = $stmt->fetch();
+
+if (!$book) {
+ // Redirect if book doesn't exist
+ header("Location: index.php");
+ exit;
+}
+
+?>
+
+
+
+
+
diff --git a/db/config.php b/db/config.php
index 67f37e2..7f77a11 100644
--- a/db/config.php
+++ b/db/config.php
@@ -5,6 +5,10 @@ define('DB_NAME', 'app_35570');
define('DB_USER', 'app_35570');
define('DB_PASS', 'ea95d2df-6283-4025-8109-636b56cb9418');
+// Define your Google Books API key here.
+// You can obtain a key from the Google Cloud Console: https://console.cloud.google.com/apis/library/books.googleapis.com
+define('GOOGLE_BOOKS_API_KEY', 'YOUR_GOOGLE_BOOKS_API_KEY');
+
function db() {
static $pdo;
if (!$pdo) {
@@ -14,4 +18,4 @@ function db() {
]);
}
return $pdo;
-}
+}
\ No newline at end of file
diff --git a/db/migrate.php b/db/migrate.php
new file mode 100644
index 0000000..0778e06
--- /dev/null
+++ b/db/migrate.php
@@ -0,0 +1,12 @@
+exec($sql);
+ echo "Database migration completed successfully.\n";
+} catch (PDOException $e) {
+ die("Database migration failed: " . $e->getMessage() . "\n");
+}
+
diff --git a/db/migrations/001_initial_schema.sql b/db/migrations/001_initial_schema.sql
new file mode 100644
index 0000000..0772e32
--- /dev/null
+++ b/db/migrations/001_initial_schema.sql
@@ -0,0 +1,72 @@
+-- 001_initial_schema.sql
+
+-- Users table for members and admins
+CREATE TABLE IF NOT EXISTS `users` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `username` VARCHAR(255) NOT NULL UNIQUE,
+ `email` VARCHAR(255) NOT NULL UNIQUE,
+ `password_hash` VARCHAR(255) NOT NULL,
+ `role` ENUM('member', 'admin', 'writer') NOT NULL DEFAULT 'member',
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- Writer applications table
+CREATE TABLE IF NOT EXISTS `writer_applications` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `user_id` INT NOT NULL,
+ `gov_id_path` VARCHAR(255) NOT NULL,
+ `work_proof_path` VARCHAR(255) NOT NULL,
+ `status` ENUM('pending', 'approved', 'rejected') NOT NULL DEFAULT 'pending',
+ `requested_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ `reviewed_at` TIMESTAMP NULL DEFAULT NULL,
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- Books table
+CREATE TABLE IF NOT EXISTS `books` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `title` VARCHAR(255) NOT NULL,
+ `author_name` VARCHAR(255) NOT NULL,
+ `description` TEXT,
+ `cover_image_url` VARCHAR(255),
+ `google_books_id` VARCHAR(255) UNIQUE,
+ `open_library_id` VARCHAR(255) UNIQUE,
+ `added_by_user_id` INT,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (`added_by_user_id`) REFERENCES `users`(`id`) ON DELETE SET NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- User libraries table (connecting users and books)
+CREATE TABLE IF NOT EXISTS `user_libraries` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `user_id` INT NOT NULL,
+ `book_id` INT NOT NULL,
+ `review` TEXT,
+ `character_sketches` TEXT,
+ `added_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`book_id`) REFERENCES `books`(`id`) ON DELETE CASCADE,
+ UNIQUE KEY `user_book_unique` (`user_id`, `book_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- Author followers table
+CREATE TABLE IF NOT EXISTS `author_followers` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `follower_id` INT NOT NULL,
+ `author_id` INT NOT NULL,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (`follower_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`author_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
+ UNIQUE KEY `follower_author_unique` (`follower_id`, `author_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- Library likes table
+CREATE TABLE IF NOT EXISTS `library_likes` (
+ `id` INT AUTO_INCREMENT PRIMARY KEY,
+ `liker_id` INT NOT NULL,
+ `library_owner_id` INT NOT NULL,
+ `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
+ FOREIGN KEY (`liker_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
+ FOREIGN KEY (`library_owner_id`) REFERENCES `users`(`id`) ON DELETE CASCADE,
+ UNIQUE KEY `liker_owner_unique` (`liker_id`, `library_owner_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
diff --git a/db/migrations/002_add_role_to_users.sql b/db/migrations/002_add_role_to_users.sql
new file mode 100644
index 0000000..3a9b9ed
--- /dev/null
+++ b/db/migrations/002_add_role_to_users.sql
@@ -0,0 +1 @@
+ALTER TABLE users ADD COLUMN role VARCHAR(255) NOT NULL DEFAULT 'user';
diff --git a/db/migrations/003_add_description_to_books.sql b/db/migrations/003_add_description_to_books.sql
new file mode 100644
index 0000000..5d64672
--- /dev/null
+++ b/db/migrations/003_add_description_to_books.sql
@@ -0,0 +1 @@
+ALTER TABLE books ADD COLUMN description TEXT;
diff --git a/footer.php b/footer.php
new file mode 100644
index 0000000..7cf63f8
--- /dev/null
+++ b/footer.php
@@ -0,0 +1,4 @@
+
+
+