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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ccc;stroke-linejoin:round;stroke-width:20px}</style></defs><title>account-deselected</title><path d="M250.14,50a35.72,35.72,0,1,0,35.72,35.71A35.71,35.71,0,0,0,250.14,50ZM221.57,450V321.43c-18.5-6.67-28.57-21-28.57-39.86V207.14a57.15,57.15,0,0,1,114.29,0v74.27c0,18.88-10.08,33.33-28.58,40V450Z" class="cls-1"/></svg>

After

Width:  |  Height:  |  Size: 450 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ff002e;stroke-linejoin:round;stroke-width:20px}</style></defs><title>account-selected</title><path d="M250.14,50a35.72,35.72,0,1,0,35.72,35.71A35.71,35.71,0,0,0,250.14,50ZM221.57,450V321.43c-18.5-6.67-28.57-21-28.57-39.86V207.14a57.15,57.15,0,0,1,114.29,0v74.27c0,18.88-10.08,33.33-28.58,40V450Z" class="cls-1"/></svg>

After

Width:  |  Height:  |  Size: 451 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ff7e00;stroke-miterlimit:10;stroke-width:18px}</style></defs><title>admin</title><g id="design_and_development_02" data-name="design and development 02"><g id="design_and_development_02-2" data-name="design and development 02"><path d="M414.67,79a6.34,6.34,0,1,1-6.34-6.33A6,6,0,0,1,414.67,79ZM383,72.67A6.33,6.33,0,1,0,389.33,79,6,6,0,0,0,383,72.67Zm-25.33,0A6.33,6.33,0,1,0,364,79,6,6,0,0,0,357.67,72.67Z" class="cls-1"/><path d="M98,148.67H224.67M98,186.67H224.67M98,224.67h76" class="cls-1"/><path d="M440,326H60V60H440ZM60,364H440M60,98H440M60,402H440M60,440H440M351.33,136A50.67,50.67,0,1,0,402,186.67,50.81,50.81,0,0,0,351.33,136Zm0,50.67,44.34-25.34m-44.34,25.34L307,161.33m44.33,25.34L326,231" class="cls-1"/></g></g></svg>

After

