diff --git a/4-bank-project/bank-solution/app.js b/4-bank-project/bank-solution/app.js
new file mode 100644
index 0000000..9e9424a
--- /dev/null
+++ b/4-bank-project/bank-solution/app.js
@@ -0,0 +1,246 @@
+const URL='//localhost:5000/api/accounts';
+let currentUser;
+
+const routes = {
+ '/login': { templateId: 'login', title:"Login"},
+ '/dashboard': { templateId: 'dashboard', title:"Dashboard",init: refresh, onShow:()=>console.log("Dashboard is shown") },
+ '/credits':{templateId: 'credits',title:"Credits"}
+};
+
+function showCredits(){
+ navigate('/credits');
+}
+
+function backToDashboard(){
+ navigate('/dashboard');
+}
+
+let state = Object.freeze({
+ account: null
+});
+const storageKey = 'savedAccount';
+
+function updateRoute() {
+ const path = window.location.pathname;
+ const route = routes[path];
+ if (!route) {
+ return navigate('/login');
+ }
+ document.title = route.title;
+ const template = document.getElementById(route.templateId);
+ const view = template.content.cloneNode(true);
+ const app = document.getElementById('app');
+ app.innerHTML = '';
+ app.appendChild(view);
+
+ if (typeof route.init === 'function') {
+ route.init();
+ }
+
+}
+
+
+function navigate(path) {
+ window.history.pushState({}, path, path);
+ updateRoute();
+}
+
+function onLinkClick(event) {
+ event.preventDefault();
+ navigate(event.target.href);
+}
+
+
+
+// Take the data from registration form and creates a new account
+async function register() {
+ const registerForm = document.getElementById('registerForm');
+ const formData = new FormData(registerForm);
+ const data = Object.fromEntries(formData);
+ const jsonData = JSON.stringify(data);
+ const result = await createAccount(jsonData);
+ if (result.error) {
+ return updateElement('registerError', result.error);
+ }
+ currentUser = data.user;
+ console.log('Account created!', result);
+ updateState('account', result);
+ navigate('/dashboard');
+ console.log("Dashboard is shown")
+}
+
+// To add a transaction
+async function addTransactions(event){
+ console.log(`${currentUser}`)
+ const content = document.getElementById('content');
+ const contentFormData = new FormData(content);
+ const transactionData = Object.fromEntries(contentFormData);
+ const transactionJsonData = JSON.stringify(transactionData);
+ event.preventDefault();
+ const apiURL=`${URL}/${currentUser}/transactions`;
+ const result = await sendRequest(apiURL, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: transactionJsonData
+ });
+
+ if (!result.error) {
+ await refresh();
+ }
+
+ return result;
+}
+
+
+async function sendRequest(url, options = {}) {
+ try {
+ const response = await fetch(url, options);
+ return await response.json();
+ } catch (error) {
+ return { error: error.message || 'Unknown error' };
+ }
+}
+
+
+// Sends a POST request to create a new account
+async function createAccount(account) {
+ return sendRequest(URL, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: account
+ });
+}
+
+//Retrieves account data
+async function getAccount(user) {
+ return sendRequest(`${URL}/${user}`);
+}
+
+
+window.onpopstate = () => updateRoute();
+updateRoute();
+
+async function login() {
+ const loginForm = document.getElementById('loginForm')
+ const user = loginForm.user.value;
+ currentUser=user;
+ const data = await getAccount(user);
+
+ if (data.error)
+ {
+ return updateElement('loginError', data.error);
+ }
+
+ updateState('account', data);
+ navigate('/dashboard');
+ console.log('Dashboard is shown');
+}
+
+
+function updateElement(id, textOrNode) {
+ const element = document.getElementById(id);
+ element.textContent = '';
+ element.append(textOrNode);
+ }
+
+
+function updateDashboard() {
+ const account = state.account;
+ if (!account) {
+ return logout();
+ }
+ updateElement('showuser',currentUser)
+ updateElement('description', account.description);
+ updateElement('balance', account.balance.toFixed(2));
+ updateElement('currency', account.currency);
+ const transactionsRows = document.createDocumentFragment();
+ for (const transaction of account.transactions)
+ {
+ const transactionRow = createTransactionRow(transaction);
+ transactionsRows.appendChild(transactionRow);
+ }
+ updateElement('transactions', transactionsRows);
+}
+
+function createTransactionRow(transaction) {
+ const template = document.getElementById('transaction');
+ const transactionRow = template.content.cloneNode(true);
+ 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);
+ return transactionRow;
+}
+
+function updateState(property, newData) {
+ state = Object.freeze({
+ ...state,
+ [property]: newData
+ });
+ if (property === 'account' && newData)
+ {
+ localStorage.setItem(storageKey, JSON.stringify({ user: newData.user }));
+ } else if (property === 'account' && !newData)
+ {
+ localStorage.removeItem(storageKey);
+ }
+}
+function logout() {
+ updateState('account', null);
+ currentUser=null;
+ navigate('/login');
+}
+
+function init() {
+ const savedAccount = localStorage.getItem(storageKey);
+ if (savedAccount) {
+ const { user } = JSON.parse(savedAccount);
+ currentUser = user;
+ updateAccountData(); // Fetch fresh account data from the server
+ }
+ window.onpopstate = () => updateRoute();
+ updateRoute();
+}
+
+init();
+
+
+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();
+}
+
+
+// To open and close the 'Add Transactions' dialogue
+const transactionBox = document.getElementById("tbox");
+const transactionButton = document.getElementById("tbutton");
+const span = document.getElementById("close");
+function openBox() {
+ transactionBox.style.display = "block";
+}
+function closeBox(){
+ transactionBox.style.display = "none";
+}
+window.onclick = function(event) {
+ if (event.target == transactionBox) {
+ transactionBox.style.display = "none";
+ }
+}
+
+
+
diff --git a/4-bank-project/bank-solution/index.html b/4-bank-project/bank-solution/index.html
new file mode 100644
index 0000000..02b036e
--- /dev/null
+++ b/4-bank-project/bank-solution/index.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+ Bank App
+
+
+ Bank App
+ Loading...
+
+
+ LOGIN
+
+
+
+ REGISTER
+
+
+
+
+
+
+
+
+
+
+
+
+ Transactions
+
+
+
+ Date |
+ Object |
+ Amount |
+
+
+
+
+
+
+
+
+
+ |
+ |
+ |
+
+
+
+
+ Made by: Anandajith S
+
+
+
+
\ No newline at end of file
diff --git a/4-bank-project/bank-solution/solution.md b/4-bank-project/bank-solution/solution.md
new file mode 100644
index 0000000..b4c8874
--- /dev/null
+++ b/4-bank-project/bank-solution/solution.md
@@ -0,0 +1,70 @@
+# 1. Subtask-1
+
+## Challenge
+We can do this by adding `/credits':{templateId: 'credits'}` in our `routes`
+
+
+
+## Assignment
+For this assignment, we need to modify `route` and the function `updateRoute()`. We add
+`document.title = route.title;` in `updateRoute()` to update our window title.
+
+```javascript
+const routes = {
+ '/login': { templateId: 'login', title:"Login"},
+ '/dashboard': { templateId: 'dashboard', title:"Dashboard",init: refresh, onShow:()=>console.log("Dashboard is shown") },
+ '/credits':{templateId: 'credits',title:"Credits"}
+};
+function updateRoute() {
+ const path = window.location.pathname;
+ const route = routes[path];
+ if (!route) {
+ return navigate('/login');
+ }
+ document.title = route.title;
+ const template = document.getElementById(route.templateId);
+ const view = template.content.cloneNode(true);
+ const app = document.getElementById('app');
+ app.innerHTML = '';
+ app.appendChild(view);
+
+ if (typeof route.init === 'function') {
+ route.init();
+ }
+}
+```
+
+# 2.Subtask-2
+
+## Challenge
+The following code in `register()` will display the error message:
+
+```javascript
+ if (result.error) {
+ return updateElement('registerError', result.error);
+ }
+```
+
+
+## Assignment
+Created a css file named `styles.css` and linked it to `index.html`
+
+# 3.Subtask-3
+
+## Challenge
+Styled the dashboard page and used media queries to create a responsive design
+
+## Assignments
+- Extracted the server base API URL
+
+- Reorganized the code and added comments at relevant locations
+
+- Created a new function `sendRequest` to send a HTTP request to the URL instead of using the same code repeatedly
+
+# 4.Subtask-4
+
+## Challenge
+Everytime the dashboard is loaded, the account data is reloaded. Hence, we don't need to store all the account details since they can be fetched from the server. First, I modified `updateState()` to only save the current user. In the `init()` fuction, we called the `updateAccountData()`
+
+
+
diff --git a/4-bank-project/bank-solution/styles.css b/4-bank-project/bank-solution/styles.css
new file mode 100644
index 0000000..4371e77
--- /dev/null
+++ b/4-bank-project/bank-solution/styles.css
@@ -0,0 +1,202 @@
+* {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ font-family: 'Times New Roman', Times, serif;
+}
+
+#heading{
+ position: absolute;
+ top: 10px;
+ left: 50%;
+ font-size: 80px;
+ transform: translateX(-50%);
+ color: white;
+ z-index: -1;
+}
+body {
+ background: linear-gradient(to bottom, #008CFF, #50BFFF);
+ height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+#app{
+ background: #fff;
+ padding: 30px;
+ border-radius: 10px;
+ box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.2);
+ text-align: left;
+ width: 800px;
+}
+
+#registerError{
+ color: red;
+ font-size: 30px;
+}
+
+h1 {
+ color: #007BFF;
+ margin-bottom: 20px;
+ text-align: center;
+}
+h2 {
+ color: #007BFF;
+ margin-bottom: 20px;
+}
+input {
+ width: 100%;
+ padding: 10px;
+ margin: 10px 0;
+ border: 1px solid #ccc;
+ border-radius: 5px;
+ font-size: 20px;
+}
+.button {
+ width: 100%;
+ padding: 10px;
+ background: #007BFF;
+ color: #fff;
+ border: none;
+ border-radius: 5px;
+ cursor: pointer;
+ margin-top: 10px;
+ font-size: 20px;
+}
+.button:hover {
+ background: #0056b3;
+}
+.divider {
+ margin: 20px 0;
+ color: #aaa;
+ font-size: 14px;
+}
+table, tr, th,td{
+ border:2px solid black;
+ border-collapse: collapse;
+ text-align: center;
+}
+
+body {font-family: Arial, Helvetica, sans-serif;}
+
+/* The Modal (background) */
+.addtransactions {
+ display: none;
+ position: fixed;
+ z-index: 1;
+ padding-top: 100px;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ overflow: auto;
+ background-color: rgb(0,0,0);
+ background-color: rgba(0,0,0,0.4);
+}
+
+/* Modal Content */
+#tcontent {
+ background-color: #fefefe;
+ margin: auto;
+ padding: 20px;
+ border: 1px solid #888;
+ width: 80%;
+}
+
+/* The Close Button */
+#close {
+ color: #aaaaaa;
+ float: right;
+ font-size: 28px;
+ font-weight: bold;
+}
+
+#close:hover,
+#close:focus {
+ color: #000;
+ text-decoration: none;
+ cursor: pointer;
+}
+
+#showbalance{
+ font-size: 50px;
+ font-weight: bolder;
+ color: #007BFF;
+ margin-top: 20px;
+ margin-bottom: 20px;
+ text-align: center;
+}
+
+table{
+ width: 100%;
+ font-size: 20px;
+}
+
+th{
+ background-color: rgb(180, 180, 180);
+ height:25px;
+}
+
+#transactions tr:nth-child(odd){
+ background-color: #4896e9;
+ height:25px;
+}
+#transactions tr:nth-child(even){
+ background-color: rgb(180, 180, 180);
+ height:25px;
+}
+#tbutton{
+ width:20%;
+ position: relative;
+ left: 65%;
+}
+
+#logout{
+ width:10%;
+ position: relative;
+}
+
+#submit{
+ position: relative;
+ text-align: center;
+}
+
+#creditsbutton {
+ width: 100px;
+}
+
+#back{
+ width: 100px;
+ padding: 5px;
+}
+
+@media (max-width: 480px) {
+ #tbutton #logout {
+ width: 30%;
+ position: relative;
+ left: 40%;
+ }
+ }
+
+
+@media (max-height:480px){
+ #logout {
+ margin-top:0.75rem;
+ position:fixed;
+ top:0.75rem;
+ left:0.75rem;
+ }
+
+ #tbutton{
+ margin-top:0.75rem;
+ position: fixed;
+ top: 0.75rem;
+ right:0.75rem;
+ }
+
+ #app{
+ height:41rem;
+ }
+}
+
diff --git a/4-bank-project/images/add_transaction.png b/4-bank-project/images/add_transaction.png
new file mode 100644
index 0000000..02e9dc3
Binary files /dev/null and b/4-bank-project/images/add_transaction.png differ
diff --git a/4-bank-project/images/credits.png b/4-bank-project/images/credits.png
new file mode 100644
index 0000000..dd359c4
Binary files /dev/null and b/4-bank-project/images/credits.png differ
diff --git a/4-bank-project/images/dashboard.png b/4-bank-project/images/dashboard.png
new file mode 100644
index 0000000..33b22e2
Binary files /dev/null and b/4-bank-project/images/dashboard.png differ
diff --git a/4-bank-project/images/transaction_added.png b/4-bank-project/images/transaction_added.png
new file mode 100644
index 0000000..bf60f6e
Binary files /dev/null and b/4-bank-project/images/transaction_added.png differ
diff --git a/4-bank-project/images/user_exists.png b/4-bank-project/images/user_exists.png
new file mode 100644
index 0000000..3daf6b8
Binary files /dev/null and b/4-bank-project/images/user_exists.png differ