diff --git a/src/components/app-main/AppMainElement.ts b/src/components/app-main/AppMainElement.ts index e1e3a68..d1078b6 100644 --- a/src/components/app-main/AppMainElement.ts +++ b/src/components/app-main/AppMainElement.ts @@ -124,11 +124,8 @@ class AppMainElement extends HTMLElement { const _modalElement = document.createElement(element); const _divEl = document.createElement("div"); _modalElement.setAttribute("data-target", "app-modal.modalElement"); - _modalElement.setAttribute( - "data-action", - "click:app-main#preventClosing" - ); _divEl.setAttribute("data-target", "app-modal.modalContent"); + _divEl.setAttribute("data-action", "click:app-main#preventClosing"); _divEl.appendChild(_modalElement); return _divEl; }; diff --git a/src/components/app-menu/AppMenuElement.ts b/src/components/app-menu/AppMenuElement.ts index 40d6ef9..7610a56 100644 --- a/src/components/app-menu/AppMenuElement.ts +++ b/src/components/app-menu/AppMenuElement.ts @@ -1,7 +1,8 @@ -import { controller } from "@github/catalyst"; +import { controller, target } from "@github/catalyst"; import { html, TemplateResult } from "@github/jtml"; import { BaseComponentElement } from "common/"; import { AppMainElement } from "components/app-main/AppMainElement"; +import { MenuItemElement } from "components/menu-item/MenuItemElement"; import { WalletService } from "services/"; @controller @@ -9,6 +10,7 @@ class AppMenuElement extends BaseComponentElement { private walletService: WalletService; private walletData: Array; private totalWallets: number; + @target walletlist: MenuItemElement; constructor() { super(); } @@ -68,11 +70,32 @@ class AppMenuElement extends BaseComponentElement { return null; }; + openModal = (): void => { + const _modal = this.appMain.appModal; + if (_modal) { + this.appMain.closeModal(); + } else { + this.appMain.createModal("wallet-create"); + } + }; + render = (): TemplateResult => { const { isAuth, totalWallets, walletData } = this; - const regularMenu = (path: string, title: string): TemplateResult => - html`${title}`; + const regularMenu = ( + path: string, + title: string, + action?: string + ): TemplateResult => { + if (action) { + return html` + ${title} + `; + } + return html`${title}`; + }; const authMenu = (path: string, title: string): TemplateResult => { if (isAuth) { return regularMenu(path, title); @@ -87,22 +110,29 @@ class AppMenuElement extends BaseComponentElement { }; const renderWallets = (wallets: Array) => { if (isAuth && totalWallets > 0) { - return html`${wallets.map((wallet) => - regularMenu(`/wallet/${wallet.id}`, wallet.name) - )}`; + return html` + ${wallets.map((wallet) => + regularMenu(`/wallet/${wallet.id}`, wallet.name) + )}`; } return html``; }; - const otherWallets = () => { + const otherWallets = (action: string) => { if (isAuth && totalWallets > 2) { - return regularMenu("/wallet/all", "Other"); + return regularMenu("/wallet/all", "Other Wallets", action); } return html``; }; + const menuHeader = (title) => + html``; + return html`
- ${regularMenu("/", "Home")} ${authMenu("/history", "History")} - ${renderWallets(walletData)} ${otherWallets()} + ${menuHeader("Wallets")} ${regularMenu("/", "Home")} + ${authMenu("/history", "Transaction History")} + ${renderWallets(walletData)} + ${otherWallets("click:app-menu#openModal")} + ${authMenu("/logout", "Logout")} ${notAuthMenu("/login", "Login")} ${notAuthMenu("/register", "Register")} diff --git a/src/components/app-pagination/AppPaginationElement.ts b/src/components/app-pagination/AppPaginationElement.ts index 1357fea..0a11f0d 100644 --- a/src/components/app-pagination/AppPaginationElement.ts +++ b/src/components/app-pagination/AppPaginationElement.ts @@ -99,9 +99,9 @@ class AppPaginationElement extends BaseComponentElement { ? this.customRenderItems : () => { if (items?.length > 0) { - return html` + return html`
${items?.map((item) => renderItem(item))} - `; +
`; } return html``; }; diff --git a/src/components/menu-item/MenuItemElement.ts b/src/components/menu-item/MenuItemElement.ts index 098cea1..548be7e 100644 --- a/src/components/menu-item/MenuItemElement.ts +++ b/src/components/menu-item/MenuItemElement.ts @@ -7,7 +7,9 @@ import { BaseComponentElement } from "common/"; class MenuItemElement extends BaseComponentElement { @attr path: string; @attr title: string; + @attr customaction: string; @target itemEl: HTMLElement; + @target customButton: HTMLDivElement; constructor() { super(); } @@ -37,6 +39,14 @@ class MenuItemElement extends BaseComponentElement { data-target="menu-item.itemEl" > ${this.title} + ${this.customaction + ? html`
+ Add +
` + : html``}
`; }; diff --git a/src/core/store/AuthStore.ts b/src/core/store/AuthStore.ts index af8edf7..fcb84d4 100644 --- a/src/core/store/AuthStore.ts +++ b/src/core/store/AuthStore.ts @@ -1,5 +1,6 @@ import { AppMainElement } from "components/"; import { AppService } from "core/services"; +import { isTrue } from "core/utils"; import { AuthService } from "services/"; class AuthStore { @@ -13,8 +14,10 @@ class AuthStore { private appMain: AppMainElement, private appService: AppService ) { - this.token = localStorage.getItem("token"); + const _token = localStorage.getItem("token"); + if (_token) this.token = _token; this.authService = new AuthService(this.appService); + this.checkToken(_token); } get token(): string { @@ -26,6 +29,7 @@ class AuthStore { set token(token: string) { const { _token } = this; const _changed = token != _token; + console.log(token); if (_changed) { this._token = token; localStorage.setItem("token", token); @@ -41,6 +45,19 @@ class AuthStore { this._userDetails = userDetails; } + checkToken = async (token: string) => { + try { + const response = await this.authService.checkToken({ token }); + if (!(response && response.valid)) { + this.token = null; + this.appMain.routerService.goTo("/token-expired"); + } + } catch (err) { + this.token = null; + this.appMain.routerService.goTo("/token-expired"); + } + }; + userLogin = async (formObject) => { try { const response = await this.authService.login(formObject); diff --git a/src/index.html b/src/index.html index 8cda3af..f3bc4ea 100644 --- a/src/index.html +++ b/src/index.html @@ -7,6 +7,15 @@ Wallet Web + \ No newline at end of file diff --git a/src/layouts/menu-layout/MenuLayoutElement.ts b/src/layouts/menu-layout/MenuLayoutElement.ts index 94b1184..2805cb3 100644 --- a/src/layouts/menu-layout/MenuLayoutElement.ts +++ b/src/layouts/menu-layout/MenuLayoutElement.ts @@ -1,4 +1,4 @@ -import { controller } from "@github/catalyst"; +import { controller, target } from "@github/catalyst"; import { closest } from "core/utils"; import { html, TemplateResult } from "@github/jtml"; import { BaseLayoutElement } from "common/layouts"; @@ -7,6 +7,7 @@ import { AppMainElement } from "components/"; @controller class MenuLayoutElement extends BaseLayoutElement { @closest appMain: AppMainElement; + @target appPage: HTMLDivElement; constructor() { super(); @@ -38,8 +39,10 @@ class MenuLayoutElement extends BaseLayoutElement { render = (): TemplateResult => { const _isAuth = this.isAuth; return html` - ${_isAuth ? html`` : html``} - +
+ ${_isAuth ? html`` : html``} + +
`; }; } diff --git a/src/services/AuthService.ts b/src/services/AuthService.ts index 1828f04..96f7d9a 100644 --- a/src/services/AuthService.ts +++ b/src/services/AuthService.ts @@ -10,6 +10,13 @@ class PingService extends BaseService { register = (data?: Object, headers?: HeadersInit) => { return this.appService.post(this.endpoint + "/register", data, headers); }; + checkToken = (params?: Object, headers?: HeadersInit) => { + return this.appService.get( + this.endpoint + "/check-token", + params, + headers + ); + }; } export default PingService; diff --git a/src/styles/core/colors.scss b/src/styles/core/colors.scss new file mode 100644 index 0000000..0143386 --- /dev/null +++ b/src/styles/core/colors.scss @@ -0,0 +1,90 @@ +$white: #ffffff; +$black: #181818; + +$gray-01: #ebeaea; +$gray-02: #d6d4d4; +$gray-03: #c5c5c5; +$gray-04: #aeacac; +$gray-05: #979696; +$gray-06: #8f8f8f; +$gray-07: #7e7e7e; +$gray-08: #6b6b6b; +$gray-09: #4d4d4d; +$gray-10: #303030; + +$red-01: #fcb0b0; +$red-02: #f88282; +$red-03: #ea5656; +$red-04: #df2424; +$red-05: #d60909; +$red-06: #bd0000; +$red-07: #a61010; +$red-08: #970202; +$red-09: #840c0c; +$red-10: #630101; + +$orange-01: #fecc91; +$orange-02: #fdc17b; +$orange-03: #fbb563; +$orange-04: #f6a13c; +$orange-05: #f6a13c; +$orange-06: #ff971e; +$orange-07: #fb9145; +$orange-08: #f68533; +$orange-09: #e96607; +$orange-10: #d4620f; + +$yellow-01: #fff59e; +$yellow-02: #f8eb7e; +$yellow-03: #feed56; +$yellow-04: #fce93c; +$yellow-05: #f8e221; +$yellow-06: #edd606; +$yellow-07: #e9d521; +$yellow-08: #e5d114; +$yellow-09: #dec802; +$yellow-10: #c1ae00; + +$green-01: #adff87; +$green-02: #7ffd43; +$green-03: #7ffd43; +$green-04: #64f91e; +$green-05: #43eb0c; +$green-06: #53d914; +$green-07: #44c307; +$green-08: #3caf06; +$green-09: #389c08; +$green-10: #287c00; + +$blue-01: #9bedff; +$blue-02: #61e3ff; +$blue-03: #1bd4fd; +$blue-04: #09c1ea; +$blue-05: #08b1d7; +$blue-06: #2c80ff; +$blue-07: #0a62e7; +$blue-08: #004fc7; +$blue-09: #0549b0; +$blue-10: #043581; + +$purple-01: #cab1ff; +$purple-02: #b295f0; +$purple-03: #a47df8; +$purple-04: #7f49f2; +$purple-05: #6f2cff; +$purple-06: #4e0dd7; +$purple-07: #4e0dd7; +$purple-08: #3a0a9f; +$purple-09: #2b0679; +$purple-10: #210362; + +$pink-01: #fda5ff; +$pink-02: #f87cfb; +$pink-03: #f151f4; +$pink-04: #ea10ee; +$pink-05: #d213d6; +$pink-06: #be07c1; +$pink-07: #a40fa7; +$pink-08: #97069a; +$pink-09: #820c85; +$pink-10: #600362; diff --git a/src/styles/core/index.scss b/src/styles/core/index.scss new file mode 100644 index 0000000..51c0195 --- /dev/null +++ b/src/styles/core/index.scss @@ -0,0 +1,2 @@ +@import "./colors.scss"; +@import "./main.scss"; diff --git a/src/styles/core/main.scss b/src/styles/core/main.scss new file mode 100644 index 0000000..9a9a9c6 --- /dev/null +++ b/src/styles/core/main.scss @@ -0,0 +1,5 @@ +app-main { + * { + font-family: Roboto; + } +} diff --git a/src/styles/main.scss b/src/styles/main.scss index baa4e90..f8a34a6 100644 --- a/src/styles/main.scss +++ b/src/styles/main.scss @@ -1,3 +1,6 @@ +@import "./core//index.scss"; @import "./thorn/index.scss"; +@import "./menu-item/index.scss"; @import "./sidebar/index.scss"; @import "./modal/index.scss"; +@import "./table/index.scss"; diff --git a/src/styles/menu-item/index.scss b/src/styles/menu-item/index.scss new file mode 100644 index 0000000..cb57874 --- /dev/null +++ b/src/styles/menu-item/index.scss @@ -0,0 +1 @@ +@import "./menu-item.scss" \ No newline at end of file diff --git a/src/styles/menu-item/menu-item.scss b/src/styles/menu-item/menu-item.scss new file mode 100644 index 0000000..8752433 --- /dev/null +++ b/src/styles/menu-item/menu-item.scss @@ -0,0 +1,71 @@ +.menu-item { + &.divider { + display: block; + height: 1px; + width: 80%; + margin: 1px auto; + border-bottom: 1px solid $gray-08; + } + &.menu-header { + flex: 1; + align-self: center; + text-align: center; + text-transform: uppercase; + text-decoration: underline; + margin: 8px auto; + font-family: Roboto; + font-size: 38px !important; + } +} +menu-item { + [data-target="menu-item.itemEl"] { + display: grid; + grid-template-columns: 1fr auto; + grid-template-areas: "main custom"; + app-link { + [data-target="app-link.main"] { + grid-area: main; + display: flex; + align-items: center; + background-color: $black; + color: $gray-01; + border-radius: 0; + padding: 2px 0; + height: 50px; + text-align: left; + padding-left: 80px; + &:hover { + color: $white; + background-color: $gray-10; + } + } + } + &.selected { + app-link { + [data-target="app-link.main"] { + background-color: $gray-09; + } + } + } + [data-target="menu-item.customButton"] { + grid-area: custom; + display: none; + } + &:hover { + [data-target="menu-item.customButton"] { + grid-area: custom; + display: flex; + align-items: center; + justify-content: center; + width: 50px; + height: 50px; + background-color: $blue-09; + cursor: pointer; + user-select: none; + &:hover { + background-color: $blue-08; + } + } + } + } +} diff --git a/src/styles/modal/modal.scss b/src/styles/modal/modal.scss index 4c8de49..79abe36 100644 --- a/src/styles/modal/modal.scss +++ b/src/styles/modal/modal.scss @@ -11,14 +11,20 @@ app-modal { overflow-y: auto; [data-target="app-modal.modalContent"] { + position: absolute; z-index: 1005; - top: 5%; - width: 1080px; + width: 960px; + min-height: 320px; + max-height: 560px; padding-bottom: 10px; - margin: 25px auto; - background: #ffffff; + margin: 0; + top: 50%; + left: 50%; + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + background: $gray-08; box-shadow: 1px 1px 5px -5px #868686; - border-radius: 0.5em; + border-radius: 3px; } } } diff --git a/src/styles/sidebar/sidebar.scss b/src/styles/sidebar/sidebar.scss index 602a14e..60f3931 100644 --- a/src/styles/sidebar/sidebar.scss +++ b/src/styles/sidebar/sidebar.scss @@ -1,47 +1,29 @@ -app-menu { - [data-target="app-menu.sidebar"] { - margin: 0; - padding: 0; - width: 200px; - background-color: #f1f1f1; - position: fixed; - height: 100%; - overflow: auto; - top: 0; - left: 0; +menu-layout { + [data-target="menu-layout.appPage"] { + display: grid; + width: 100%; + min-height: 100vh; + grid-template-columns: 301px auto; + grid-template-areas: "sidebar content"; - menu-item { - [data-target="menu-item.itemEl"] { - app-link { - [data-target="app-link.main"] { - width: 100%; - height: 25px; - background-color: #828282; - color: #d5d5d5; - border-radius: 0; - padding-bottom: 25px; - margin: 1px auto; - &:hover { - background-color: #82878a; - } - } - } - &.selected { - app-link { - [data-target="app-link.main"] { - color: #1a1a1a; - background-color: #6e838d; - } - } - } + app-menu { + [data-target="app-menu.sidebar"] { + grid-area: sidebar; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 301px; + border-right: 1px solid $gray-08; + background-color: $black; + } + } + + app-slot { + [data-target="base-layout.content"] { + grid-area: content; + margin: 15px; } } } } - -app-slot { - [data-target="base-layout.content"] { - margin-left: 200px; - padding: 1px 16px; - } -} diff --git a/src/styles/table/index.scss b/src/styles/table/index.scss new file mode 100644 index 0000000..da51a4b --- /dev/null +++ b/src/styles/table/index.scss @@ -0,0 +1 @@ +@import "./table.scss" \ No newline at end of file diff --git a/src/styles/table/table.scss b/src/styles/table/table.scss new file mode 100644 index 0000000..d8c7d3a --- /dev/null +++ b/src/styles/table/table.scss @@ -0,0 +1,10 @@ +.table { + display: table; + tr { + display: table-row; + td { + display: table-cell; + border: 1px solid $gray-05; + } + } +}