initial commit

This commit is contained in:
allard
2025-11-23 18:58:51 +01:00
commit 376a944abc
1553 changed files with 314731 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
class Account extends HTMLElement {
events = ""
points = ""
name = ""
constructor() {
// Always call super first in constructor
super();
console.log('INITIALIZED ACCOUNT VIEW');
var customElement = this;
let template = document.getElementById('accountview');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
let sr = this.shadowRoot;
let logoutButton = sr.getElementById("logoutAccountButton")
logoutButton.addEventListener("click", e => {
this.logout();
})
let deleteButton = sr.getElementById("deleteAccountButton")
deleteButton.addEventListener("click", e => {
this.delete();
})
}
logout() {
// clear cookies of tokens
document.cookie = "access_token=; Max-Age=0'"
document.cookie = "id_token=; Max-Age=0'"
// clear local storage
localStorage.clear()
var phoneview = document.getElementById("phoneview");
var mobileview = phoneview.getMobileView();
mobileview.innerHTML = "";
var welcome = document.createElement('welcome-element')
welcome.setAttribute('mode','INTEGRATED')
mobileview.appendChild(welcome)
phoneview.hideNavigation();
}
delete() {
let phoneview = document.getElementById("phoneview");
let mobileview = phoneview.getMobileView();
mobileview.innerHTML = "";
let element = document.createElement('loading-spinner-element');
element.setAttribute("status", "Deleting account...")
mobileview.appendChild(element)
setTimeout(() => {
deleteUserProfile(loyalty.getCookie('access_token'), success => {
if (success) {
element.setAttribute("status", "Successfully deleted account. Logging out...")
setTimeout(() => {
this.logout();
}, 2500)
}
})
}, 1500)
}
connectedCallback(){
var customElement = this;
var sr = this.shadowRoot;
/* where to make a data call for points/events */
this.mode = customElement.getAttribute('mode');
this.events = customElement.getAttribute('events');
this.points = customElement.getAttribute('points');
if (this.events == null) {
this.events = '-'
}
if (this.points == null) {
this.points = '-'
}
this.name = customElement.getAttribute('name') || localStorage.getItem("loyaltyname")
if(this.name == null){
this.name = "";
}else{
console.log('SETTING NAME')
}
this.nameelement = sr.getElementById('name');
this.nameelement.innerHTML = this.name;
}
}
try {
customElements.define('account-element', Account);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,45 @@
class Asset extends HTMLElement {
static get observedAttributes() {
return ['assetimage', 'text', 'link'];
}
constructor(details) {
// Always call super first in constructor
super();
let template = document.getElementById('assetlink');
let templateContent = template.content;
this.details = details;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
connectedCallback(){
var customElement = this;
var sr = this.shadowRoot;
this.assetimage = sr.getElementById('assetimage');
this.assetimage.src = customElement.getAttribute('assetimage');
this.assettext = sr.getElementById('text');
this.assettext.innerHTML = customElement.getAttribute('text');
let link = customElement.getAttribute('link')
if (link) {
this.assettext.addEventListener("click", e => {
window.location = link
})
}
}
}
try {
customElements.define('asset-element', Asset);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,30 @@
function loginWithAppId(username, password, callback) {
let jsonBody = {
id_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFwcElkLTY4ZDI1ZDQ2LThmZGItNDhlMy1iODNkLTJhYzY2YzI5MTA2NC0yMDIwLTAxLTMxVDAwOjI5OjI4Ljg1NiIsInZlciI6NH0.eyJpc3MiOiJodHRwczovL3VzLXNvdXRoLmFwcGlkLmNsb3VkLmlibS5jb20vb2F1dGgvdjQvMTIzIiwiYXVkIjpbIjEyMyJdLCJleHAiOjAsInRlbmFudCI6IjY4ZDI1ZDQ2LThmZGItNDhlMy1iODNkLTJhYzY2YzI5MTA2NCIsImlhdCI6MCwiZW1haWwiOiJKb2huQFNtaXRoLm9yZyIsIm5hbWUiOiJKb2huIFNtaXRoIiwic3ViIjoiMTIzIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiTGl0YUNhdnJhayIsImdpdmVuX25hbWUiOiJKb2huIiwiZmFtaWx5X25hbWUiOiJTbWl0aCIsImlkZW50aXRpZXMiOlt7InByb3ZpZGVyIjoiY2xvdWRfZGlyZWN0b3J5IiwiaWQiOiIxMjMifV0sImFtciI6WyJjbG91ZF9kaXJlY3RvcnkiXX0.ABC",
access_token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFwcElkLTY4ZDI1ZDQ2LThmZGItNDhlMy1iODNkLTJhYzY2YzI5MTA2NC0yMDIwLTAxLTMxVDAwOjI5OjI4Ljg1NiIsInZlciI6NH0.eyJpc3MiOiJodHRwczovL3VzLXNvdXRoLmFwcGlkLmNsb3VkLmlibS5jb20vb2F1dGgvdjQvMTIzIiwiZXhwIjowLCJhdWQiOlsiMTIzIl0sInN1YiI6IjEyMyIsImFtciI6WyJjbG91ZF9kaXJlY3RvcnkiXSwiaWF0IjowLCJ0ZW5hbnQiOiIxMjMiLCJzY29wZSI6Im9wZW5pZCBhcHBpZF9kZWZhdWx0IGFwcGlkX3JlYWR1c2VyYXR0ciBhcHBpZF9yZWFkcHJvZmlsZSBhcHBpZF93cml0ZXVzZXJhdHRyIGFwcGlkX2F1dGhlbnRpY2F0ZWQifQ.ABC"
}
document.cookie = 'access_token=' + jsonBody.access_token + ';'
document.cookie = 'id_token=' + jsonBody.id_token+ ';'
callback(jsonBody)
}
function getRandomUser(callback) {
let text = "John Smith"
let name = text.split(' ')
let firstname = name[0]
let surname = name[1]
let password = name[0] + name[1]
let email = name[0] + "@" + name[1] + ".org"
callback(firstname, surname, password, email)
}
function createAccountAppId(firstname, lastname, password, email, callback) {
let json = {}
json.status = "user created successfully"
callback(json)
}
function getAllUsers(callback) {
callback(['JohnSmith'])
}

View File

@@ -0,0 +1,67 @@
function loginWithAppId(username, password, callback) {
let jsonBody = {username, password}
fetch("/demo/login", {
method: 'POST',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(jsonBody)
}).then((response) => {
console.log(response)
return response.json();
}).then((json) => {
console.log(json)
callback(json)
}).catch((error) => {
callback(null)
})
}
function getRandomUser(callback) {
fetch("/demo/random_user")
.then((response) => {
return response.text()
})
.then((text) => {
let name = text.split(' ')
let firstname = name[0]
let surname = name[1]
let password = name[0] + name[1]
let email = name[0] + "@" + name[1] + ".org"
callback(firstname, surname, password, email)
})
}
function createAccountAppId(firstname, lastname, password, email, callback) {
let jsonRequestBody = {}
jsonRequestBody.firstName = firstname
jsonRequestBody.lastName = lastname
jsonRequestBody.password = password
jsonRequestBody.email = email
fetch('/demo/create_account', {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body: JSON.stringify(jsonRequestBody)
}).then((response) => {
console.log(response)
return response.json()
}).then((json) => {
callback(json)
})
}
function getAllUsers(callback) {
fetch('/demo/get_all_users')
.then((response) => {
return response.json()
}).then((users) => {
callback(users)
})
}
// sample appid account
// loginWithAppId("RolandeColla", "RolandeColla")

View File

@@ -0,0 +1,137 @@
let SECURE_USER_BACKEND_URL='/proxy_user'
let SECURE_EVENT_BACKEND_URL='/proxy_transaction'
// DEVMODE
let mode = 'INTEGRATED'
function createProfile(access_token, callback) {
callback(true)
}
function deleteUserProfile(access_token, callback) {
callback(true)
}
function getTransactions(access_token, callback) {
let testdata = [{
"amount": 20,
"category": "Cafe",
"date": "2020-04-27T22:09:39.183Z",
"pointsEarned": 20,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Starbucks",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},
{
"amount": 15,
"category": "Carshare",
"date": "2020-04-27T22:09:39.183Z",
"pointsEarned":15,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Uber",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},
{
"amount": 70,
"category": "Gas",
"date": "2020-04-27T22:09:39.183Z",
"pointsEarned": 100,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Esso",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},
{
"amount": 20,
"category": "Meals",
"date": "2020-04-27T22:09:39.183Z",
"pointsEarned":20,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Sweetgreen",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},,
{
"amount": 127,
"category": "Groceries",
"date": "2020-04-27T22:09:39.183Z",
"pointsEarned": 200,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Whole Foods",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},
{
"amount": 34,
"category": "Meals",
"date": "2020-04-17T22:09:39.183Z",
"pointsEarned":34,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Shake Shack",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},
,
{
"amount": 20,
"category": "Meals",
"date": "2020-04-18T22:09:39.183Z",
"pointsEarned":20,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Sweetgreen",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},,
{
"amount": 127,
"category": "Groceries",
"date": "2020-04-27T22:09:39.183Z",
"pointsEarned": 200,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Whole Foods",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
},
{
"amount": 5.75,
"category": "Cafe",
"date": "2020-04-28T22:09:39.183Z",
"pointsEarned":34,
"processed": true,
"transactionId": "c2eb0fb9-2af0-43a3-820d-fa210203f698",
"transactionName": "Starbucks",
"userId": "60e67c81-1a27-4423-a890-db653941822a"
}
]
callback(null, testdata)
}
function getSpending(access_token, callback) {
var data = [
{
"category": "Cafe",
"amount": 45
},
{
"category": "Groceries",
"amount": 239
},
{
"category": "Fuel",
"amount": 75
},
{
"category": "Ride Share",
"amount": 35
},
{
"category": "Restaurant",
"amount": 90
}
];
callback(null, data)
}
function createTransaction(access_token, transactionName, category, amount, callback) {
callback(true)
}

View File

@@ -0,0 +1,227 @@
let SECURE_USER_BACKEND_URL='/proxy_user'
let SECURE_EVENT_BACKEND_URL='/proxy_transaction'
function createProfile(access_token, callback) {
let jsonRequestBody = {}
jsonRequestBody.consentGiven = true
fetch(SECURE_USER_BACKEND_URL + '/bank/v1/users', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + access_token,
'Content-type': 'application/json'
},
body: JSON.stringify(jsonRequestBody)
}).then((response) => {
if (response.status == '204') {
callback(true)
} else {
callback(false)
}
})
}
function getUserStats(access_token, callback) {
fetch(SECURE_USER_BACKEND_URL + '/bank/v1/userEvents/self/info', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then(async (response) => {
if (response.status == '200') {
return response.json()
} else {
let responsetext = await response.text()
console.log(responsetext)
throw responsetext
}
}).then((json) => {
callback(null, json.eventCount, json.pointsEarned)
}).catch(e => {
console.log(e)
callback(e, null, null)
})
}
function getUserEvents(access_token, callback) {
fetch(SECURE_USER_BACKEND_URL + '/bank/v1/userEvents/self', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then(async (response) => {
if (response.status == '200') {
return response.json()
} else {
let responsetext = await response.text()
console.log(responsetext)
throw responsetext
}
}).then((events) => {
callback(null, events)
}).catch(e => {
console.log(e)
callback(e, null)
})
}
function getUserEventsWithData(access_token, callback) {
getUserEvents(access_token, (err, events) => {
let queryParams = ''
if (events.length == 0) {
callback(null, events)
} else {
events.forEach(element => {
queryParams += 'id=' + element + '&'
});
fetch(SECURE_EVENT_BACKEND_URL + '/bank/v1/events?' + queryParams, {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then(async (response) => {
console.log(response)
if (response.status == '200') {
return response.json()
} else {
let responsetext = await response.text()
console.log(responsetext)
throw responsetext
}
}).then((events) => {
callback(null, events)
}).catch(e => {
callback(e, null)
})
}
})
}
function getEvents(access_token, callback) {
fetch(SECURE_EVENT_BACKEND_URL + '/bank/v1/events', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then(async (response) => {
if (response.status == '200') {
return response.json()
} else {
let responsetext = await response.text()
console.log(responsetext)
throw responsetext
}
}).then((events) => {
callback(null, events)
}).catch(e => {
console.log(e)
callback(e, null)
})
}
function checkInEvent(access_token, eventId, callback) {
let jsonRequestBody = {}
jsonRequestBody.eventId = eventId
fetch(SECURE_USER_BACKEND_URL + '/bank/v1/userEvents', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + access_token,
'Content-type': 'application/json'
},
body: JSON.stringify(jsonRequestBody)
}).then((response) => {
console.log(response)
if (response.status == '204') {
callback(true)
} else {
callback(false)
}
})
}
function deleteUserProfile(access_token, callback) {
fetch(SECURE_USER_BACKEND_URL + '/bank/v1/users/self', {
method: 'DELETE',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then((response) => {
console.log(response)
if (response.status == '204') {
callback(true)
} else {
callback(false)
}
})
}
function getTransactions(access_token, callback) {
fetch(SECURE_EVENT_BACKEND_URL + '/bank/v1/transactions', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then(async (response) => {
if (response.status == '200') {
return response.json()
} else {
let responsetext = await response.text()
console.log(responsetext)
throw responsetext
}
}).then((transactions) => {
callback(null, transactions)
}).catch(e => {
console.log(e)
callback(e, null)
})
}
function getSpending(access_token, callback) {
fetch(SECURE_EVENT_BACKEND_URL + '/bank/v1/transactions/spending', {
method: 'GET',
headers: {
'Authorization': 'Bearer ' + access_token
}
}).then(async (response) => {
if (response.status == '200') {
return response.json()
} else {
let responsetext = await response.text()
console.log(responsetext)
throw responsetext
}
}).then((transactions) => {
callback(null, transactions)
}).catch(e => {
console.log(e)
callback(e, null)
})
}
function createTransaction(access_token, transactionName, category, amount, callback) {
let jsonRequestBody = { transactionName, category, amount }
fetch(SECURE_EVENT_BACKEND_URL + '/bank/v1/transactions', {
method: 'POST',
headers: {
'Authorization': 'Bearer ' + access_token,
'Content-type': 'application/json'
},
body: JSON.stringify(jsonRequestBody)
}).then(response => {
console.log(response)
if (response.status == '204') {
callback(true)
} else {
callback(false)
}
}).catch(e => {
console.log(e)
callback(false)
})
}

View File

@@ -0,0 +1,31 @@
function attendEvent(userSubject, event) {
let localStorageId = userSubject + '-events'
let userEvents = localStorage.getItem(localStorageId)
if (userEvents == null || userEvents == "") {
let events = []
events.push(event)
localStorage.setItem(userSubject + '-events', JSON.stringify(events))
} else {
let arrayOfEvents = JSON.parse(userEvents)
if (arrayOfEvents.filter(e => e.eventId === event.eventId).length > 0) {
console.log('event exists in local storage')
} else {
arrayOfEvents.push(event)
}
localStorage.setItem(localStorageId, JSON.stringify(arrayOfEvents))
}
}
function getStoredEvents(userSubject) {
let storedEventsString = localStorage.getItem(userSubject + '-events')
if (storedEventsString == null || storedEventsString == "") return null
return JSON.parse(storedEventsString)
}
function removeStoredEvent(userSubject, eventId) {
let localStorageId = userSubject + '-events'
let storedEvents = getStoredEvents(userSubject)
storedEvents = storedEvents.filter(e => e.eventId != eventId)
localStorage.setItem(localStorageId, JSON.stringify(storedEvents))
}

View File

@@ -0,0 +1,89 @@
class Home extends HTMLElement {
constructor() {
super();
console.log('INITIALIZING HOMESCREEN');
let template = document.getElementById('homescreen');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
generateTransaction(access_token, shadowRoot, tile){
var limit = tile.detail.eventData.limit * 100;
var base = tile.detail.eventData.base * 100;
var charge = Math.floor(Math.random() * (limit - base + 1)) + base;
charge=charge/100;
charge=charge.toFixed(2);
var entity = tile.detail.eventData.name.toUpperCase()
console.log('CREATING A CREDIT CARD CHARGE OF $' + charge + ' ON ' + entity );
createTransaction(access_token, entity, entity, charge,
(success) => {
if (success) {
let text = 'CREDIT CARD $' + charge + ' ON ' + entity ;
this.showNotification(shadowRoot, text)
} else {
this.showNotification(shadowRoot, "Failed creating transaction. Please check logs")
}
})
}
showNotification(shadowRoot, notificationText) {
var notifcationArea = shadowRoot.getElementById('notificationarea');
notifcationArea.innerHTML = '';
var message = document.createElement('div');
message.innerHTML = notificationText
message.className = 'notification';
notifcationArea.appendChild(message);
setTimeout(function(){
message.remove()
}, 2000);
}
connectedCallback() {
var sr = this.shadowRoot;
var tiles = sr.getElementById('APPTILES');
var homescreen = this;
tiles.addEventListener('APPTILE', e => {
console.log('HOMESCREEN RECIEVED EVENT FROM TILE: ' + e.detail.eventData.name.toLocaleUpperCase());
switch(e.detail.eventData.name){
case 'bank':
sr.host.parentElement.innerHTML = '<welcome-element mode="' + this.mode + '"></welcome-element>';
break;
default:
let access_token = loyalty.getCookie('access_token')
if (access_token != "") {
homescreen.generateTransaction(access_token, sr, e)
} else {
homescreen.showNotification(sr, 'Please log in using the Bank app.')
}
break;
}
});
}
}
try {
customElements.define('homescreen-element', Home);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,148 @@
class Login extends HTMLElement {
static get observedAttributes() {
return ['firstname', 'surname'];
}
clickCheck(){
console.log('login.clickCheck');
if(this.checkbox.checked){
this.createAccountButton.disabled = false;
}else{
this.createAccountButton.disabled = true;
}
}
createAccount() {
console.log('login.createAccount');
/* where to make a data call for points/events */
let sr = this.shadowRoot
var firstname = sr.getElementById('firstname').innerHTML;
var surname = sr.getElementById('surname').innerHTML;
var email = sr.getElementById('email').innerHTML;
var phoneview = document.getElementById("phoneview");
var mobileview = phoneview.getMobileView();
this.MODE = this.getAttribute('mode')
let previousMobileView = mobileview.innerHTML
mobileview.innerHTML = "";
// create loading spinner first
var element = document.createElement('loading-spinner-element');
element.setAttribute("status", "Creating account...")
mobileview.appendChild(element)
createAccountAppId(firstname, surname, firstname + "" + surname, email, (json) => {
console.log(json)
if (json.status == "user created successfully") {
element.setAttribute("status", "Logging in...")
let usernamepassword = firstname + "" + surname
loginWithAppId(usernamepassword, usernamepassword, (jsonWithTokens) => {
// when creation of account
// and login complete, create the profile
element.setAttribute("status", "Creating user profile...")
createProfile(jsonWithTokens.access_token, success => {
// then show account view
if (success) {
this.createTransactionsView(firstname, surname)
}
// else edge case when failed to create user profile
})
// edge case when unable to sign in
})
} else {
// edge case when failed to register with app id
element.setAttribute("status", json.message)
setTimeout(() => {
mobileview.innerHTML = previousMobileView
}, 2000)
}
})
}
createTransactionsView(firstname, surname) {
var accountinfo ={
firstname:firstname,
surname: surname
}
var fullname = accountinfo.firstname + ' ' + accountinfo.surname
var phoneview = document.getElementById("phoneview");
var mobileview = phoneview.getMobileView();
let element = document.createElement('transactions-element')
element.setAttribute('name', fullname);
element.setAttribute('mode', this.MODE);
mobileview.innerHTML = "";
mobileview.appendChild(element);
localStorage.setItem("loyaltyname", fullname);
phoneview.showNavigation();
}
constructor() {
// Always call super first in constructor
super();
let template = document.getElementById('loginview');
let templateContent = template.content;
const shadow = this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
var sr = this.shadowRoot;
this.checkbox = sr.getElementById('gdprcheck');
this.checkbox.addEventListener('click', e => {
this.clickCheck();
});
this.createAccountButton = sr.getElementById('createAccountButton');
this.createAccountButton.addEventListener('click', e =>{
this.createAccount();
});
}
connectedCallback(){
var ids = ['firstname', 'surname', 'password', 'username', 'email'];
var sr = this.shadowRoot;
var customElement = this;
ids.forEach(function(id){
var element = sr.getElementById(id);
var data = customElement.getAttribute(id);
element.innerHTML = data;
})
let firstnameDiv = sr.getElementById('firstname')
let surnameDiv = sr.getElementById('surname')
let usernameDiv = sr.getElementById('username')
let passwordDiv = sr.getElementById('password')
let emailDiv = sr.getElementById('email')
firstnameDiv.addEventListener('input', function () {
usernameDiv.innerHTML = this.innerHTML + surnameDiv.innerHTML
passwordDiv.innerHTML = this.innerHTML.replace(/./g,'*') + surnameDiv.innerHTML.replace(/./g,'*')
emailDiv.innerHTML = this.innerHTML + "@" + surnameDiv.innerHTML + ".org"
})
surnameDiv.addEventListener('input', function () {
usernameDiv.innerHTML = firstnameDiv.innerHTML + this.innerHTML
passwordDiv.innerHTML = firstnameDiv.innerHTML.replace(/./g,'*') + this.innerHTML.replace(/./g,'*')
emailDiv.innerHTML = firstnameDiv.innerHTML + "@" + this.innerHTML + ".org"
})
}
}
try {
customElements.define('login-element', Login);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,91 @@
class Loyalty {
mobileview;
constructor() {
console.log('INITIALIZING LOYALTY APP');
var phoneview = document.getElementById("phoneview");
this.mobileview = phoneview.getMobileView();
// if cookie exists - then user is logged in
// navigate to account section
// if(this.mode=='INTEGRATED'){
// if (this.getCookie('access_token') != "" && this.getCookie('id_token') != "") {
// let id_object = this.parseJwt(this.getCookie('id_token'))
// console.log(id_object)
// var accountinfo = {
// firstname: id_object.given_name,
// surname: id_object.family_name
// }
// var fullname = accountinfo.firstname + ' ' + accountinfo.surname
// this.mobileview.innerHTML = "";
// let element = document.createElement('transactions-element')
// element.setAttribute('name', fullname);
// element.setAttribute('mode', this.mode);
// this.mobileview.appendChild(element);
// localStorage.setItem("loyaltyname", fullname);
// console.log(phoneview)
// phoneview.showNavigation();
// }
// }
}
signup() {
console.log('loyalty.signup');
// var phoneview = document.getElementById("phoneview");
// var mobileview = phoneview.getMobileView();
this.mobileview.innerHTML = "";
var element = document.createElement('login-element');
getRandomUser((firstname, surname, password, email) => {
element.setAttribute('firstname', firstname);
element.setAttribute('surname', surname);
element.setAttribute('password', password);
element.setAttribute('email', email);
element.setAttribute('username', firstname + surname);
this.mobileview.appendChild(element);
})
/* same as mobileview.innerHTML =
'<login-element firstname="John surname="Lennon" password="######" username="john@email.com"></login-element>' */
}
parseJwt (token) {
var base64Url = token.split('.')[1];
var base64 = base64Url.replace('/-/g', '+').replace('/_/g', '/');
var jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
return JSON.parse(jsonPayload);
};
getCookie(cname) {
var name = cname + "=";
var decodedCookie = decodeURIComponent(document.cookie);
var ca = decodedCookie.split(';');
for(var i = 0; i <ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
}
// var loyalty = new Loyalty();
var loyalty = new Loyalty();

View File

@@ -0,0 +1,70 @@
class Navigation extends HTMLElement {
activeview = '';
getMobileView(){
var sr = this.shadowRoot;
// I don't like this being hard coded, but have stuggled to find a dynamic way for exampe: .childNodes.item("mobileview");
var mobileview = sr.host.parentElement.childNodes[3];
return mobileview;
}
constructor() {
super();
let template = document.getElementById('navigationview');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
setAllButtonsDisabled(){
var sr = this.shadowRoot;
this.buttonRow = sr.getElementById('buttonrow');
const buttonlist = Array.from(this.buttonRow.children);
buttonlist.forEach(function(node){
node.setDisabled();
})
}
connectedCallback(){
var sr = this.shadowRoot;
this.buttonRow = sr.getElementById('buttonrow');
var navelement = this;
this.buttonRow.addEventListener('NAV', e => {
console.log(e)
var id = e.detail.eventData.id;
// console.log('HOMESCREEN RECIEVED EVENT FROM NAV BUTTON: ' + id.toLocaleUpperCase());
this.setAllButtonsDisabled();
var button = sr.getElementById(id);
button.setEnabled();
navelement.activeview = id;
var mobileview = this.getMobileView();
mobileview.innerHTML = "<" + id + "-element></" + id +"-element>";
});
}
}
try {
customElements.define('navigation-element', Navigation);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,79 @@
class NavigationButton extends HTMLElement {
SELECTEDSUFFIX = '-selected.svg';
DESELECTEDSUFFIX = '-deselected.svg'
static get observedAttributes() {
return ['imagename','viewname','mode'];
}
constructor() {
super();
let template = document.getElementById('navigationbutton');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
setMode(mode){
this.mode = mode;
var imagestring = this.imagename;
if(this.mode=='active'){
imagestring = imagestring + this.SELECTEDSUFFIX;
}else{
imagestring = imagestring + this.DESELECTEDSUFFIX;
}
this.buttonimage.src = './images/' + imagestring;
}
setEnabled(){
this.setMode('active');
}
setDisabled(){
this.setMode('inactive');
}
connectedCallback(){
var customElement = this;
var sr = this.shadowRoot;
this.buttonimage = sr.getElementById('navbuttonimage');
this.button = sr.getElementById('navbutton');
// this.mode = customElement.getAttribute('mode');
this.viewname = customElement.getAttribute('viewname');
this.imagename = customElement.getAttribute('imagename')
this.setMode(customElement.getAttribute('mode'));
this.button.onclick = function () {
console.log('CLICKING NAV BUTTON: ' + customElement.viewname.toLocaleUpperCase());
var customEvent = new CustomEvent( 'NAV', {
detail: {
eventData: {"id":customElement.viewname}
},
bubbles: true
});
customElement.dispatchEvent(customEvent);
}
console.log('ADDING NAVIGATION BUTTON : ' + this.viewname.toLocaleUpperCase());
}
}
try {
customElements.define('navigationbutton-element', NavigationButton);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,54 @@
class Phone extends HTMLElement {
constructor() {
super();
console.log('INITIALIZING MOBILE PHONE');
let template = document.getElementById('phone');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
getMobileView(){
var sr = this.shadowRoot;
var mobileview = sr.getElementById('mobileview');
return mobileview;
}
showNavigation(){
var sr = this.shadowRoot;
var nav = sr.getElementById("mobilenavigation");
nav.style.display = "flex";
}
hideNavigation(){
var sr = this.shadowRoot;
var nav = sr.getElementById("mobilenavigation");
nav.style.display = "none";
}
connectedCallback() {
var sr = this.shadowRoot;
var phone = this;
var basebutton = sr.getElementById('basebutton');
var mobileview = sr.getElementById('mobileview');
var navigation = sr.getElementById('mobilenavigation');
var apptiles = sr.getElementById('APPTILES');
basebutton.addEventListener('click', e => {
mobileview.innerHTML = '<homescreen-element id="HOMESCREEN"></homescreen-element>';
phone.hideNavigation();
});
}
}
try {
customElements.define('phone-element', Phone);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,35 @@
class LoadingSpinner extends HTMLElement {
static get observedAttributes() { return ['status']; }
constructor() {
// Always call super first in constructor
super();
let template = document.getElementById('loadingspinner');
let templateContent = template.content;
console.log('INITIALIZING SPINNER')
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
attributeChangedCallback(name, oldValue, newValue) {
// if status attribute is set, change to custom status
console.log("ATTRIBUTE CHANGED")
if (name == "status") {
this.shadowRoot.getElementById("status").innerHTML = newValue
}
}
}
try {
customElements.define('loading-spinner-element', LoadingSpinner);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,72 @@
class Statistics extends HTMLElement {
events = ""
points = ""
name = ""
constructor() {
// Always call super first in constructor
super();
console.log('INITIALIZED ACCOUNT VIEW');
var customElement = this;
let template = document.getElementById('statistics');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
connectedCallback(){
console.log('INITIALIZING ANALYSIS');
var sr = this.shadowRoot;
var ctx = sr.getElementById('myChart');
getSpending(loyalty.getCookie('access_token'), (err, spending) => {
if (err == null) {
console.log(spending)
let labels = []
let values = []
spending.forEach(entry => {
labels.push(entry.category)
values.push(entry.amount)
})
let data = {
labels: labels,
datasets: [{
label: 'Spending Breakdown',
data: values,
backgroundColor: [
'rgba(178, 35, 60, 1.0)',
'rgba(229, 45, 78, 1.0)',
'rgba(236, 108, 131, 1.0)',
'rgba(244, 171, 184, 1.0)',
'rgba(252, 234, 237, 1.0)',
'rgba(102, 20, 34, 1.0)'
]
}]
};
let myDoughnutChart = new Chart(ctx, {
type: 'doughnut',
data: data
});
}
})
}
}
try {
customElements.define('statistics-element', Statistics);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,50 @@
class Tile extends HTMLElement {
static get observedAttributes() {
return ['tileimage', 'tiletext', 'limit', 'base'];
}
constructor() {
super();
let template = document.getElementById('tile');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
connectedCallback(){
var customElement = this;
var sr = this.shadowRoot;
this.tileimage = sr.getElementById('buttonImage');
this.tileimage.src = customElement.getAttribute('tileimage');
this.tiletext = customElement.getAttribute('tiletext');
this.limit=customElement.getAttribute('ceiling');
this.base=customElement.getAttribute('base');
this.button = sr.getElementById('tileButton');
this.button.onclick = function () {
console.log('CLICKING TILE: ' + customElement.tiletext.toLocaleUpperCase());
var customEvent = new CustomEvent( 'APPTILE', {
detail: {
eventData: {"name":customElement.tiletext,"limit":customElement.limit,"base":customElement.base}
},
bubbles: true
});
customElement.dispatchEvent(customEvent);
}
console.log('ADDING TILE : ' + this.tiletext.toLocaleUpperCase());
}
}
try {
customElements.define('tile-element', Tile);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,54 @@
class Transaction extends HTMLElement {
observables = ['vendor', 'date', 'amount', 'points'];
static get observedAttributes() {
return observables;
}
constructor() {
super();
let template = document.getElementById('transaction');
let templateContent = template.content;
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
connectedCallback() {
var sr = this.shadowRoot;
var transactionComponent = this;
console.log('LOADING TRANSACTION DATA');
this.observables.forEach(function(id){
var element = sr.getElementById(id);
element.innerHTML = transactionComponent.getAttribute(id);
})
// eventscomponent.addEventListener(eventid, e => {
// console.log(e.detail)
// let id_object = loyalty.parseJwt(loyalty.getCookie('id_token'))
// attendEvent(id_object.sub, e.detail.eventData)
// // re-attach this component
// let container = this.parentElement
// let content = container.innerHTML
// container.innerHTML = content
// });
}
}
try {
customElements.define('transaction-element', Transaction);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,94 @@
class Transactions extends HTMLElement {
balance = 0;
points = 0;
constructor() {
super();
let template = document.getElementById('transactions');
let templateContent = template.content;
console.log('INITIALIZING TRANSACTIONS VIEW')
const shadow = this.attachShadow({
mode: 'open'
})
.appendChild(templateContent.cloneNode(true));
}
createTransaction(vendor, date, amount, points){
var transaction = document.createElement('transaction-element');
transaction.setAttribute('vendor', vendor);
transaction.setAttribute('date', date);
if (amount != '-') amount = amount.toFixed(2);
if (points != '-') points = points.toFixed(2);
transaction.setAttribute('amount', amount);
transaction.setAttribute('points',points);
return transaction;
}
connectedCallback() {
var sr = this.shadowRoot;
var transactionlist = sr.getElementById('TRANSACTIONLIST');
var balance = sr.getElementById('BALANCE');
var points = sr.getElementById('POINTS');
var transactionComponent = this;
getTransactions(loyalty.getCookie('access_token'), (err, _transactions) => {
console.log(_transactions)
if (err == null) {
let transactions = _transactions.sort((a,b) => new Date(b.date) -new Date(a.date))
transactions.forEach(transaction => {
const date = new Date(transaction.date)
const year = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date)
const month = new Intl.DateTimeFormat('en', { month: 'short' }).format(date)
const day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date)
if (transaction.amount != null || transaction.amount != undefined) transactionComponent.balance += transaction.amount
if (transaction.pointsEarned != null || transaction.pointsEarned != undefined) transactionComponent.points += transaction.pointsEarned
if (transaction.amount == null || transaction.amount == undefined) transaction.amount = '-'
if (transaction.pointsEarned == null || transaction.pointsEarned == undefined) transaction.pointsEarned = '-'
let transactionElement = transactionComponent.createTransaction(transaction.transactionName, month + " " + day + " " + year, transaction.amount, transaction.pointsEarned)
transactionlist.appendChild(transactionElement)
})
balance.innerHTML = '$' + transactionComponent.balance.toFixed(2);
points.innerHTML = transactionComponent.points.toFixed(2);
} else if (err == 'User not registered') {
let phoneview = document.getElementById("phoneview");
let mobileview = phoneview.getMobileView();
mobileview.innerHTML = "";
let element = document.createElement('loading-spinner-element');
element.setAttribute("status", "User is marked for deletion...")
mobileview.appendChild(element)
phoneview.hideNavigation();
setTimeout(() => {
element.setAttribute("status", "Logging out...")
setTimeout(() => {
// clear cookies of tokens
document.cookie = "access_token=; Max-Age=0'"
document.cookie = "id_token=; Max-Age=0'"
// clear local storage
localStorage.clear()
mobileview.innerHTML = "";
var welcome = document.createElement('welcome-element')
welcome.setAttribute('mode','INTEGRATED')
mobileview.appendChild(welcome)
}, 2500)
}, 2000)
}
})
}
}
try {
customElements.define('transactions-element', Transactions);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}

View File

@@ -0,0 +1,108 @@
class Welcome extends HTMLElement {
constructor() {
super();
console.log('INITIALIZING WELCOME VIEW');
let template = document.getElementById('welcomeview');
let templateContent = template.content;
const shadow = this.attachShadow({mode: 'open'})
.appendChild(templateContent.cloneNode(true));
}
connectedCallback() {
let sr = this.shadowRoot;
let selectUserInput = sr.getElementById("usernameselect")
let signinButton = sr.getElementById("signin")
var phoneview = document.getElementById("phoneview");
var mobileview = phoneview.getMobileView();
if (loyalty.getCookie('access_token') != "" && loyalty.getCookie('id_token') != "") {
let id_object = loyalty.parseJwt(loyalty.getCookie('id_token'))
console.log(id_object)
var accountinfo = {
firstname: id_object.given_name,
surname: id_object.family_name
}
var fullname = accountinfo.firstname + ' ' + accountinfo.surname
mobileview.innerHTML = "";
let element = document.createElement('transactions-element')
element.setAttribute('name', fullname);
mobileview.appendChild(element);
localStorage.setItem("loyaltyname", fullname);
phoneview.showNavigation();
} else {
getAllUsers((users) => {
users.forEach(user => {
var option = document.createElement("option");
option.text = user
selectUserInput.add(option)
});
})
}
signinButton.addEventListener("click", e => {
this.signin(selectUserInput.value, selectUserInput.value)
})
}
signin(username, password) {
let sr = this.shadowRoot;
var mobileview = sr.host.parentElement;
mobileview.innerHTML = "";
// create loading spinner first
var element = document.createElement('loading-spinner-element');
element.setAttribute("status", "Logging in...")
mobileview.appendChild(element)
loginWithAppId(username, password, (jsonWebToken) => {
// when login complete,
// re-initialize app?
new Loyalty(this.mode);
let id_object = loyalty.parseJwt(jsonWebToken.id_token)
console.log(id_object)
var accountinfo = {
firstname: id_object.given_name,
surname: id_object.family_name
}
var fullname = accountinfo.firstname + ' ' + accountinfo.surname
mobileview.innerHTML = "";
let element = document.createElement('transactions-element')
element.setAttribute('name', fullname);
mobileview.appendChild(element);
localStorage.setItem("loyaltyname", fullname);
phoneview.showNavigation();
// edge case when unable to sign in
})
}
}
try {
customElements.define('welcome-element', Welcome);
} catch (err) {
const h3 = document.createElement('h3')
h3.innerHTML = err
document.body.appendChild(h3)
}