Merge branch 'feature/WW-13-wallet-list-page'

This commit is contained in:
Fran Jurmanović
2021-06-10 00:12:47 +02:00
18 changed files with 312 additions and 23 deletions

View File

@@ -116,7 +116,6 @@ class AppDropdownElement extends BaseComponentElement {
let _return = true; let _return = true;
const rules = this.rules?.split("|").filter((a) => a); const rules = this.rules?.split("|").filter((a) => a);
const value = (this.inp as HTMLSelectElement)?.value; const value = (this.inp as HTMLSelectElement)?.value;
console.log(_return, rules, value);
rules rules
.slice() .slice()
.reverse() .reverse()
@@ -146,7 +145,7 @@ class AppDropdownElement extends BaseComponentElement {
} }
render = (): TemplateResult => { render = (): TemplateResult => {
return html`<div data-target="app-dropdown.main"> return html`<div class="input-main" data-target="app-dropdown.main">
<select <select
data-target="app-dropdown.inp" data-target="app-dropdown.inp"
data-action="change:app-dropdown#onChange" data-action="change:app-dropdown#onChange"

View File

@@ -1,6 +1,7 @@
import { attr, controller, target } from "@github/catalyst"; import { attr, controller, target } from "@github/catalyst";
import { html, TemplateResult, unsafeHTML } from "@github/jtml"; import { html, TemplateResult, unsafeHTML } from "@github/jtml";
import { BaseComponentElement } from "common/"; import { BaseComponentElement } from "common/";
import { AppDropdownElement } from "components/app-dropdown/AppDropdownElement";
import { InputFieldElement } from "components/input-field/InputFieldElement"; import { InputFieldElement } from "components/input-field/InputFieldElement";
import { findMethod, isTrue, querys } from "core/utils"; import { findMethod, isTrue, querys } from "core/utils";
@@ -9,6 +10,7 @@ class AppFormElement extends BaseComponentElement {
@target formElement: HTMLElement; @target formElement: HTMLElement;
@target innerSlot: HTMLElement; @target innerSlot: HTMLElement;
@querys inputField: NodeListOf<InputFieldElement>; @querys inputField: NodeListOf<InputFieldElement>;
@querys appDropdown: NodeListOf<AppDropdownElement>;
@attr custom: string; @attr custom: string;
@attr hasCancel: string; @attr hasCancel: string;
slotted: any; slotted: any;
@@ -30,7 +32,7 @@ class AppFormElement extends BaseComponentElement {
} }
const actionString = this.custom; const actionString = this.custom;
const submitFunc = findMethod(actionString, this.appMain); const submitFunc = findMethod(actionString, this.appMain);
submitFunc?.(e); submitFunc?.(this.values);
return false; return false;
}; };
@@ -60,6 +62,21 @@ class AppFormElement extends BaseComponentElement {
} }
}; };
get values(): any {
const formObject: any = {};
this.inputField.forEach((input: InputFieldElement) => {
const inputType = input.inp;
formObject[input.name] = (inputType as HTMLInputElement).value;
});
this.appDropdown?.forEach((input: AppDropdownElement) => {
if (input.required && (input.inp as HTMLSelectElement).value) {
const inputType = input.inp;
formObject[input.name] = (inputType as HTMLSelectElement).value;
}
});
return formObject;
}
get valid() { get valid() {
let _valid = 0; let _valid = 0;
this.inputField?.forEach((input) => { this.inputField?.forEach((input) => {

View File

@@ -64,7 +64,7 @@ class AppMainElement extends HTMLElement {
}, },
{ {
path: "/:walletId", path: "/:walletId",
component: "history-page", component: "wallet-page",
layout: "menu-layout", layout: "menu-layout",
}, },
], ],
@@ -72,27 +72,27 @@ class AppMainElement extends HTMLElement {
{ {
path: "/register", path: "/register",
component: "register-page", component: "register-page",
layout: "menu-layout", layout: "initial-layout",
}, },
{ {
path: "/login", path: "/login",
component: "login-page", component: "login-page",
layout: "menu-layout", layout: "initial-layout",
}, },
{ {
path: "/unauthorized", path: "/unauthorized",
component: "login-page", component: "login-page",
layout: "menu-layout", layout: "initial-layout",
}, },
{ {
path: "/token-expired", path: "/token-expired",
component: "login-page", component: "login-page",
layout: "menu-layout", layout: "initial-layout",
}, },
{ {
path: "/not-found", path: "/not-found",
component: "not-found", component: "not-found",
layout: "menu-layout", layout: "initial-layout",
}, },
{ {
path: "/logout", path: "/logout",

View File

@@ -10,6 +10,7 @@ export * from "./app-dropdown/AppDropdownElement";
export * from "./app-loader/AppLoaderElement"; export * from "./app-loader/AppLoaderElement";
export * from "./circle-loader/CircleLoaderElement"; export * from "./circle-loader/CircleLoaderElement";
export * from "./app-form/AppFormElement"; export * from "./app-form/AppFormElement";
export * from "./wallet-header/WalletHeaderElement";
// LAST // LAST
export * from "./app-main/AppMainElement"; export * from "./app-main/AppMainElement";

View File

@@ -111,7 +111,7 @@ class InputFieldElement extends BaseComponentElement {
/>`; />`;
}; };
return html`<div data-target="input-field.main"> return html`<div class="input-main" data-target="input-field.main">
${renderMessage(this.label)} ${renderInput(this.type)} ${renderMessage(this.label)} ${renderInput(this.type)}
${renderError(this.displayError, this.error)} ${renderError(this.displayError, this.error)}
</div>`; </div>`;

View File

@@ -0,0 +1,70 @@
import { attr, controller, target } from "@github/catalyst";
import { html, TemplateResult } from "@github/jtml";
import { BaseComponentElement } from "common/";
import { CircleLoaderElement } from "components/circle-loader/CircleLoaderElement";
import { findMethod } from "core/utils";
@controller
class WalletHeaderElement extends BaseComponentElement {
@attr currentBalance: number;
@attr lastMonth: number;
@attr nextMonth: number;
@attr currency: string;
@attr custom: string;
fetchFunc: Function = () => {};
constructor() {
super();
}
elementConnected = (): void => {
this.executeFetch();
this.update();
};
attributeChangedCallback(): void {
this.update();
}
executeFetch = async (options?): Promise<void> => {
const actionString = this.custom;
const submitFunc = findMethod(actionString, this.appMain);
try {
this.loader?.start?.();
await submitFunc(options);
this.loader?.stop?.();
} catch (err) {
this.loader?.stop?.();
console.error(err);
}
};
render = (): TemplateResult => {
const { currentBalance, currency, lastMonth, nextMonth } = this;
const renderItem = (header, balance, currency) => html`<div>
<div>${header}</div>
<div><span>${balance}</span><span>${currency}</span></div>
</div>`;
const renderHeader = () => {
if (this.loader && this.loader.loading) {
return html`<circle-loader></circle-loader>`;
}
return html`${renderItem(
"Last Month",
lastMonth,
currency
)}${renderItem(
"Current Balance",
currentBalance,
currency
)}${renderItem("Next Month", nextMonth, currency)}`;
};
return html`<div>${renderHeader()}</div>`;
};
}
export type { WalletHeaderElement };

View File

@@ -1 +1,2 @@
export * from "./menu-layout/MenuLayoutElement"; export * from "./menu-layout/MenuLayoutElement";
export * from "./initial-layout/InitialLayoutElement";

View File

@@ -0,0 +1,31 @@
import { controller, target } from "@github/catalyst";
import { closest } from "core/utils";
import { html, TemplateResult } from "@github/jtml";
import { BaseLayoutElement } from "common/layouts";
import { AppMainElement } from "components/";
@controller
class InitialLayoutElement extends BaseLayoutElement {
@closest appMain: AppMainElement;
@target appPage: HTMLDivElement;
constructor() {
super();
}
elementConnected = (): void => {
this.update();
};
elementDisconnected = (appMain: AppMainElement): void => {};
render = (): TemplateResult => {
return html`
<div data-target="initial-layout.appPage">
<app-slot data-target="initial-layout.appSlot"></app-slot>
</div>
`;
};
}
export type { InitialLayoutElement };

View File

@@ -1,12 +1,13 @@
import { controller } from "@github/catalyst"; import { controller, target } from "@github/catalyst";
import { html, TemplateResult, until } from "@github/jtml"; import { html, TemplateResult, until } from "@github/jtml";
import { PingService } from "services/"; import { WalletService } from "services/";
import { AppMainElement } from "components/"; import { AppMainElement, WalletHeaderElement } from "components/";
import { BasePageElement } from "common/"; import { BasePageElement } from "common/";
@controller @controller
class HomePageElement extends BasePageElement { class HomePageElement extends BasePageElement {
private pingService: PingService; @target walletHeader: WalletHeaderElement;
private walletService: WalletService;
constructor() { constructor() {
super({ super({
title: "Home", title: "Home",
@@ -14,25 +15,31 @@ class HomePageElement extends BasePageElement {
} }
elementConnected = (): void => { elementConnected = (): void => {
this.pingService = new PingService(this.appMain?.appService); this.walletService = new WalletService(this.appMain?.appService);
this.update(); this.update();
this.appMain.addEventListener("tokenchange", this.update); this.appMain.addEventListener("tokenchange", this.update);
this.getBalance();
}; };
elementDisconnected = (appMain: AppMainElement): void => { elementDisconnected = (appMain: AppMainElement): void => {
appMain?.removeEventListener("tokenchange", this.update); appMain?.removeEventListener("tokenchange", this.update);
}; };
getPong = async (): Promise<void> => { getBalance = async (): Promise<void> => {
try { try {
const response = await this.pingService.getAll(); const response = await this.walletService.getBalance();
this.setBalance(response);
} catch (err) { } catch (err) {
throw err; throw err;
} }
}; };
pongEl = (): TemplateResult => { setBalance = (header) => {
return html`<div>${until(this.getPong())}</div>`; if (!this.walletHeader) return;
this.walletHeader.currency = header.currency;
this.walletHeader.currentBalance = header.currentBalance || "0";
this.walletHeader.lastMonth = header.lastMonth || "0";
this.walletHeader.nextMonth = header.nextMonth || "0";
}; };
openModal = (): void => { openModal = (): void => {
@@ -47,6 +54,14 @@ class HomePageElement extends BasePageElement {
render = (): TemplateResult => { render = (): TemplateResult => {
return html` return html`
<button data-action="click:home-page#openModal">New Wallet</button> <button data-action="click:home-page#openModal">New Wallet</button>
<wallet-header
data-target="home-page.walletHeader"
data-current-balance="0"
data-last-month="0"
data-next-month="0"
data-currency="0"
data-custom="home-page#getBalance"
></wallet-header>
`; `;
}; };
} }

View File

@@ -7,3 +7,4 @@ export * from "./history-page/HistoryPageElement";
export * from "./wallet-list/WalletListElement"; export * from "./wallet-list/WalletListElement";
export * from "./wallet-create/WalletCreateElement"; export * from "./wallet-create/WalletCreateElement";
export * from "./transaction-create/TransactionCreateElement"; export * from "./transaction-create/TransactionCreateElement";
export * from "./wallet-page/WalletPageElement";

View File

@@ -51,15 +51,22 @@ class TransactionCreateElement extends BasePageElement {
} catch (err) {} } catch (err) {}
}; };
onSubmit = async (): Promise<void> => { onSubmit = async (values): Promise<void> => {
try { try {
if (!this.validate()) { if (!this.validate()) {
return; return;
} }
const { name: description, wallet: walletId } = this.values;
const {
description: description,
wallet: walletId,
amount,
} = values;
const response = await this.transactionService.post({ const response = await this.transactionService.post({
description, description,
walletId, walletId,
amount,
}); });
if (response?.id) { if (response?.id) {
@@ -90,10 +97,17 @@ class TransactionCreateElement extends BasePageElement {
data-custom="transaction-create#onSubmit" data-custom="transaction-create#onSubmit"
data-has-cancel="true" data-has-cancel="true"
> >
<input-field
data-type="number"
data-name="amount"
data-label="Amount"
data-targets="transaction-create.inputs"
data-rules="required"
></input-field>
<input-field <input-field
data-type="text" data-type="text"
data-name="name" data-name="description"
data-label="Name" data-label="Description"
data-targets="transaction-create.inputs" data-targets="transaction-create.inputs"
data-rules="required" data-rules="required"
></input-field> ></input-field>

View File

@@ -0,0 +1,105 @@
import { controller, target } from "@github/catalyst";
import { html, TemplateResult } from "@github/jtml";
import { TransactionsService, WalletService } from "services/";
import {
AppMainElement,
AppPaginationElement,
WalletHeaderElement,
} from "components/";
import { BasePageElement } from "common/";
@controller
class WalletPageElement extends BasePageElement {
private transactionsService: TransactionsService;
private walletService: WalletService;
@target pagination: AppPaginationElement;
@target walletHeader: WalletHeaderElement;
walletId: string;
constructor() {
super({
title: "Wallet",
});
}
elementConnected = (): void => {
this.walletService = new WalletService(this.appMain?.appService);
this.transactionsService = new TransactionsService(
this.appMain?.appService
);
if (this?.routerService?.routerState?.data) {
const { walletId } = this?.routerService?.routerState?.data;
if (walletId) {
this.walletId = walletId;
}
}
this.update();
this.pagination?.setFetchFunc?.(this.getTransactions, true)!;
this.appMain.addEventListener("tokenchange", this.update);
};
elementDisconnected = (appMain: AppMainElement): void => {
appMain?.removeEventListener("tokenchange", this.update);
};
getTransactions = async (options): Promise<any> => {
try {
if (this?.routerService?.routerState?.data) {
const { walletId } = this?.routerService?.routerState?.data;
if (walletId) {
options["walletId"] = walletId;
}
}
const response = await this.transactionsService.getAll(options);
return response;
} catch (err) {
throw err;
}
};
getBalance = async (): Promise<void> => {
try {
const response = await this.walletService.getBalance({
walletId: this.walletId,
});
this.setBalance(response);
} catch (err) {
throw err;
}
};
setBalance = (header) => {
if (!this.walletHeader) return;
this.walletHeader.currency = header.currency;
this.walletHeader.currentBalance = header.currentBalance || "0";
this.walletHeader.lastMonth = header.lastMonth || "0";
this.walletHeader.nextMonth = header.nextMonth || "0";
};
render = (): TemplateResult => {
const renderHeader = () => html`<wallet-header
data-target="wallet-page.walletHeader"
data-current-balance="0"
data-last-month="0"
data-next-month="0"
data-currency="0"
data-custom="wallet-page#getBalance"
></wallet-header>`;
const renderWallet = () => {
if (this.routerService?.routerState?.data?.walletId) {
return html`<span
>${this.routerService?.routerState?.data?.walletId}</span
>`;
}
return html``;
};
return html`<div>
${renderHeader()} ${renderWallet()}
<app-pagination
data-target="wallet-page.pagination"
></app-pagination>
</div>`;
};
}
export type { WalletPageElement };

View File

@@ -4,6 +4,14 @@ class WalletService extends BaseService {
constructor(appService: AppService) { constructor(appService: AppService) {
super("/wallet", appService); super("/wallet", appService);
} }
getBalance = (params?: Object, headers?: HeadersInit) => {
return this.appService.get(
this.endpoint + "/wallet-header",
params,
headers
);
};
} }
export default WalletService; export default WalletService;

View File

@@ -0,0 +1,20 @@
app-form {
form[data-target="app-form.formElement"] {
width: 56%;
margin: 0 auto;
input-field,
app-dropdown > .input-main {
width: 100%;
display: block;
input,
select {
width: 100%;
padding: 2px 0;
margin: 6px 0;
display: block;
font-size: 16px;
}
}
}
}

View File

@@ -0,0 +1 @@
@import "./app-form.scss";

View File

@@ -0,0 +1 @@
@import "./menu-layout.scss";

View File

@@ -0,0 +1,3 @@
[data-target="input-field.main"] {
width: 100%;
}

View File

@@ -6,3 +6,5 @@
@import "./app-loader/index.scss"; @import "./app-loader/index.scss";
@import "./circle-loader/index.scss"; @import "./circle-loader/index.scss";
@import "./page/index.scss"; @import "./page/index.scss";
@import "./app-form/index.scss";
@import "./layout/index.scss";