Skip to content

Commit

Permalink
Completes the initial version of the project
Browse files Browse the repository at this point in the history
  • Loading branch information
jesusgraterol committed Oct 3, 2023
1 parent b1803a3 commit 4f74d67
Show file tree
Hide file tree
Showing 8 changed files with 1,047 additions and 82 deletions.
126 changes: 104 additions & 22 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,36 +1,118 @@
<!DOCTYPE html>
<html lang="en">
<head>

<!-- Charset -->
<meta charset="UTF-8">
<head>

<!-- Viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Charset -->
<meta charset="UTF-8">

<!-- Title -->
<title>Library</title>
<!-- Viewport -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">
<!-- Title -->
<title>Library</title>

<!-- Theme Color -->
<meta name="theme-color" content="#000000">
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico">

<!-- Stylesheet -->
<link rel="stylesheet" href="stylesheets/app.css">
<!-- Theme Color -->
<meta name="theme-color" content="#000000">

<!-- Script -->
<script type="module" src="scripts/app.js" defer></script>
<!-- Stylesheet -->
<link rel="stylesheet" href="stylesheets/app.css">

</head>
<body>

<!-- App Container -->
<div class="app-container">
<!-- Script -->
<script type="module" src="scripts/app.js" defer></script>

</head>
<body>

<!-- App Container -->
<div class="app-container">

</div>
<!-- Header -->
<header>

<span class="md-icon md-48">book_2</span>

<h1>Library</h1>

<button id="add_book_button">ADD BOOK</button>

</header>

<!-- Spinner Container -->
<div id="spinner_container">
<div class="lds-ring"><div></div><div></div><div></div><div></div></div>
</div>


<!-- No Data Found -->
<p id="no_data_found">No books were found</p>

<!-- Main Container -->
<main id="main"><!-- Handled by books.js --></main>


<!-- Form Modal -->
<dialog id="modal" class="form">

<div class="header">
<p>Book Form</p>
<a href="javascript:;" id="modal_close_button" tabindex="-1">
<span class="md-icon">close</span>
</a>
</div>

<form id="form" novalidate>

<div class="form-row">
<div class="form-control">
<label for="author" id="author_label">Author*
<input type="text" name="author" id="author" autofocus>
</label>
<p id="author_error" class="error">
<span class="md-icon">error</span> Enter a valid author
</p>
</div>
</div>

<div class="form-row">
<div class="form-control">
<label for="name" id="name_label">Name*
<input type="text" name="name" id="name">
</label>
<p id="name_error" class="error">
<span class="md-icon">error</span> Enter a valid name
</p>
</div>
</div>

<div class="form-row">
<div class="form-control">
<label for="description" id="description_label">Description*
<textarea name="description" id="description"></textarea>
</label>
<p id="description_error" class="error">
<span class="md-icon">error</span> Enter a valid description
</p>
</div>
</div>

<button type="submit" id="submit_button" disabled>ADD BOOK</button>
</form>

</dialog>



<!-- Toastr -->
<div id="toastr" class="toastr">
<span class="md-icon" id="toastr_icon"></span> <p id="toastr_text"></p>
</div>

</div>

</body>

</body>
</html>
205 changes: 203 additions & 2 deletions scripts/app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FormGroup } from "./modules/form_group.js";
import { Modal } from "./modules/modal.js";

import { Toastr } from "./modules/toastr.js";
import { Books } from "./modules/books.js";

/**
* App
Expand All @@ -11,13 +12,213 @@ class App {
// The FormGroup Instace
#form;

// Modal
// The Modal Instance
#modal;

// The Toastr Instance
#toastr;

// The Books Instance
#books;

// The element of the spinner
#spinner_el;


constructor() {
// Initialize the Form Group Instance
this.#form = this.#build_form_group();

// Initialize the Modal Instance
this.#modal = new Modal();

// Initialize the Toastr Instance
this.#toastr = new Toastr();

// Initialize the Books Instance
this.#books = new Books();

// Subscribe to the click events on the dom
document.addEventListener( "click", (e) => this.#on_click_event(e) );

// Initialize the element of the spinner
this.#spinner_el = document.getElementById("spinner_container");

// Subscribe to the form submission event and handle it
this.#form.el.addEventListener("submit", (e) => this.#on_form_submission(e));

// Initialize the app
this.#on_init();
}








/*******************
* App Initializer *
*******************/



/**
* Initializes the loading of the app, mainly the Books Module.
* @returns Promise<void>
*/
async #on_init() {
// Display the spinner
this.#show_spinner();

// Initialize the books
try {
await this.#books.initialize();

// Finally, hide the spinner
this.#hide_spinner();
} catch (e) { this.#toastr.error(e) }
}











/******************
* Event Handlers *
******************/





/**
* Triggers whenever an element in the dom is clicked.
* @param e
* @returns Promise<void>
*/
async #on_click_event(e) {
// Handle a click on the add book button
if (e.target.id == "add_book_button") {
this.#form.reset();
this.#modal.show();
}

// Handle a click on a toggle read button
else if (e.target.id.includes("toggle-read-state")) {
try {
await this.#books.toggle_read_state(e.target.id.split("_")[1]);
this.#toastr.info("The book's read state has been toggled successfully.");
} catch (e) { this.#toastr.error(e) }
}

// Handle a click on a delete button
else if (e.target.id.includes("delete")) {
try {
await this.#books.delete_book(e.target.id.split("_")[1]);
this.#toastr.success("The book has been deleted successfully.");
} catch (e) { this.#toastr.error(e) }
}
}





/**
* Triggers whenever the form is submitted. Handles the creation of a new book.
* @param e
* @returns Promise<void>
*/
async #on_form_submission(e) {
// Cancel the default behavior
e.preventDefault();

// Trigger the submission if the form is valid
if (this.#form.valid) {
try {
// Set submission state
this.#form.submission_started();

// Add the book to the db
const values = this.#form.build_control_values();
await this.#books.add_book(values.author, values.name, values.description);

// Close the dialog and reset the form
this.#form.submission_ended();
this.#form.reset();
this.#modal.close();
} catch (e) { this.#toastr.error(e) }
}
}











/****************
* Misc Helpers *
****************/





/**
* Builds the form group instance for all the book inputs.
* @returns FormGroup
*/
#build_form_group() {
return new FormGroup("form", [
{
id: "author",
validate_function: (control_values) => {
return typeof control_values["author"] == "string" &&
/^[a-zA-Z ]{2,30}$/.test(control_values["author"]);
}
},
{
id: "name",
validate_function: (control_values) => {
return typeof control_values["name"] == "string" &&
control_values["name"].length >= 2 &&
control_values["name"].length <= 200;
}
},
{
id: "description",
validate_function: (control_values) => {
return typeof control_values["description"] == "string" &&
control_values["description"].length >= 10 &&
control_values["description"].length <= 500;
}
},
]);
}






/**
* Shows and hides the spinner accordingly.
*/
#show_spinner() { this.#spinner_el.style.display = "block" }
#hide_spinner() { this.#spinner_el.style.display = "none" }
}


Expand Down
Loading

0 comments on commit 4f74d67

Please sign in to comment.