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 = '
Book added to your library! View your library.
'; + } + + } 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.

+ + + +
+
Search Google Books
+
+
+
+ + +
+
+
+
+ + +
+
Search Results
+
+
+ + +
+
+
+ Cover for <?php echo htmlspecialchars($title); ?> +
+
+
+

by

+

...

+
+ + + + + + +
+
+
+
+ +
+
+
+ + +
+ + 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;

+ +
+
Pending Applications
+
+ + + + + + + + + + + + + + + + + + + + + + + +
UsernameBioAction
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.
+ +
+
+ Writer Application +
+
+

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; +} + +?> + + +
+
+

+
by
+

+
+
+ + 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 @@ + + + + \ No newline at end of file diff --git a/header.php b/header.php new file mode 100644 index 0000000..b3abf9a --- /dev/null +++ b/header.php @@ -0,0 +1,52 @@ + + + + + + + Virtual Library + + + + +
\ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..aa19648 100644 --- a/index.php +++ b/index.php @@ -1,150 +1,49 @@ query("SELECT b.id, b.title, b.author_name, b.added_by_user_id, u.username FROM books b LEFT JOIN users u ON b.added_by_user_id = u.id ORDER BY b.created_at DESC LIMIT 5"); +$recent_books = $stmt->fetchAll(); -$phpVersion = PHP_VERSION; -$now = date('Y-m-d H:i:s'); ?> - - - - - - New Style - - - - - - - - - - - - - - - - - - - - - -
-
-

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

+ +
+
+

Welcome to the Virtual Library

+

Your personal space to discover, organize, and share books.

+ + Get Started + + Go to Your Library +
-
- - - + +
+
+

Recently Added Books

+ 0): ?> +
+ + +
+
+
+

by + + + + + +

+ + +
+ +

No books have been added yet. Be the first!

+ +
+
+
+ + diff --git a/library.php b/library.php new file mode 100644 index 0000000..b46c532 --- /dev/null +++ b/library.php @@ -0,0 +1,108 @@ +prepare("SELECT id FROM books WHERE title = :title AND author_name = :author_name"); + $stmt->execute(['title' => $title, 'author_name' => $author_name]); + $book = $stmt->fetch(); + + if ($book) { + $book_id = $book['id']; + } else { + // Insert new book + $stmt = db()->prepare("INSERT INTO books (title, author_name, added_by_user_id) VALUES (:title, :author_name, :user_id)"); + $stmt->execute(['title' => $title, 'author_name' => $author_name, '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 = '
Book added to your library!
'; + } + } catch (PDOException $e) { + $message = '
Error: ' . $e->getMessage() . '
'; + } + } else { + $message = '
Please enter both title and author.
'; + } +} + +// Fetch user's books +$stmt = db()->prepare("SELECT b.id, b.title, b.author_name FROM books b JOIN user_libraries ul ON b.id = ul.book_id WHERE ul.user_id = :user_id ORDER BY b.title"); +$stmt->execute(['user_id' => $user_id]); +$user_books = $stmt->fetchAll(); + +?> + +
+

My Library

+

Welcome, !

+ + + +
+
+ Add a New Book Manually +
+
+

You can also search and add books automatically.

+
+
+ + +
+
+ + +
+ +
+
+
+ +
+
+ Your Books +
+
+ 0): ?> +
    + +
  • + + by +
  • + +
+ +

You haven't added any books yet.

+ +
+
+
+ + \ No newline at end of file diff --git a/login.php b/login.php new file mode 100644 index 0000000..899c79f --- /dev/null +++ b/login.php @@ -0,0 +1,44 @@ +prepare("SELECT * FROM users WHERE email = ?"); + $stmt->execute([$email]); + $user = $stmt->fetch(); + + if ($user && password_verify($password, $user['password_hash'])) { + $_SESSION['user_id'] = $user['id']; + $_SESSION['username'] = $user['username']; + $_SESSION['user_role'] = $user['role']; + header("Location: index.php"); + exit; + } else { + $message = '
Invalid email or password.
'; + } +} +?> + + +

Login

+ +
+
+ + +
+
+ + +
+ +
+ + \ No newline at end of file diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..3a0a043 --- /dev/null +++ b/logout.php @@ -0,0 +1,7 @@ + \ No newline at end of file diff --git a/signup.php b/signup.php new file mode 100644 index 0000000..9d55edb --- /dev/null +++ b/signup.php @@ -0,0 +1,58 @@ +Passwords do not match.'; + } else { + $pdo = db(); + + $stmt = $pdo->prepare("SELECT * FROM users WHERE email = ?"); + $stmt->execute([$email]); + if ($stmt->fetch()) { + $message = '
Email already registered.
'; + } else { + $hashed_password = password_hash($password, PASSWORD_DEFAULT); + + $stmt = $pdo->prepare("INSERT INTO users (username, email, password_hash, role) VALUES (?, ?, ?, 'member')"); + if ($stmt->execute([$username, $email, $hashed_password])) { + $message = '
Registration successful! You can now login.
'; + } else { + $message = '
Registration failed. Please try again.
'; + } + } + } +} +?> + + +

Sign Up

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