From d581f75fd81ffd9c915acf7995efdd61790cb6a4 Mon Sep 17 00:00:00 2001 From: tharindu-dm <85168846+tharindu-dm@users.noreply.github.com> Date: Thu, 24 Oct 2024 00:44:05 +0530 Subject: [PATCH 1/2] list shows 5 different list types in 5 different tables and can swaps based on URL and secondary nav button clicks --- app/controllers/BookListController.php | 47 ++++- app/controllers/UserController.php | 2 +- app/models/BookList.php | 14 ++ app/views/error.php | 56 +----- app/views/myBookList.php | 249 +++++++++++++++++++++++++ app/views/userProfile.php | 20 +- public/css/error.css | 51 +++++ public/css/myBookList.css | 112 +++++++++++ public/css/profile.css | 4 +- public/js/myBookList.js | 87 +++++++++ 10 files changed, 579 insertions(+), 63 deletions(-) create mode 100644 app/views/myBookList.php create mode 100644 public/css/error.css create mode 100644 public/css/myBookList.css create mode 100644 public/js/myBookList.js diff --git a/app/controllers/BookListController.php b/app/controllers/BookListController.php index dba0aed..1976bcc 100644 --- a/app/controllers/BookListController.php +++ b/app/controllers/BookListController.php @@ -5,10 +5,51 @@ class BookListController extends Controller public function index() { //echo "this is the List Controller\n"; - $list = new BookList; + $URL = splitURL(); - $this->view("BookList"); //calling the view function in /includes/Controller.php to view the Listpage + if (count($URL) == 2) { + switch ($URL[1]) { + case 'Reading': + case 'Completed': + case 'Onhold': + case 'Dropped': + case 'Planned': + $this->listPage($URL[1]); + break; + default: + $this->view('error'); + break; + } + + } else { + $this->view('login'); + } + } + + private function listPage($listType) + { + if(!isset($_SESSION['user_id'])){ + $this->view('login'); + return; + } + $uid = $_SESSION['user_id']; + $Booklist = new BookList(); //List Table + + $Reading = $Booklist->getUserBookList($uid, 'reading'); + $Completed = $Booklist->getUserBookList($uid, 'completed'); + $Onhold = $Booklist->getUserBookList($uid, 'hold'); + $Dropped = $Booklist->getUserBookList($uid, 'dropped'); + $Planned = $Booklist->getUserBookList($uid, 'planned'); + + + $this->view('myBookList', [ //view the list of books + 'readingList' => $Reading, + 'completedList' => $Completed, + 'onholdList' => $Onhold, + 'droppedList' => $Dropped, + 'plannedList' => $Planned + ]); } - + } \ No newline at end of file diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php index 98535f1..7046e3d 100644 --- a/app/controllers/UserController.php +++ b/app/controllers/UserController.php @@ -9,7 +9,7 @@ public function index() if (count($URL) == 2) { switch ($URL[1]) { - case 'profile': + case 'Profile': $this->userProfile(); break; default: diff --git a/app/models/BookList.php b/app/models/BookList.php index 4f4362c..994bedd 100644 --- a/app/models/BookList.php +++ b/app/models/BookList.php @@ -28,4 +28,18 @@ public function addToList($userID, $bookID, $AddStatus) { //$chapter to be added to the list : edit the query to add the chapter to the list return $this->insert(['user' => $userID, 'book' => $bookID, 'status' => $AddStatus]); } + + public function getUserBookList($userID, $staus) + { //get the list of books of the user with the status + + $query = "SELECT b.[bookID], b.[title], l.chapterProgress, l.[status], + c.[name] AS cover_image FROM [Book] b + LEFT JOIN [BookList] l ON b.bookID = l.[book] + LEFT JOIN [CoverImage] c ON b.[coverImage] = c.covID + WHERE l.[user] = $userID AND l.[status] = '$staus';"; + + //show($query); + + return $this->query($query); + } } diff --git a/app/views/error.php b/app/views/error.php index ea07a35..21f7116 100644 --- a/app/views/error.php +++ b/app/views/error.php @@ -4,59 +4,9 @@ 404 Error - Page Not Found - - + + +
diff --git a/app/views/myBookList.php b/app/views/myBookList.php new file mode 100644 index 0000000..4e5a195 --- /dev/null +++ b/app/views/myBookList.php @@ -0,0 +1,249 @@ + + + + + + + + + Profile | Freewrite + + + + + + +
+
+
+ + + + + +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +

No books in list.

+ + +
CoverBookChapterStatusAction
Cover Image of <?= htmlspecialchars($book['title']); ?> + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

No books in list.

+ + +
CoverBookChapterStatusAction
Cover Image of <?= htmlspecialchars($book['title']); ?> + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

No books in list.

+ + +
CoverBookChapterStatusAction
Cover Image of <?= htmlspecialchars($book['title']); ?> + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

No books in list.

+ + +
CoverBookChapterStatusAction
Cover Image of <?= htmlspecialchars($book['title']); ?> + + + + +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + +

No books in list.

+ + +
CoverBookChapterStatusAction
Cover Image of <?= htmlspecialchars($book['title']); ?> + + + + +
+
+
+ + you better if you login"; + } + ?> +
+
+ + + + + + + \ No newline at end of file diff --git a/app/views/userProfile.php b/app/views/userProfile.php index ba333a2..6718183 100644 --- a/app/views/userProfile.php +++ b/app/views/userProfile.php @@ -57,23 +57,33 @@
-

Reading

+ +

Reading

+

-

Completed

+ +

Completed

+

-

On-Hold

+ +

On-Hold

+

-

Dropped

+ +

Dropped

+

-

Plan to Read

+ +

Plan to Read

+

diff --git a/public/css/error.css b/public/css/error.css new file mode 100644 index 0000000..f9ad3e1 --- /dev/null +++ b/public/css/error.css @@ -0,0 +1,51 @@ + +body { + font-family: 'Arial', sans-serif; + background-color: #f0f2f5; + display: flex; + justify-content: center; + align-items: center; + height: 100vh; + margin: 0; + color: #333; +} +.container { + text-align: center; + background-color: white; + padding: 3rem; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + max-width: 500px; +} +h1 { + font-size: 4rem; + margin: 0; + color: #e74c3c; +} +h2 { + font-size: 2rem; + margin-top: 0; +} +p { + font-size: 1.1rem; + line-height: 1.6; + margin-bottom: 2rem; +} +.btn { + display: inline-block; + padding: 0.8rem 1.5rem; + background-color: #ffd700; + color: #000; + text-decoration: none; + border-radius: 5px; + transition: background-color 0.3s ease; +} +.btn:hover { + background-color: #000; + color: #ffd700; +} +.feather { + width: 100px; + height: 100px; + margin-bottom: 2rem; +} \ No newline at end of file diff --git a/public/css/myBookList.css b/public/css/myBookList.css new file mode 100644 index 0000000..0475dae --- /dev/null +++ b/public/css/myBookList.css @@ -0,0 +1,112 @@ +/* Reset and general styles */ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: Arial, sans-serif; + line-height: 1.6; + color: #333; + background-color: #f8f8f8; +} + +/* Header and navigation styles */ +header { + background-color: #fff; + padding: 1rem; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); +} + +/* list container styles */ +main{ + min-height: 100vh; +} +/* 2nd nav bar */ + +.secondary-nav { + display: flex; + justify-content: center; + align-items: center; + padding: 1rem; + background-color: #fff; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + +} + +.table-selector { + display: flex; + justify-content: space-between; + align-items: center; +} + +.table-selector button { + margin-inline: 2rem; + padding: 0.5rem 1rem; + background-color: #ffd700; + color: #000; + border: none; + border-radius: 5px; + cursor: pointer; +} + +/*table styles*/ +.table-section { + display: flex; + justify-content: center; + align-items: center; + padding: 1rem; +} + +.table-set-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; +} + +table { + width: 100%; +} + +th, +td { + border-radius: 0.6rem; + padding: 0.5rem; + text-align: center; +} + +th { + background-color: #ffd700; + + border-spacing: 1rem; +} + +tbody tr { + background-color: #f7e78c; + border-radius: 0.6rem; + margin-bottom: 0.2rem; +} + +tbody td { + background-color: inherit; + border-radius: 0.6rem; +} + +img { + width: 90px; + height: 90px; + object-fit: cover; + border-radius: 5rem; +} + +table button { + padding: 0.5rem 1rem; + background-color: #000; + color: #ffd700; + border: none; + border-radius: 5px; + cursor: pointer; +} diff --git a/public/css/profile.css b/public/css/profile.css index ef7243e..6294cd3 100644 --- a/public/css/profile.css +++ b/public/css/profile.css @@ -18,7 +18,9 @@ header { padding: 1rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } - +main{ + min-height: 100vh; + } nav { /* Navigation styles */ } diff --git a/public/js/myBookList.js b/public/js/myBookList.js new file mode 100644 index 0000000..8585fd3 --- /dev/null +++ b/public/js/myBookList.js @@ -0,0 +1,87 @@ +const readingTable = document.getElementById("reading-table"); +const completedTable = document.getElementById("completed-table"); +const onholdTable = document.getElementById("onhold-table"); +const droppedTable = document.getElementById("dropped-table"); +const plannedTable = document.getElementById("planned-table"); + +//button +const readingBtn = document.getElementById("reading-btn"); +const completedBtn = document.getElementById("completed-btn"); +const onholdBtn = document.getElementById("onhold-btn"); +const droppedBtn = document.getElementById("dropped-btn"); +const plannedBtn = document.getElementById("planned-btn"); + +document.addEventListener("DOMContentLoaded", function () { + const url = window.location.href.split("/"); + const type = url[url.length - 1]; + console.log("URL type:", type); // Debug the extracted type + switchTable(type); +}); + +readingBtn.addEventListener("click", () => { + switchTable("Reading"); +}); + +completedBtn.addEventListener("click", () => { + switchTable("Completed"); +}); + +onholdBtn.addEventListener("click", () => { + switchTable("Onhold"); +}); + +droppedBtn.addEventListener("click", () => { + switchTable("Dropped"); +}); + +plannedBtn.addEventListener("click", () => { + switchTable("Planned"); +}); + +function switchTable(type) { + switch (type) { + case "Reading": + readingTable.style.display = "flex"; + completedTable.style.display = "none"; + onholdTable.style.display = "none"; + droppedTable.style.display = "none"; + plannedTable.style.display = "none"; + + break; + case "Completed": + readingTable.style.display = "none"; + completedTable.style.display = "flex"; + onholdTable.style.display = "none"; + droppedTable.style.display = "none"; + plannedTable.style.display = "none"; + break; + case "Onhold": + readingTable.style.display = "none"; + completedTable.style.display = "none"; + onholdTable.style.display = "flex"; + droppedTable.style.display = "none"; + plannedTable.style.display = "none"; + break; + case "Dropped": + readingTable.style.display = "none"; + completedTable.style.display = "none"; + onholdTable.style.display = "none"; + droppedTable.style.display = "flex"; + plannedTable.style.display = "none"; + break; + case "Planned": + readingTable.style.display = "none"; + completedTable.style.display = "none"; + onholdTable.style.display = "none"; + droppedTable.style.display = "none"; + plannedTable.style.display = "flex"; + break; + default: + readingTable.style.display = "flex"; + completedTable.style.display = "none"; + onholdTable.style.display = "none"; + droppedTable.style.display = "none"; + plannedTable.style.display = "none"; + break; + } +} From a51d4b4be5b38122d104407e06ce47a831e8626c Mon Sep 17 00:00:00 2001 From: tharindu-dm <85168846+tharindu-dm@users.noreply.github.com> Date: Thu, 24 Oct 2024 02:17:28 +0530 Subject: [PATCH 2/2] Book List CRUD implemented --- app/controllers/BookController.php | 34 ++++++++-- app/models/BookList.php | 19 ++++++ app/views/myBookList.php | 95 +++++++++++++++++++++++--- public/css/myBookList.css | 104 ++++++++++++++++++++++++++++- public/js/myBookList.js | 68 +++++++++++++++++++ 5 files changed, 303 insertions(+), 17 deletions(-) diff --git a/app/controllers/BookController.php b/app/controllers/BookController.php index 1a2a067..b3cab71 100644 --- a/app/controllers/BookController.php +++ b/app/controllers/BookController.php @@ -19,7 +19,6 @@ public function index() } else { $this->view('error'); } - break; case 'Chapter': @@ -28,11 +27,20 @@ public function index() } else { $this->view('error'); } - break; case 'List': - $this->addToList($_POST['List_uid'], $_POST['List_bid'], $_POST['list']); + switch ($URL[2]) { + case 'update': + $this->updateList($_POST['List_bid'], $_POST['chapterCount'], $_POST['status']); + break; + case 'delete': + $this->deleteFromList($_POST['List_bid']); + break; + default: + $this->addToList($_POST['List_uid'], $_POST['List_bid'], $_POST['list']); + break; + } break; default: $this->view('error'); @@ -63,7 +71,25 @@ private function viewChapter($chapterID) private function addToList($uid, $bookID, $status) { $list = new BookList(); //get chapter to be added to the list - $list->addToList($uid,$bookID, $status); + $list->addToList($uid, $bookID, $status); + $this->viewBook($bookID); + } + + private function updateList($bookID, $chapterCount, $BookStatus) + { + $list = new BookList(); + + $uid = $_SESSION['user_id']; + $list->updateList($uid, $bookID, $chapterCount, $BookStatus); + $this->viewBook($bookID); + } + + private function deleteFromList($bookID) + { + $list = new BookList(); + + $uid = $_SESSION['user_id']; + $list->deleteFromList($uid, $bookID); $this->viewBook($bookID); } } \ No newline at end of file diff --git a/app/models/BookList.php b/app/models/BookList.php index 994bedd..ad5a708 100644 --- a/app/models/BookList.php +++ b/app/models/BookList.php @@ -42,4 +42,23 @@ public function getUserBookList($userID, $staus) return $this->query($query); } + + + public function updateList($uid, $bid, $chaps, $status) + { + $query = "UPDATE [BookList] SET [chapterProgress] = $chaps, [status] = '$status' WHERE [user] = $uid AND [book] = $bid;"; + + //show($query); + + return $this->query($query); + } + + public function deleteFromList($uid, $bid) + { + $query = "DELETE FROM [BookList] WHERE [user] = $uid AND [book] = $bid;"; + + //show($query); + + return $this->query($query); + } } diff --git a/app/views/myBookList.php b/app/views/myBookList.php index 4e5a195..9285eae 100644 --- a/app/views/myBookList.php +++ b/app/views/myBookList.php @@ -53,13 +53,17 @@ Book Chapter Status - Action + Action - + + Cover Image of <?= htmlspecialchars($book['title']); ?> @@ -72,6 +76,7 @@ + @@ -90,13 +95,16 @@ Book Chapter Status - Action + Action - + Cover Image of <?= htmlspecialchars($book['title']); ?> @@ -109,6 +117,7 @@ + @@ -127,13 +136,16 @@ Book Chapter Status - Action + Action - + Cover Image of <?= htmlspecialchars($book['title']); ?> @@ -146,6 +158,7 @@ + @@ -164,13 +177,16 @@ Book Chapter Status - Action + Action - + Cover Image of <?= htmlspecialchars($book['title']); ?> @@ -183,6 +199,7 @@ + @@ -201,13 +218,16 @@ Book Chapter Status - Action + Action - + Cover Image of <?= htmlspecialchars($book['title']); ?> @@ -220,6 +240,7 @@ + @@ -231,6 +252,60 @@
+
+
+

Edit Record

+

Title:

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

You are about to delete

+

Title:

+ +
+ + + +
+ + +
+
+
+
+ you better if you login"; diff --git a/public/css/myBookList.css b/public/css/myBookList.css index 0475dae..f336aa1 100644 --- a/public/css/myBookList.css +++ b/public/css/myBookList.css @@ -12,6 +12,7 @@ body { background-color: #f8f8f8; } +/* ------------------------------------------------------------------------------ */ /* Header and navigation styles */ header { background-color: #fff; @@ -20,7 +21,7 @@ header { } /* list container styles */ -main{ +main { min-height: 100vh; } /* 2nd nav bar */ @@ -32,7 +33,6 @@ main{ padding: 1rem; background-color: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - } .table-selector { @@ -51,6 +51,7 @@ main{ cursor: pointer; } +/* ------------------------------------------------------------------------------ */ /*table styles*/ .table-section { display: flex; @@ -102,7 +103,7 @@ img { border-radius: 5rem; } -table button { +.listEdit-btn { padding: 0.5rem 1rem; background-color: #000; color: #ffd700; @@ -110,3 +111,100 @@ table button { border-radius: 5px; cursor: pointer; } + +.listDelete-btn { + padding: 0.5rem 1rem; + background-color: #ff0000; + color: #ffd700; + border: none; + border-radius: 5px; + cursor: pointer; +} + +/* ------------------------------------------------------------------------------ */ +/*EDITING to my booklist */ +.add-to-list { + display: none; + position: fixed; /* Make it fixed to the viewport */ + top: 0; + left: 0; + width: 100vw; /* Full width of the viewport */ + height: 100vh; /* Full height of the viewport */ + background: rgba(0, 0, 0, 0.6); /* Adjust the opacity of the background */ + + justify-content: center; /* Center the form horizontally */ + align-items: center; /* Center the form vertically */ + z-index: 1; +} + +.list-add-container { + display: flex; + flex-direction: column; + max-width: fit-content; + background-color: #fff; + padding: 2rem; + border-radius: 1rem; + z-index: 2; +} + +.form-content { + display: flex; + flex-direction: column; + gap: 10px; +} + +.chapter-counter { + display: flex; + gap: 10px; +} + +.status-content { + display: flex; + flex-direction: column; + margin-bottom: 4rem; +} + +.list-add-actionBtns { + display: flex; + gap: 10px; + margin-top: 10px; + justify-content: center; +} + +.add-list-cancel-button { + background-color: #535353; + color: #fff; + padding: 0.5rem 2rem 0.5rem 2rem; + border-radius: 0.5rem; +} + +.add-list-submit-button { + background-color: #ffd700; + color: #000; + padding: 0.5rem 2rem 0.5rem 2rem; + border-radius: 0.5rem; +} + +/* ------------------------------------------------------------------------------ */ +/*DELETE Record*/ +.delete-from-list{ + display: none; + position: fixed; /* Make it fixed to the viewport */ + top: 0; + left: 0; + width: 100vw; /* Full width of the viewport */ + height: 100vh; /* Full height of the viewport */ + background: rgba(0, 0, 0, 0.6); /* Adjust the opacity of the background */ + + justify-content: center; /* Center the form horizontally */ + align-items: center; /* Center the form vertically */ + z-index: 1; +} + +.delete-list-submit-button { + background-color: #ff0000; + color: #000; + font-weight: 600; + padding: 0.5rem 2rem 0.5rem 2rem; + border-radius: 0.5rem; +} \ No newline at end of file diff --git a/public/js/myBookList.js b/public/js/myBookList.js index 8585fd3..9b2cb3a 100644 --- a/public/js/myBookList.js +++ b/public/js/myBookList.js @@ -85,3 +85,71 @@ function switchTable(type) { break; } } + +/////////////////////////////////////////////////////////////////////////////////// +const cancelBtn = document.getElementById("cancel-button"); //in the overlay +const overlay = document.querySelector(".add-to-list"); + +document.addEventListener("click", function (e) { + if (e.target && e.target.classList.contains("listEdit-btn")) { + // Get the parent tr element + const row = e.target.closest("tr"); + + // Get the data from data attributes + const bookId = row.dataset.bookId; + const bookTitle = row.dataset.bookTitle; + const chapterCount = row.dataset.chapterProgress; + const getBookStatus = row.dataset.status; + + // Set the values in the inputs + const bookID_input = document.getElementById("List_bid"); + const bookTitle_header = document.getElementById("bookTitle-header"); + const chapterCounter = document.getElementById("chapterCount"); + const bookStatus_Select = document.getElementById("status-select"); + + bookID_input.value = bookId; + bookTitle_header.innerHTML = bookTitle; + chapterCounter.value = chapterCount; + bookStatus_Select.value = getBookStatus; + + // Toggle the overlay display + overlay.style.display = overlay.style.display !== "flex" ? "flex" : "none"; + } +}); + +cancelBtn.addEventListener("click", (e) => { + e.preventDefault(); // Prevent the default action + + overlay.style.display = "none"; +}); + +/////////////////////////////////////////////////////////////////////////////////// +const cancelBtn_delete = document.getElementById("cancel-delete-button"); //in the overlay +const overlay_delete = document.querySelector(".delete-from-list"); + +document.addEventListener("click", function (e) { + if (e.target && e.target.classList.contains("listDelete-btn")) { + // Get the parent tr element + const row = e.target.closest("tr"); + + // Get the data from data attributes + const bookId = row.dataset.bookId; + const bookTitle = row.dataset.bookTitle; + + // Set the values in the inputs + const bookID_input = document.getElementById("List_bid_delete"); + const bookTitle_header = document.getElementById("bookTitle-header-delete"); + + bookID_input.value = bookId; + bookTitle_header.innerHTML = bookTitle; + + // Toggle the overlay display + overlay_delete.style.display = overlay_delete.style.display !== "flex" ? "flex" : "none"; + } + }); + +cancelBtn_delete.addEventListener("click", (e) => { + e.preventDefault(); // Prevent the default action + + overlay_delete.style.display = "none"; +});