Width:  |  Height:  |  Size: 865 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{font-size:60px;font-family:IBMPlexSans, IBM Plex Sans;}.cls-1,.cls-3{fill:#39687e;}.cls-2{letter-spacing:-0.01em;}</style></defs><title>bank</title><text class="cls-1" transform="translate(171.25 457.12)"><tspan class="cls-2">B</tspan><tspan x="38.58" y="0">ANK</tspan></text><rect class="cls-3" x="100" y="324.57" width="300" height="21.43"/><path class="cls-3" d="M367.86,142.43a10.71,10.71,0,0,0,10.71-10.72V99.57A10.71,10.71,0,0,0,371.5,89.5L253.64,46.64a10.71,10.71,0,0,0-7.28,0L128.5,89.5a10.71,10.71,0,0,0-7.07,10.07v32.14a10.71,10.71,0,0,0,10.71,10.72h10.72V281.71H121.43v21.43H378.57V281.71H357.14V142.43Zm-225-35.36L250,68.07l107.14,39V121H142.86ZM271.43,281.71H228.57V142.43h42.86ZM164.28,142.43h42.86V281.71H164.28ZM335.72,281.71H292.86V142.43h42.86Z"/></svg>

After

Width:  |  Height:  |  Size: 886 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#39687e;}</style></defs><title>banklogo</title><rect class="cls-1" x="50" y="421.44" width="400.01" height="28.57"/><path class="cls-1" d="M407.15,178.58a14.28,14.28,0,0,0,14.28-14.29V121.43A14.29,14.29,0,0,0,412,108L254.86,50.86a14.36,14.36,0,0,0-9.72,0L88,108a14.29,14.29,0,0,0-9.43,13.43v42.86a14.28,14.28,0,0,0,14.28,14.29h14.29V364.29H78.57v28.58H421.43V364.29H392.86V178.58Zm-300-47.15L250,79.43l142.86,52V150H107.14ZM278.57,364.29H221.43V178.58h57.14ZM135.71,178.58h57.15V364.29H135.71ZM364.29,364.29H307.14V178.58h57.15Z"/></svg>

After

Width:  |  Height:  |  Size: 657 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:#ff7e00;}.cls-2{font-size:60px;font-family:IBMPlexSans, IBM Plex Sans;}</style></defs><title>cafe</title><rect class="cls-1" x="105.17" y="325.31" width="289.66" height="20.69"/><path class="cls-1" d="M337.93,149.45H167.24a20.71,20.71,0,0,0-20.69,20.69V252.9a51.79,51.79,0,0,0,51.73,51.72H281a51.79,51.79,0,0,0,51.73-51.72V242.55h5.17a46.55,46.55,0,1,0,0-93.1ZM312.07,252.9a31.07,31.07,0,0,1-31,31H198.28a31.07,31.07,0,0,1-31-31V170.14H312.07Zm25.86-31h-5.17V170.14h5.17a25.86,25.86,0,1,1,0,51.72Z"/><path class="cls-1" d="M281,128.76H260.34v-1.51a20.54,20.54,0,0,0-11.43-18.5L221.15,94.86a41.13,41.13,0,0,1-22.87-37V46H219V57.86a20.58,20.58,0,0,0,11.43,18.5l27.76,13.88a41.13,41.13,0,0,1,22.87,37Z"/><text class="cls-2" transform="translate(177.88 457.12)">CAFE</text></svg>

After

Width:  |  Height:  |  Size: 902 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#555861;stroke-miterlimit:10;stroke-width:20px}</style></defs><title>cloud</title><path d="M450,248.67A77.39,77.39,0,0,1,372.67,326h-1.34" class="cls-1"/><path d="M136.67,326C87.33,319.33,50,276.67,50,226A99.86,99.86,0,0,1,150,126c13.33,0,26.67,2.67,37.33,8C203.33,99.33,238,76.67,278,76.67a99.71,99.71,0,0,1,100,94.66,77.34,77.34,0,0,1,72,77.34" class="cls-1"/><path d="M170,276.67l80-80,80,80M250,423.33V196.67" class="cls-1"/></svg>

After

Width:  |  Height:  |  Size: 567 B

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
.st0{fill:#494A4B;}
.st1{fill:#FF002E;}
</style>
<path class="st0" d="M130,280h105v30H130V280z M130,340h240v30H130V340z M130,400h240v30H130V400z"/>
<title>Deploy rules</title>
<polygon class="st1" points="280,70 190,160 211.1,181.1 265,127.4 265,310 295,310 295,127.4 348.9,181.1 370,160 "/>
</svg>

After

Width:  |  Height:  |  Size: 692 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ccc;stroke-linejoin:round;stroke-width:20px}</style></defs><title>eventlist-deselected</title><g id="list_bullet" data-name="list bullet"><path id="list_bullet-2" d="M130,90A40,40,0,1,1,90,50,40,40,0,0,1,130,90ZM90,370a40,40,0,1,0,40,40A40,40,0,0,0,90,370Zm0-160a40,40,0,1,0,40,40A40,40,0,0,0,90,210ZM183.33,90H450M183.33,250H450M183.33,410H450" class="cls-1" data-name="list bullet"/></g></svg>

After

Width:  |  Height:  |  Size: 528 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ff002e;stroke-linejoin:round;stroke-width:20px}</style></defs><title>eventlist-selected</title><g id="list_bullet" data-name="list bullet"><path id="list_bullet-2" d="M130,90A40,40,0,1,1,90,50,40,40,0,0,1,130,90ZM90,370a40,40,0,1,0,40,40A40,40,0,0,0,90,370Zm0-160a40,40,0,1,0,40,40A40,40,0,0,0,90,210ZM183.33,90H450M183.33,250H450M183.33,410H450" class="cls-1" data-name="list bullet"/></g></svg>

After

Width:  |  Height:  |  Size: 529 B

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<style type="text/css">
.st0{fill:#494A4B;}
</style>
<path class="st0" d="M12.3,27.9c-0.4-0.2-0.6-0.5-0.5-0.9l1.6-10.2H9.2c-0.5,0-0.9-0.4-0.9-0.8c0-0.1,0-0.1,0-0.2l2.6-11.1
C11,4.3,11.4,4,11.8,4h8.6c0.3,0,0.5,0.1,0.7,0.3c0.2,0.2,0.2,0.5,0.2,0.7l-1.5,6.7h4.1c0.3,0,0.6,0.2,0.8,0.5
c0.1,0.3,0.1,0.6-0.1,0.9L13.3,27.6c-0.2,0.2-0.4,0.4-0.7,0.4C12.5,28,12.4,28,12.3,27.9z M17.6,13.4l1.7-7.7h-6.8l-2.2,9.4h5.1
L14,24l8.1-10.5H17.6z"/>
<title>Flash</title>
</svg>

After

Width:  |  Height:  |  Size: 824 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:#ff7e00;}.cls-2{font-size:60px;font-family:IBMPlexSans, IBM Plex Sans;}</style></defs><title>fuel</title><polygon class="cls-1" points="205.61 255.08 187.25 244.06 209.65 206.71 156.08 206.71 197.96 136.92 216.32 147.94 193.92 185.29 247.49 185.29 205.61 255.08"/><path class="cls-1" d="M400,99.57H389.29V67.43H367.86V99.57H357.14v64.29h10.72V287.07a16.08,16.08,0,0,1-32.15,0V196A10.7,10.7,0,0,0,325,185.29H282.14V78.14a10.71,10.71,0,0,0-10.71-10.71H132.14a10.72,10.72,0,0,0-10.71,10.71v225H100v21.43H303.57V303.14H282.14V206.71h32.15v80.36a37.5,37.5,0,0,0,75,0V163.86H400ZM260.71,303.14H142.86V88.86H260.71Z"/><text class="cls-2" transform="translate(180.37 457.12)">FUEL</text></svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:#39687e;}.cls-2{font-size:60px;font-family:IBMPlexSans, IBM Plex Sans;}.cls-3{letter-spacing:-0.01em;}</style></defs><title>groceries</title><circle class="cls-1" cx="203.36" cy="320.03" r="20.67"/><circle class="cls-1" cx="348.06" cy="320.03" r="20.67"/><path class="cls-1" d="M389.41,103H160.16l-8.48-43.41a10.34,10.34,0,0,0-10.34-8.27H100V72h32.87l39.48,198.45a10.34,10.34,0,0,0,10.34,8.27H368.74V258H191.16l-8.47-41.35H368.74a10.33,10.33,0,0,0,10.33-8.06l20.67-93A10.33,10.33,0,0,0,389.41,103Zm-28.94,93H178.76l-14.47-72.35h212.2Z"/><text class="cls-2" transform="translate(86.77 457.12)">G<tspan class="cls-3" x="41.7" y="0">R</tspan><tspan x="79.5" y="0">OCERIES</tspan></text></svg>

After

Width:  |  Height:  |  Size: 816 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2,.cls-3{fill:none;stroke-linejoin:round}.cls-1,.cls-2{stroke:#494a4b;stroke-width:19px}.cls-2{stroke:#ff7e00}.cls-3{stroke:#ff002e;stroke-linecap:round;stroke-width:20px}</style></defs><title>istio</title><path d="M370,90H250V410H370M129.93,250H370" class="cls-1"/><circle cx="90" cy="250" r="40" class="cls-2" transform="translate(-55.03 27.37) rotate(-13.28)"/><circle cx="410" cy="410" r="40" class="cls-3" transform="translate(-83.23 105.17) rotate(-13.28)"/><circle cx="410" cy="90" r="40" class="cls-3" transform="translate(-9.71 96.61) rotate(-13.28)"/><circle cx="410" cy="250" r="40" class="cls-3" transform="translate(-46.47 100.89) rotate(-13.28)"/></svg>

After

Width:  |  Height:  |  Size: 787 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:none;stroke:#555861;stroke-width:20px;stroke-linejoin:round}.cls-2{fill:#ff002e;stroke:#ff002e;stroke-width:.25px}</style></defs><title>lightbulb</title><g id="innovate"><g id="innovate-2" data-name="innovate"><path id="patterns-ideas-creativity-04" d="M250,55.23c64.6,0,114,51.94,114,117.8,0,31.67-13.93,63.34-36.73,86.14-26.6,27.86-26.6,59.53-26.6,81.06v19H199.33v-19c0-21.53,0-53.2-26.6-81.06C149.93,235.1,136,204.7,136,173c0-65.86,49.4-117.8,114-117.8" class="cls-1"/></g></g><path id="gear" d="M276.76,169.14a26.86,26.86,0,1,1-26.86-26.86A26.59,26.59,0,0,1,276.76,169.14ZM314.37,181V155.17H297.18l-5.37-11.82,11.81-11.82-18.26-18.26-11.82,11.82-11.82-5.37V103.6H235.94v17.19l-11.82,5.37L212.3,114.34,194,132.61l11.82,11.82-5.38,11.81H184.37V182h17.19l5.37,11.82-11.82,11.82,18.27,18.26,11.81-11.82L237,217.48V233.6H262.8V216.41L274.62,211l11.81,11.82,18.27-18.27-11.82-11.82L298.25,181Z" class="cls-2"/><line x1="199.33" x2="300.67" y1="388.1" y2="388.1" class="cls-1"/><line x1="199.33" x2="300.67" y1="416.43" y2="416.43" class="cls-1"/><line x1="212" x2="288" y1="444.77" y2="444.77" class="cls-1"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" focusable="false" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
<style type="text/css">
.st0{fill:#494A4B;stroke:#535455;}
</style>
<path d="M23.59 19.41L26 22 21 22 21 24 26 24 23.59 26.59 25 28 30 23 25 18 23.59 19.41zM13 6A9 9 0 005.52 20l1.66-1.11A7 7 0 1113 22H2v2H13A9 9 0 0013 6z"></path>
<title>Loop</title>
</svg>

After

Width:  |  Height:  |  Size: 622 B

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:none;stroke:#39687E;stroke-width:28;stroke-linecap:round;stroke-linejoin:round;}
.st2{fill:#FF7E00;}
</style>
<title>loyaltylogo</title>
<rect class="st0" width="500" height="500"/>
<g id="credit_card">
<path id="credit_card-2" class="st1" d="M440.7,396.7H59.3c-16.2,0-29.3-13.1-29.3-29.3V132.7c0-16.2,13.2-29.3,29.3-29.3h381.3
c16.2,0,29.3,13.1,29.3,29.3v234.7C470,383.5,456.8,396.6,440.7,396.7z M30,162h440 M30,206h440"/>
</g>
<rect x="41" y="143.7" class="st2" width="418" height="82.1"/>
</svg>

After

Width:  |  Height:  |  Size: 908 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:none;stroke:#535455;stroke-width:9px}.cls-1{stroke-linejoin:round}.cls-2{stroke-miterlimit:10}</style></defs><title>newyork</title><g id="nyc_brooklyn" data-name="nyc brooklyn"><g id="nyc_brookklyn" data-name="nyc brookklyn"><line x1="375" x2="375" y1="187.5" y2="229.17" class="cls-1"/><line x1="333.33" x2="333.33" y1="187.5" y2="229.17" class="cls-1"/><polygon points="385.42 125 385.42 187.5 322.92 187.5 322.92 125 354.17 104.17 385.42 125" class="cls-1"/><polyline points="208.33 333.33 208.33 93.75 93.75 93.75" class="cls-2"/><line x1="166.67" x2="166.67" y1="250" y2="291.67" class="cls-1"/><line x1="166.67" x2="166.67" y1="187.5" y2="229.17" class="cls-1"/><line x1="166.67" x2="166.67" y1="125" y2="166.67" class="cls-1"/><line x1="187.5" x2="187.5" y1="250" y2="291.67" class="cls-1"/><line x1="187.5" x2="187.5" y1="187.5" y2="229.17" class="cls-1"/><line x1="187.5" x2="187.5" y1="125" y2="166.67" class="cls-1"/><line x1="145.83" x2="145.83" y1="250" y2="291.67" class="cls-1"/><line x1="145.83" x2="145.83" y1="187.5" y2="229.17" class="cls-1"/><line x1="145.83" x2="145.83" y1="125" y2="166.67" class="cls-1"/><line x1="125" x2="125" y1="250" y2="291.67" class="cls-1"/><line x1="125" x2="125" y1="187.5" y2="229.17" class="cls-1"/><line x1="125" x2="125" y1="125" y2="166.67" class="cls-1"/><line x1="104.17" x2="104.17" y1="250" y2="291.67" class="cls-1"/><line x1="104.17" x2="104.17" y1="187.5" y2="229.17" class="cls-1"/><line x1="104.17" x2="104.17" y1="125" y2="166.67" class="cls-1"/><polyline points="125 406.25 125 333.33 291.67 333.33" class="cls-2"/><polyline points="291.67 406.25 291.67 229.17 406.25 229.17" class="cls-2"/><line x1="208.33" x2="208.33" y1="375" y2="406.25" class="cls-2"/><line x1="375" x2="375" y1="302.08" y2="333.33" class="cls-1"/><line x1="333.33" x2="333.33" y1="302.08" y2="333.33" class="cls-1"/><line x1="375" x2="375" y1="354.17" y2="385.42" class="cls-1"/><line x1="333.33" x2="333.33" y1="354.17" y2="385.42" class="cls-1"/><line x1="333.33" x2="333.33" y1="250" y2="281.25" class="cls-1"/><line x1="375" x2="375" y1="250" y2="281.25" class="cls-1"/><polyline points="166.67 406.25 166.67 375 250 375 250 406.25" class="cls-2"/><polyline points="250 333.33 250 166.67 208.33 166.67" class="cls-2"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FF002E;}
.st1{fill:#494A4B;}
</style>
<path class="st0" d="M146.9,96.2v51.4H95.4V96.2H146.9 M69.7,70.5v102.9h102.9V70.5H69.7z M275.4,134.8v51.4H224v-51.4H275.4
M198.3,109.1v102.9h102.9V109.1H198.3z M146.9,250.5v51.4H95.4v-51.4H146.9 M69.7,224.8v102.9h102.9V224.8H69.7z"/>
<path class="st1" d="M326.9,173.4v77.1h-77.1v77.1h-77.1v102.9h257.1V173.4H326.9z M275.4,276.2h51.4v51.4h-51.4V276.2z
M249.7,404.8h-51.4v-51.4h51.4V404.8z M326.9,404.8h-51.4v-51.4h51.4V404.8z M404,404.8h-51.4v-51.4H404V404.8z M404,327.6h-51.4
v-51.4H404V327.6z M352.6,250.5v-51.4H404v51.4H352.6z"/>
<title>Development</title>
</svg>

After

Width:  |  Height:  |  Size: 995 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ccc;stroke-linejoin:round;stroke-width:20px;}</style></defs><title>reservation-deselected</title><path class="cls-1" d="M196.67,90h0Zm-80,0H63.33V450H436.67V90h-320Zm0,160H223.33V196.67H116.67Zm240-133.33V63.33a13.34,13.34,0,0,0-26.67,0v53.34a13.34,13.34,0,0,0,26.67,0Zm-186.67,0V63.33a13.34,13.34,0,0,0-26.67,0v53.34a13.34,13.34,0,0,0,26.67,0ZM116.67,370H223.33V316.67H116.67Zm160-120H383.33V196.67H276.67Zm0,120H383.33V316.67H276.67Z"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:none;stroke:#ff002e;stroke-linejoin:round;stroke-width:20px}</style></defs><title>reservation-selected</title><path d="M196.67,90h0Zm-80,0H63.33V450H436.67V90h-320Zm0,160H223.33V196.67H116.67Zm240-133.33V63.33a13.34,13.34,0,0,0-26.67,0v53.34a13.34,13.34,0,0,0,26.67,0Zm-186.67,0V63.33a13.34,13.34,0,0,0-26.67,0v53.34a13.34,13.34,0,0,0,26.67,0ZM116.67,370H223.33V316.67H116.67Zm160-120H383.33V196.67H276.67Zm0,120H383.33V316.67H276.67Z" class="cls-1"/></svg>

After

Width:  |  Height:  |  Size: 577 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:#ff002e;}.cls-2{font-size:60px;font-family:IBMPlexSans, IBM Plex Sans;}.cls-3{letter-spacing:-0.01em;}.cls-4{letter-spacing:-0.06em;}</style></defs><title>restaurant</title><path class="cls-1" d="M200.87,185.29,115.15,99.57,100,114.72l70.56,70.57H100V196a150,150,0,0,0,300,0V185.29ZM250,324.57A128.75,128.75,0,0,1,121.87,206.71H378.13A128.75,128.75,0,0,1,250,324.57Z"/><path class="cls-1" d="M314.29,110.29A53.44,53.44,0,0,0,297.46,113,85.59,85.59,0,0,0,176,96.14L125.87,46,110.71,61.15,175.54,126l7.57-7.58a63.84,63.84,0,0,1,45.46-18.83,64.5,64.5,0,0,1,50.22,24.26,54.26,54.26,0,0,0-6.32,6.54,32,32,0,0,1-25.1,12.06H207.14v21.43h40.23a53.35,53.35,0,0,0,41.82-20.09,32.14,32.14,0,0,1,57.24,20.09h21.43A53.63,53.63,0,0,0,314.29,110.29Z"/><text class="cls-2" transform="translate(65.08 457.12)">RE<tspan class="cls-3" x="73.38" y="0">S</tspan><tspan class="cls-4" x="107.46" y="0">T</tspan><tspan class="cls-3" x="137.88" y="0">A</tspan><tspan x="175.56" y="0">URANT</tspan></text></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:#ff002e;}.cls-2{font-size:60px;font-family:IBMPlexSans, IBM Plex Sans;}</style></defs><title>rideshare</title><path class="cls-1" d="M392.93,174.19,310.11,144.4l-34.72-43.5a32.17,32.17,0,0,0-24.85-11.79H164.82a32.14,32.14,0,0,0-26.46,14.15l-29,42.85A53.64,53.64,0,0,0,100,176v84.53a10.72,10.72,0,0,0,10.71,10.72h22.93a42.86,42.86,0,0,0,82.72,0h67.28a42.86,42.86,0,0,0,82.72,0h22.93A10.72,10.72,0,0,0,400,260.54V184.26A10.71,10.71,0,0,0,392.93,174.19ZM175,282a21.43,21.43,0,1,1,21.43-21.43A21.43,21.43,0,0,1,175,282Zm150,0a21.43,21.43,0,1,1,21.43-21.43A21.43,21.43,0,0,1,325,282Zm53.57-32.14H366.36a42.86,42.86,0,0,0-82.72,0H216.36a42.86,42.86,0,0,0-82.72,0H121.43V176A32.14,32.14,0,0,1,127,157.9L156,115a10.71,10.71,0,0,1,8.89-4.5h85.71a10.73,10.73,0,0,1,8.25,3.86l36.43,45.75a11.76,11.76,0,0,0,4.72,3.43l78.53,28.18Z"/><text class="cls-2" transform="translate(79.54 457.12)">RIDE SHARE</text></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#ff002e}.cls-2,.cls-3{fill:none;stroke-linejoin:round;stroke-width:20px}.cls-2{stroke:#555861}.cls-3{stroke:#ff002e;stroke-linecap:round}</style></defs><title>secure</title><circle id="_Path_" cx="250" cy="265" r="10.67" class="cls-1" data-name="&lt;Path&gt;"/><path d="M170,90H370a80,80,0,0,1,0,160H330m-160,0H130a80,80,0,0,0,0,160H330" class="cls-2"/><path d="M223.33,210V176.67a26.67,26.67,0,0,1,53.34,0V210M250,252.67v20m0-69.34a53.34,53.34,0,1,0,53.33,53.34A53.49,53.49,0,0,0,250,203.33Z" class="cls-3"/><circle cx="90" cy="90" r="40" class="cls-3"/><circle cx="410" cy="410" r="40" class="cls-3"/></svg>

After

Width:  |  Height:  |  Size: 729 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#ccc;}</style></defs><title>statsicongrey</title><path class="cls-1" d="M216.07,440a149.29,149.29,0,0,1,0-298.57A13.56,13.56,0,0,1,229.64,155V277.14H351.79a13.58,13.58,0,0,1,13.57,13.57A149.29,149.29,0,0,1,216.07,440ZM202.5,169.39a122.14,122.14,0,1,0,134.9,134.9H229.64a27.15,27.15,0,0,1-27.14-27.15Z"/><path class="cls-1" d="M419.64,222.86H297.5a27.15,27.15,0,0,1-27.14-27.15V73.57A13.57,13.57,0,0,1,283.93,60,149.28,149.28,0,0,1,433.21,209.29,13.57,13.57,0,0,1,419.64,222.86ZM297.5,195.71H405.26A122.14,122.14,0,0,0,297.5,88Z"/></svg>

After

Width:  |  Height:  |  Size: 656 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#ff002e;}</style></defs><title>statsiconred</title><path class="cls-1" d="M216.07,440a149.29,149.29,0,0,1,0-298.57A13.56,13.56,0,0,1,229.64,155V277.14H351.79a13.58,13.58,0,0,1,13.57,13.57A149.29,149.29,0,0,1,216.07,440ZM202.5,169.39a122.14,122.14,0,1,0,134.9,134.9H229.64a27.15,27.15,0,0,1-27.14-27.15Z"/><path class="cls-1" d="M419.64,222.86H297.5a27.15,27.15,0,0,1-27.14-27.15V73.57A13.57,13.57,0,0,1,283.93,60,149.28,149.28,0,0,1,433.21,209.29,13.57,13.57,0,0,1,419.64,222.86ZM297.5,195.71H405.26A122.14,122.14,0,0,0,297.5,88Z"/></svg>

After

Width:  |  Height:  |  Size: 658 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 500 500"><defs><style>.cls-1,.cls-2{fill:#fff;stroke-miterlimit:10;stroke-width:20px}.cls-1{stroke:#555861}.cls-2{stroke:#ff002e}</style></defs><title>threat</title><g id="strategy_play" data-name="strategy play"><path id="strategy_play-2" d="M272.38,189.86l57.34,55.94m-55.94,0,55.94-55.94M174.48,50l57.34,55.94m-55.95,0L231.82,50m138.46,97.9,57.34,55.95m-55.94,0,55.94-55.95M92,92V343.71c0,69.93,69.93,69.93,69.93,69.93H245.8M119.93,119.93,92,92l-28,28M385.66,78l-28-28-28,28m28-28V92c0,42-42,42-42,42H259.79c-55.94,0-55.94,55.94-55.94,55.94v69.93" class="cls-1" data-name="strategy play"/></g><ellipse cx="399.65" cy="315.31" class="cls-2" rx="28.01" ry="27.92" transform="translate(-105.9 374.93) rotate(-45)"/><ellipse cx="301.75" cy="315.31" class="cls-2" rx="28.01" ry="27.92" transform="translate(-134.57 305.7) rotate(-45)"/><ellipse cx="301.75" cy="413.21" class="cls-2" rx="28.01" ry="27.92" transform="translate(-203.8 334.38) rotate(-45)"/><ellipse cx="203.85" cy="315.31" class="cls-2" rx="28.01" ry="27.92" transform="translate(-163.25 236.48) rotate(-45)"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#ccc;}</style></defs><title>crediticongrey</title><path class="cls-1" d="M152.2,233H301.48v27.14H152.2Zm0,67.85H328.63V328H152.2Z"/><path class="cls-1" d="M423.63,97.28H97.91a27.14,27.14,0,0,0-27.14,27.14V395.85A27.15,27.15,0,0,0,97.91,423H423.63a27.15,27.15,0,0,0,27.14-27.15V124.42A27.14,27.14,0,0,0,423.63,97.28Zm0,27.14v27.15H97.91V124.42ZM97.91,395.85V178.71H423.63V395.85Z"/></svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@@ -0,0 +1 @@
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><defs><style>.cls-1{fill:#ff002e;stroke:#ff002e;stroke-linejoin:round;stroke-width:0.25px;}</style></defs><title>crediticonred</title><path class="cls-1" d="M141.43,233H290.71v27.14H141.43Zm0,67.85H317.86V328H141.43Z"/><path class="cls-1" d="M412.86,97.28H87.14A27.14,27.14,0,0,0,60,124.42V395.85A27.15,27.15,0,0,0,87.14,423H412.86A27.15,27.15,0,0,0,440,395.85V124.42A27.14,27.14,0,0,0,412.86,97.28Zm0,27.14v27.15H87.14V124.42ZM87.14,395.85V178.71H412.86V395.85Z"/></svg>

After

Width:  |  Height:  |  Size: 566 B

File diff suppressed because it is too large Load Diff

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)
}

View File

@@ -0,0 +1 @@
<a id="sched-embed" href="//clouddevconf.sched.com/" data-sched-bg="dark">View the Cloud Dev Conf schedule &amp; directory.</a><script type="text/javascript" src="//clouddevconf.sched.com/js/embed.js"></script>

View File

@@ -0,0 +1,132 @@
:root {
--loyalty-background-color: white;
--loyalty-app-color: white;
--loyalty-text-color: #494A4B;
--loyalty-button-color: #FF7E00;
--loyalty-highlight-color: #FF002E;
--loyalty-phone-color: #39687E;
--loyalty-sensor-color: #88a4b1;
--loyalty-divide-color: aliceblue;
--loyalty-highlight-color: #fff2e5;
}
.loyalty {
padding: 0;
margin: 0;
background-color: var(--loyalty-background-color);
/* #F5F8FA; #33729b; #9f805e; */
/* font-family: 'Open Sans', sans-serif;*/
font-family: 'IBM Plex Sans', sans-serif;
/* font-family: 'Questrial', sans-serif; */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
display: flex;
flex-direction: row;
justify-content: center;
color: var(--loyalty-text-color);
}
.container {
width: 900px;
height: 600px;
margin: 70px;
background: var(--loyalty-app-color);
display: flex;
flex-direction: row;
}
.navigation {
display: flex;
/* min-height: 15%;
max-height:15%; */
flex-direction: column;
width: 50%;
padding-right: 50px;
}
.app {
display: flex;
flex-direction: column;
justify-content: center;
align-content: center;
align-items: center;
width: 50%;
/* background: aliceblue; */
}
.titlebar {
display: flex;
flex-direction: row;
}
.logo {
display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
}
.icon {
width: 40px;
}
.title {
display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
align-items: center;
margin: 10px;
text-transform: uppercase;
font-weight: bold;
}
.about {
display: flex;
flex-direction: row;
justify-content: left;
align-content: center;
align-items: center;
margin: 10px;
margin-left: 5px;
text-transform: uppercase;
font-weight: normal;
font-size: 12px;
line-height: 18px;
word-spacing: 2px;
padding-bottom: 20px;
}
.instruction {
display: flex;
flex-direction: row;
justify-content: left;
align-content: center;
align-items: center;
margin: 10px;
margin-left: 5px;
text-transform: uppercase;
font-weight: bold;
font-size: 16px;
line-height: 20px;
word-spacing: 2px;
color: var(--loyalty-text-color);
}
.linkbar {
display: flex;
flex-direction: row;
margin-top: 20px;
}
.linktext {
display: flex;
flex-direction: row;
justify-content: center;
align-content: center;
align-items: center;
margin: 10px;
text-transform: uppercase;
font-weight: bold;
font-size: 14px;
}

View File

@@ -0,0 +1,61 @@
<template id="transaction">
<style>
.transactiondata{
}
.transactionlist{
font-size: 12px;
font-weight: bold;
}
.transactionitem{
display: flex;
flex-direction: row;
padding-top: 10px;
color:var(--loyalty-text-color);
}
.transactionvendor{
display: flex;
flex-direction: column;
min-width: 100px;
}
.vendorname{
}
.transactiondate{
font-size:10px;
padding-top: 2px;
font-weight: normal;
}
.transactionamount{
display: flex;
flex-direction: row;
justify-content: flex-end;
justify-items: center;
min-width: 70px;
}
.transactionpoints{
display: flex;
flex-direction: row;
justify-content: flex-end;
justify-items: center;
min-width: 70px;
}
</style>
<div class="transactionitem">
<div class="transactionvendor">
<label id="vendor" class="vendorname"></label>
<label id="date" class="transactiondate"></label>
</div>
<label id="amount" class="transactionamount"></label>
<label id="points" class="transactionpoints"></label>
</div>
</template>