-
Notifications
You must be signed in to change notification settings - Fork 0
/
atm.js
333 lines (291 loc) · 13.1 KB
/
atm.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
//#region update gui time
function updateTimer() { timeView.innerText = new Date().toLocaleTimeString('he-IL', { hour: '2-digit', minute: '2-digit' }) }
setInterval(updateTimer, 1000);
updateTimer();
//#endregion
/** @type {Account[]} */
const users = [];
users.push(new Account("Almog BZ", 1000))
users.push(new Account("Natalie Vinitsky", 999999))
users.push(new Account("Noam Adari", 200))
users.push(new Account("Emma Snow", 800))
users.push(new Account("Anton Chekov", 69))
users.push(new Account("Beni Bad Boy", 69))
/**
* Creates credit card html view as div
* @param {Account} account
* @returns {HTMLDivElement}
*/
function createCardHTML(account) {
const el = document.createElement("div")
el.className = "ccView flex";
el.innerHTML = `<div class="space"></div>
<label class="number">${account.cardNumber.slice(0, 4) + " " + account.cardNumber.slice(4, 8) + " " + account.cardNumber.slice(8, 12)}</label>
<label class="name" pin="${account.pincode}">${account.name}</label>`;
return el;
}
//load cards according to all users
function loadCardsView() {
const cardsDiv = document.querySelector("#creditCardList");
cardsDiv.innerHTML = ""; //empty div
//for each user generate a card div
users.forEach(acc => {
const el = createCardHTML(acc)
el.addEventListener("click", loadLoginScreen.bind(null, acc.cardNumber, "cardNumber"))
cardsDiv.appendChild(el)
});
}
loadCardsView();
/** @type {Account} stores the current logged in user*/
let currentUser;
/**
* searches for an account by files / value
* @param {String} searchTerm
* @param {String} field
*/
function loadLoginScreen(searchTerm, field = "name") {
console.log(searchTerm)
const user = users.find(acc => acc[field]?.toLowerCase() == searchTerm.toLowerCase());
console.log(user)
if (user) {
//sets current user fo later use
currentUser = user;
//changes the screen to pin code input
pincode_screen.click();
}
else {
alert(`Could not found a user with ${field.toUpperCase()} of - ${searchTerm.toUpperCase()}`)
}
}
//triggers when loading pincode screen
function onPincodeScreenLoad() {
//update greeting name
document.querySelector("#pincode_screen + .screen #namePlaceholder").innerText = currentUser.name.toUpperCase();
document.querySelector(".header .displayName").innerText = "Hello " + currentUser.name;
//copy & replace credit card view
const ccViewPincode = document.querySelector("#ccViewPincode");
const newCradView = createCardHTML(currentUser);
newCradView.setAttribute("style", ccViewPincode.getAttribute("style"));
newCradView.setAttribute("id", "ccViewPincode")
ccViewPincode.replaceWith(newCradView)
}
/** on user enter pincode */
function verifyPincode(code) {
const isCorrectPincode = code == currentUser.pincode;
if (!isCorrectPincode)
return alert("Wrong pincode!!\n(Hint: the code is shown on bottom right on the credit card)")
document.getElementById("pincode").value = "";
//on good login
document.querySelector("#menu_screen").click();
atmShow("home")
}
//indicates if key down events will trigger binds
let allowKeybinds = false;
function atmShow(page) {
//clear current style
document.querySelectorAll(`.atmNav label`).forEach(label => label.classList.remove("current"))
//add style to current
document.querySelector(`[onclick="atmShow('${page}')"]`)?.classList.add("current");
const container = document.querySelector(".dynContent");
switch (page) {
case "home":
allowKeybinds = true;
container.innerHTML = `
<h2>ATM MENU:</h2>
<p>To interact with the ATM you can click on the menu above, OR press user shortcuts on your keyboard:</p>
<h4>Shortcuts Cheat-Sheet:</h4>
<ul>
<li><strong>D</strong> - to deposit money.</li>
<li><strong>W</strong> - to withdraw money.</li>
<li><strong>C</strong> - to check current balance.</li>
<li><strong>P</strong> - to change account pincode.</li>
<li><strong>R</strong> - to print current account info.</li>
<li><strong>Q</strong> - to quit back to main menu.</li>
</ul>`
break;
case "deposit":
container.innerHTML = `
<h2><i class="fa-solid fa-money-bills"></i> Deposit:</h2>
<div class="flex mobileBreak">
<p>You may deposit here money into your account,<br>
<strong>Notice:</strong> you can only deposit bills of <strong>20₪ / 50₪ / 100₪ / 200₪</strong>.</p>
${createCardHTML(currentUser).outerHTML}
</div>
<form id="depositForm" onsubmit="event.preventDefault(); atmDeposit(depositValue.value)">
<h3>How much would you like to Deposit?</h3>
<input id="depositValue" required placeholder="20 / 50 / 100 / 200 ...">
<button>Deposit</button>
</form>
<hr>
<p style="text-align:center">No hidden fees! no risky staff here.. just you know.. give us your money! we will keep it for you ♥</p>`
break;
case "withdraw":
container.innerHTML = `
<h2><i class="fa-solid fa-money-bill-transfer"></i> Withdraw:</h2>
<div class="flex mobileBreak">
<p>You may withdraw your money into cash!<br>
No fees, n limits! you just need to have that amount of money..</p>
${createCardHTML(currentUser).outerHTML}
</div>
<h3>Choose withdrawal amount:</h3>
<div class="flex mobileBreak warp" id="withdrawOptions">
<button onclick="atmWithdraw(50)">50₪</button>
<button onclick="atmWithdraw(100)">100₪</button>
<button onclick="atmWithdraw(150)">150₪</button>
<button onclick="atmWithdraw(300)">300₪</button>
<form id="withdrawForm" onsubmit="event.preventDefault(); atmWithdraw(~~withdrawValue.value)">
<input id="withdrawValue" min=0 type="number" required placeholder="Custom ₪ amount..">
<button>Withdraw</button>
</form>
</div>`
break;
case "check":
container.innerHTML = `
<h2><i class="fa-solid fa-money-bill-trend-up"></i> Balance Check:</h2>
<p>Your current balance stands on:</p>
<div class="currentBalance">${currentUser.balance.toLocaleString()}₪</div>`
break;
case "pincode":
container.innerHTML = `
<h2><i class="fa-solid fa-lock"></i> Change Pincode:</h2>
<div class="flex mobileBreak">
<p>You may change your pincode here,<br>
Notice! this pincode will serve your for later use, please do remember it!</p>
${createCardHTML(currentUser).outerHTML}
</div>
<h3>Change pincode form:</h3>
<form class="flex halfGap" id="changePincodeForm" onsubmit="event.preventDefault(); atmPincodeChange()">
<div class="flex warp mobileBreak">
<div>
<label for="changePin_current">Current Pincode:</label>
<input id="changePin_current" type="password" required minlength="4" pattern="^([0-9]){4}" title="4 letters & numbers ONLY." maxlength="4" alt="sdf" placeholder="****"/>
</div>
<div>
<div>
<label for="changePin_new">New Pincode:</label>
<input id="changePin_new" type="password" required minlength="4" pattern="^([0-9]){4}" title="4 letters & numbers ONLY." maxlength="4" placeholder="****"/>
</div>
<div>
<label for="changePin_verify">Verify New Pincode:</label>
<input id="changePin_verify" type="password" required minlength="4" pattern="^([0-9]){4}" title="4 letters & numbers ONLY." maxlength="4" placeholder="****"/>
</div>
</div>
</div>
<button>Change</button>
</form>`
break;
case "quit":
allowKeybinds = false; //block binds
currentUser = null; //remove current
(async () => {
document.querySelector(".logoutMsg").style.display = "flex";
await sleep(2000);
document.querySelector(".header .displayName").innerText = "Hello Guest"
login_screen.click() //show login screen
document.querySelector(".logoutMsg").style.display = "none";
})()
break;
}
}
document.addEventListener("keydown", (e) => {
if (!allowKeybinds)
return;
switch (e.key) {
case "d":
atmShow("deposit")
break;
case "w":
atmShow("withdraw")
break;
case "c":
atmShow("check")
break;
case "p":
atmShow("pincode")
break;
case "r":
printAccount()
break;
case "q":
atmShow("quit")
break;
}
})
async function atmDeposit(amount) {
if (amount <= 0)
return;
amount = Number(amount)
//check if the amount can be just from 20s
const multiply20 = amount % 20 == 0;
//if the amount is more then 50 AND its modulo is 10 then the amount is combination of 1*50 & X*20
const combinationOf20n50 = amount % 20 == 10 && amount >= 50;
if (!multiply20 && !combinationOf20n50)
return alert("You can only deposit amount in bills..\n(using 20 / 50 / 100 / 200)")
allowKeybinds = false;
document.getElementById("depositForm").innerHTML = `
<div style="text-align:center">
<i class="fa-solid fa-spinner fa-spin-pulse fa-10x"></i>
<p>Depositing to your account: ${amount.toLocaleString()}₪;<br> Please wait...</p>
</div>`;
currentUser.balance += amount;
await sleep(2000);
atmShow("home")
}
async function atmWithdraw(amount) {
if (amount <= 0)
return;
if (currentUser.balance < amount)
return alert("You don't have enough in your Balance for this operation!")
allowKeybinds = false;
document.getElementById("withdrawOptions").innerHTML = `
<div style="text-align:center; width:100%">
<i class="fa-solid fa-spinner fa-spin-pulse fa-10x"></i>
<p>Withdrawing ${amount.toLocaleString()}₪ from your account,<br> Please wait...</p>
</div>`;
currentUser.balance -= amount;
await sleep(2000);
atmShow("home")
}
async function atmPincodeChange() {
const currentPincode = document.querySelector("#changePin_current").value,
newPincode = document.querySelector("#changePin_new").value,
nePincodeVerify = document.querySelector("#changePin_verify").value;
if (currentPincode != currentUser.pincode)
return alert("Current pincode entered doesn't match for this account!!")
if (newPincode != nePincodeVerify)
return alert("New pincode & verify pincode miss-match!")
allowKeybinds = false;
document.getElementById("changePincodeForm").innerHTML = `
<div style="text-align:center; width:100%">
<i class="fa-solid fa-spinner fa-spin-pulse fa-10x"></i>
<p>Changing pincode for account - ${currentUser.cardNumber}..</p>
</div>`;
currentUser.pincode = newPincode;
await sleep(2000);
atmShow("home")
}
function printAccount() {
const div = document.querySelector(".printView");
div.innerHTML = `
<h1 style="color:#000; text-shadow: none;"><i class="fa-solid fa-building-columns logo"></i> Fake Bank of Israel
</h1>
<div class="flex" style="justify-content:space-around; gap:2em:" >
${createCardHTML(currentUser).outerHTML}
<div style="color:#000; text-shadow:none; text-align: left; font-size:2em">
<h2>Account info:</h2>
<div class="flex infoView">
<div class="flex"><span>Full Name:</span> <span>${currentUser.name}</span></div>
<div class="flex"><span>Account Number:</span> <span>${currentUser.cardNumber}</span></div>
<div class="flex"><span>Access Pincode:</span> <span>****</span></div>
<div> <hr></div>
<div class="flex"><span>Balance:</span> <span>${currentUser.balance.toLocaleString()}</span></div>
</div>
<br>
<span style="font-size:0.5em">Relevant for date: ${new Date()}</span>
</div>
</div>
<p style="color:#000; font-weight:400">All info within this document is private and meant for the eyes of the account owner and his lawyer only!
Any use of this document and the info within it is forbidden and can case legal action upon any use of it. </p>`
window.print();
}
const sleep = async ms => new Promise(res => setTimeout(res, ms))