diff --git a/bank-solution/.vscode/settings.json b/bank-solution/.vscode/settings.json
new file mode 100644
index 0000000..6f3a291
--- /dev/null
+++ b/bank-solution/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "liveServer.settings.port": 5501
+}
\ No newline at end of file
diff --git a/bank-solution/app.js b/bank-solution/app.js
new file mode 100644
index 0000000..3b55b68
--- /dev/null
+++ b/bank-solution/app.js
@@ -0,0 +1,253 @@
+//Create a variable which stores the logged-in user's details, with initial value as none indicating no user is logged in.
+//We need a private space to store all the user details who have created their accounts. These details are stored and used to retrieve the account details.
+
+let state = Object.freeze({
+ account: null
+});
+const api = '//localhost:5000/api/accounts/';
+const storageKey = 'savedAccount';
+
+//We need to create an array which would hold all the required ids and titles of each template which would help in navigation.
+
+const routes = {
+ '/login': {
+ templateId: 'login' ,
+ title: 'Login Page'
+ },
+ '/dashboard': {
+ templateId: 'dashboard',
+ title: 'Dashboard',
+ init: refresh
+ },
+ '/credits': {
+ templateId: 'credits',
+ title: 'credits'
+ },
+};
+
+
+
+
+//templateId: The ID of the HTML template to load.
+//title: The title of the page (used to update document.title).
+//init: A function which executes when the route is loaded.
+
+async function register() {
+ const registerForm = document.getElementById('registerForm'); //retrieves data from the register form and stores it in this variable.
+ const formData = new FormData(registerForm);
+ const data = Object.fromEntries(formData);
+ const jsonData = JSON.stringify(data); //Converts data into an object and then converts in the form of JSON string.
+ const result = await createAccount(jsonData); //stores the registered user details
+
+ if(result.error){
+ return updateElement('registerError', result.error); //displays the error message and does the respective styling.
+ }
+
+ console.log('Account created!', result);
+ updateState('account',result); // stores it into the variable we created for user details if no error is returned.
+ navigate('/dashboard'); //calls the navigate function and navigates to the dashboard page.
+}
+
+
+async function add(){
+ const transactionForm = document.getElementById('transactionForm');
+ if (!transactionForm) {
+ console.log("Transaction form not found!");
+ return;
+ }
+ const addDetails = new FormData(transactionForm);
+ const transactionDetails = Object.fromEntries(addDetails);
+ console.log("Transaction Details:", transactionDetails);
+ // Create the row
+ const transactionRow = createTransactionRow(transactionDetails);
+ // Find the transactions table
+ const transactionsTable = document.getElementById('transactions'); // Ensure this is the tbody, not the table
+ if (!transactionsTable) {
+ console.log("Transactions table not found!");
+ return;
+ }
+ // Append the new row to the table
+ transactionsTable.appendChild(transactionRow);
+ console.log("Attempting to save transaction to API...");
+
+ try {
+ const response = await fetch(`${api}${encodeURIComponent(state.account.user)}/transactions`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(transactionDetails),
+ });
+ if (!response.ok) throw new Error(await response.text());
+ console.log("Transaction successfully saved to API.");
+ } catch (error) {
+ console.error("Error saving transaction:", error);
+ }
+
+ // Reset the form after adding
+ transactionForm.reset();
+}
+
+async function createAccount(account) {
+ try {
+ const response = await fetch(api , {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' }, //sends a POST request to the API to create an account.
+ body: account
+ });
+ return await response.json(); //converts the response to JSON.
+ } catch (error) {
+ return { error: error.message || 'Unknown error' }; //catch is used to display an error message if any error is generated.
+ }
+}
+
+function logout() {
+ updateState('account', null);
+ localStorage.removeItem(storageKey); //removes the items stored in the storageKey.
+ navigate('/login'); //redirects to the login page once logged out
+}
+
+async function login() {
+ const loginForm = document.getElementById('loginForm'); //retrieves data from the login form and stores it in this variable.
+ const user = loginForm.user.value; //the name type is used to get the username to the variable user.
+ const data = await getAccount(user); //calls the getAccount function to fetch the user details on logging in.
+ if(data.error){
+ return updateElement('loginError',data.error); //displays an error message when any error is found.
+ }
+
+ updateState('account',data); //stores the user details in the account variable.
+ navigate('/dashboard'); //navigates to the dashboard page on logging in.
+}
+
+// We create a function used to get the user details when already registered in the accounts api using async/await function.
+
+async function getAccount(user) {
+ try {
+ const response = await fetch(api + encodeURIComponent(user));
+ return await response.json();
+ } catch (error) {
+ return { error: error.message || 'Unknown error' }; //try and catch function to catch any error and display the error if there.
+ }
+}
+
+
+//createTransactionRow generates a separate row for each transaction.
+
+function createTransactionRow(transaction) {
+ const template = document.getElementById('transaction'); //calls the transaction template.
+ const transactionRow = template.content.cloneNode(true); //clones the transaction template.
+ const tr = transactionRow.querySelector('tr');
+ tr.children[0].textContent = transaction.date ;
+ tr.children[1].textContent = transaction.object;
+ tr.children[2].textContent = transaction.amount; //updates the row with transaction details.
+ return transactionRow; //returns the modified row.
+}
+
+
+function updateRoute() {
+ const path = window.location.pathname; //gets the current url path.
+ const route = routes[path]; //searches for the given template in the routes array.
+
+ if (!route) {
+ return navigate('/dashboard'); //if there is no route, then redirects to the login page.(basically used as a default)
+ }
+
+ const template = document.getElementById(route.templateId); //searches for the template in our html file.
+ const view = template.content.cloneNode(true); //clones the template.
+ const app = document.getElementById('app');
+ document.title = route.title; //sets the document title according to the template that is currently active.
+ app.innerHTML = ''; //sets the title to LOading... if any error in navigating between templates.
+ app.appendChild(view);
+
+ if (typeof route.init === 'function') {
+ route.init(); //calls an initialization function if one is defined.
+ }
+
+ attachEventListeners();
+ }
+
+ function attachEventListeners() {
+ document.querySelector(".logoutButton")?.addEventListener("click", logout);
+ document.getElementById('addTransactions')?.addEventListener('click', () => {
+ document.querySelector("[data-modal]")?.showModal();
+ });
+ document.getElementById("ok")?.addEventListener('click', add);
+}
+
+
+function updateElement(id, content){ //used to change the text of the respective element by specifying the parameters(id and text)
+ const element = document.getElementById(id);
+ element.textContent = '';
+ element.append(content); //We replace the textContent mathod with the append() method as it allows to attach either text or DOM Nodes to a parent element, which is perfect for all our use cases.
+}
+
+function navigate(path) {
+ window.history.pushState({}, path, path); //updates the browser history.
+ updateRoute();
+} //used for navigation purposes.
+
+function updateDashboard() {
+ const account = state.account;
+ if (!account) {
+ return logout();
+ }
+
+ updateElement('description', account.description);
+ updateElement('balance', account.balance.toFixed(2));
+ updateElement('currency', account.currency); //updates the given elements content.
+
+ const transactionsRows = document.createDocumentFragment();
+ for (const transaction of account.transactions) {
+ const transactionRow = createTransactionRow(transaction);
+ transactionsRows.appendChild(transactionRow);
+ }
+ updateElement('transactions', transactionsRows); //creates and appends the transaction rows.
+}
+
+//we create a function which would update any details directly on the dashboard page itself without the need to reload and login again.
+
+async function updateAccountData() {
+ const account = state.account;
+ if (!account) {
+ return logout();
+ }
+
+ const data = await getAccount(account.user);
+ if (data.error) {
+ return logout();
+ }
+
+ updateState('account', data);
+}
+
+async function refresh() {
+ await updateAccountData();
+ updateDashboard();
+}
+
+function updateState(property, newData) {
+ state = Object.freeze({
+ ...state,
+ [property]: newData
+ });
+
+ if (newData && newData.user) {
+ localStorage.setItem(storageKey, newData.user);
+ } else {
+ localStorage.removeItem(storageKey); // Ensure old data is removed
+ }
+}
+
+async function init() {
+ const savedUser = localStorage.getItem(storageKey);
+ if (savedUser) {
+ const info = await getAccount(savedUser);
+ updateState('account', info); //calls the updateState function to get the entire user details after getting the username.
+ }
+
+ // Our previous initialization code
+ window.onpopstate = () => updateRoute(); //Ensures navigation works on clicking the back and forward buttons.
+ updateRoute(); //Loads the correct page when the app starts.
+}
+
+
+
+init();
\ No newline at end of file
diff --git a/bank-solution/index.html b/bank-solution/index.html
new file mode 100644
index 0000000..83620cb
--- /dev/null
+++ b/bank-solution/index.html
@@ -0,0 +1,105 @@
+
+
+
+ Back
+ Logout
+
+
+```
+After creating the template, my next step was to add the template to my routes object, which established a connection between my url and credits template. I also added a link in the header element of my dashboard template to navigate between the templates.
+
+```html
+Credits
+```
+
+## 3. data
+
+### Challenge
+
+```css
+@media screen and (max-width: 1504px) {
+ .forms {
+ width: 50%;
+ margin-left: 25%;
+ }
+
+ input, button {
+ width: 70%;
+ }
+
+ #table {
+ width: 60%;
+ margin-left: 20%;
+ }
+}
+
+/* For mobile devices */
+@media screen and (max-width: 968px) {
+ .forms {
+ width: 70%;
+ margin-left: 15%;
+ font-size: 20px;
+ }
+
+ h2 {
+ font-size: 28px;
+ }
+
+ input, button {
+ width: 70%;
+ font-size: 18px;
+ }
+
+ button {
+ height: 45px;
+ font-size: 24px;
+ }
+
+ .heading, .heading2 {
+ font-size: 20px;
+ text-shadow: 4px 4px crimson;
+ }
+
+ #balanceField {
+ font-size: 40px;
+ height: 60px;
+ }
+
+ #table {
+ width: 80%;
+ margin-left: 10%;
+ font-size: 25px;
+ }
+
+ #table td {
+ height: 50px;
+ }
+
+ .logoutButton{
+ margin-top: 50px;
+ width: 150px;
+ height: 50px;
+ border-radius: 10px;
+ text-decoration: none;
+ }
+
+ .logoutButton a{
+ font-size: 25px;
+ text-decoration: none;
+ color: white;
+ text-shadow: 2px 2px rgb(253, 249, 11);
+ }
+}
+
+/* For very small screens */
+@media screen and (max-width: 580px) {
+ .forms {
+ width: 70%;
+ margin-left: 15%;
+ font-size: 18px;
+ }
+
+ h2 {
+ font-size: 24px;
+ }
+
+ input, button {
+ width: 75%;
+ font-size: 16px;
+ }
+
+ button {
+ height: 40px;
+ font-size: 20px;
+ }
+
+ .heading, .heading2 {
+ font-size: 18px;
+ text-shadow: 3px 3px crimson;
+ }
+
+ #balanceField {
+ font-size: 30px;
+ height: 50px;
+ }
+
+ #table {
+ width: 90%;
+ margin-left: 5%;
+ font-size: 20px;
+ }
+
+ #table td {
+ height: 40px;
+ }
+}
+```
+
+### Assignment
+
+```javascript
+//Create a variable which stores the logged-in user's details, with initial value as none indicating no user is logged in.
+//We need a private space to store all the user details who have created their accounts. These details are stored and used to retrieve the account details.
+
+let account = null;
+const api = '//localhost:5000/api/accounts/';
+
+//We need to create an array which would hold all the required ids and titles of each template which would help in navigation.
+
+const routes = {
+ '/login': {
+ templateId: 'login' ,
+ title: 'Login Page'
+ },
+ '/dashboard': {
+ templateId: 'dashboard',
+ title: 'Dashboard',
+ init: updateDashboard
+ },
+ '/credits': {
+ templateId: 'credits',
+ title: 'credits'
+ },
+};
+
+
+//templateId: The ID of the HTML template to load.
+//title: The title of the page (used to update document.title).
+//init: A function which executes when the route is loaded.
+
+async function register() {
+ const registerForm = document.getElementById('registerForm'); //retrieves data from the register form and stores it in this variable.
+ const formData = new FormData(registerForm);
+ const data = Object.fromEntries(formData);
+ const jsonData = JSON.stringify(data); //Converts data into an object and then converts in the form of JSON string.
+ const result = await createAccount(jsonData); //stores the registered user details
+
+ if(result.error){
+ return updateElement('registerError', result.error); //displays the error message and does the respective styling.
+ }
+
+ console.log('Account created!', result);
+ account = result; // stores it into the variable we created for user details if no error is returned.
+ navigate('/dashboard'); //calls the navigate function and navigates to the dashboard page.
+}
+
+async function createAccount(account) {
+ try {
+ const response = await fetch(api , {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' }, //sends a POST request to the API to create an account.
+ body: account
+ });
+ return await response.json(); //converts the response to JSON.
+ } catch (error) {
+ return { error: error.message || 'Unknown error' }; //catch is used to display an error message if any error is generated.
+ }
+}
+
+async function login() {
+ const loginForm = document.getElementById('loginForm'); //retrieves data from the login form and stores it in this variable.
+ const user = loginForm.user.value; //the name type is used to get the username to the variable user.
+ const data = await getAccount(user); //calls the getAccount function to fetch the user details on logging in.
+ if(data.error){
+ return updateElement('loginError',data.error); //displays an error message when any error is found.
+ }
+
+ account = data; //stores the user details in the account variable.
+ navigate('/dashboard'); //navigates to the dashboard page on logging in.
+}
+
+// We create a function used to get the user details when already registered in the accounts api using async/await function.
+
+async function getAccount(user) {
+ try {
+ const response = await fetch(api + encodeURIComponent(user));
+ return await response.json();
+ } catch (error) {
+ return { error: error.message || 'Unknown error' }; //try and catch function to catch any error and display the error if there.
+ }
+}
+
+//createTransactionRow generates a separate row for each transaction.
+
+function createTransactionRow(transaction) {
+ const template = document.getElementById('transaction'); //calls the transaction template.
+ const transactionRow = template.content.cloneNode(true); //clones the transaction template.
+ const tr = transactionRow.querySelector('tr');
+ tr.children[0].textContent = transaction.date;
+ tr.children[1].textContent = transaction.object;
+ tr.children[2].textContent = transaction.amount.toFixed(2); //updates the row with transaction details.
+ return transactionRow; //returns the modified row.
+}
+
+
+function updateRoute() {
+ const path = window.location.pathname; //gets the current url path.
+ const route = routes[path]; //searches for the given template in the routes array.
+
+ if (!route) {
+ return navigate('/login'); //if there is no route, then redirects to the login page.(basically used as a default)
+ }
+
+ const template = document.getElementById(route.templateId); //searches for the template in our html file.
+ const view = template.content.cloneNode(true); //clones the template.
+ const app = document.getElementById('app');
+ document.title = route.title; //sets the document title according to the template that is currently active.
+ app.innerHTML = ''; //sets the title to LOading... if any error in navigating between templates.
+ app.appendChild(view);
+
+ if (typeof route.init === 'function') {
+ route.init(); //calls an initialization function if one is defined.
+ }
+ }
+
+
+function updateElement(id, textorNode){ //used to change the text of the respective element by specifying the parameters(id and text)
+ const element = document.getElementById(id);
+ element.textContent = '';
+ element.append(textorNode); //We replace the textContent mathod with the append() method as it allows to attach either text or DOM Nodes to a parent element, which is perfect for all our use cases.
+}
+
+function navigate(path) {
+ window.history.pushState({}, path, path); //updates the browser history.
+ updateRoute();
+} //used for navigation purposes.
+
+function updateDashboard() {
+ if (!account) {
+ return navigate('/login');
+ }
+
+ updateElement('description', account.description);
+ updateElement('balance', account.balance.toFixed(2));
+ updateElement('currency', account.currency); //updates the given elements content.
+
+ const transactionsRows = document.createDocumentFragment();
+ for (const transaction of account.transactions) {
+ const transactionRow = createTransactionRow(transaction);
+ transactionsRows.appendChild(transactionRow);
+ }
+ updateElement('transactions', transactionsRows); //creates and appends the transaction rows.
+}
+
+window.onpopstate = () => updateRoute(); //Ensures navigation works on clicking the back and forward buttons.
+updateRoute(); //Loads the correct page when the app starts.
+```
+
+## 4. state-management
+
+### Challenge
+
+Update the updateState() function to contain the following code, so that the storageKey stores the username only, rather than storing the entire account detials.
+
+```javascript
+function updateState(property, newData) {
+ state = Object.freeze({
+ ...state,
+ [property]: newData
+ });
+
+ if (newData && newData.user) {
+ localStorage.setItem(storageKey, newData.user);
+ } else {
+ localStorage.removeItem(storageKey); // Ensure old data is removed
+ }
+```
+Subsequently, we also need to make changes to our init() function to get our account details later by using getAccount() function.
+
+```javascript
+async function init() {
+ const savedUser = localStorage.getItem(storageKey);
+ if (savedUser) {
+ const info = await getAccount(savedUser);
+ updateState('account', info); //calls the updateState function to get the entire user details after getting the username.
+ }
+
+ // Our previous initialization code
+ window.onpopstate = () => updateRoute(); //Ensures navigation works on clicking the back and forward buttons.
+ updateRoute(); //Loads the correct page when the app starts.
+}
+```
+### Assignment
+
+In order to add a feature which enables us to add the transactions to our account and displays the balance the next time we login, we need to first create a dialog which opens up where we enter the transaction details.
+
+So first , I added the (add transaction) button which on clicking will open our dialog. I added the above code to my index.html file just below our div element which is containing our description heading.
+
+```html
+
+
+
+```
+I then added some styling to my button such that the final output looks like this.
+
+
+I then added the dialog tag in my index.html file which shows up only when the button is clicked.I first created a separate html file to style my dialog and then integrated everything into my actual file, making it easy for me to work on one thing.
+I added the following code which creates a data modal which shows up only when the add transaction button is clicked.
+
+```html
+
+```
+I had added a form in my dialog so that on adding the transaction details and submitting my form , it would be a lot more easier to save it to the api later. ( basically following the same thing that we follow for register)
+
+I added all the event listeners in my project in attachEventListeners function due to some error I faced in my later stages (which I will specify at a later stage)
+
+```javascript
+async function add(){
+ const transactionForm = document.getElementById('transactionForm');
+ if (!transactionForm) {
+ console.log("Transaction form not found!");
+ return;
+ }
+ const addDetails = new FormData(transactionForm);
+ const transactionDetails = Object.fromEntries(addDetails);
+ console.log("Transaction Details:", transactionDetails);
+ // Create the row
+ const transactionRow = createTransactionRow(transactionDetails);
+ // Find the transactions table
+ const transactionsTable = document.getElementById('transactions'); // Ensure this is the tbody, not the table
+ if (!transactionsTable) {
+ console.log("Transactions table not found!");
+ return;
+ }
+ // Append the new row to the table
+ transactionsTable.appendChild(transactionRow);
+ console.log("Attempting to save transaction to API...");
+
+ try {
+ const response = await fetch(`${api}${encodeURIComponent(state.account.user)}/transactions`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(transactionDetails),
+ });
+ if (!response.ok) throw new Error(await response.text());
+ console.log("Transaction successfully saved to API.");
+ } catch (error) {
+ console.error("Error saving transaction:", error);
+ }
+
+ // Reset the form after adding
+ transactionForm.reset();
+}
+```
+
+