mirror of
https://github.com/FJurmanovic/wallet-web.git
synced 2026-02-06 06:08:10 +00:00
added transaction date to transaction form
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@github/catalyst": "^1.1.3",
|
||||
"dayjs": "^1.10.5",
|
||||
"lit-html": "^1.4.1",
|
||||
"validator": "^13.6.0"
|
||||
},
|
||||
|
||||
@@ -79,6 +79,10 @@ class BaseElement extends HTMLElement {
|
||||
|
||||
update = (): void => {
|
||||
render(this.render(), this);
|
||||
if (this.shadowRoot) {
|
||||
const renderSlot = () => html`<slot><slot></slot></slot>`;
|
||||
render(renderSlot(), this.shadowRoot);
|
||||
}
|
||||
this.bindEvents('data-action');
|
||||
this.bindEvents('app-action');
|
||||
this.updateCallback();
|
||||
|
||||
@@ -39,6 +39,7 @@ class Validator {
|
||||
.reverse()
|
||||
.map((rule) => {
|
||||
let args = [];
|
||||
let inps = [];
|
||||
if (rule.includes('[') && rule.includes(']')) {
|
||||
const begSep = rule.lastIndexOf('[');
|
||||
const endSep = rule.lastIndexOf(']');
|
||||
@@ -51,7 +52,7 @@ class Validator {
|
||||
const begBr = arg.lastIndexOf('(');
|
||||
const endBr = arg.lastIndexOf(')');
|
||||
const field = arg.slice(begBr + 1, endBr);
|
||||
|
||||
inps = [...inps, this.form.getInput(field)];
|
||||
return this.form?.values[field];
|
||||
}
|
||||
});
|
||||
@@ -69,10 +70,19 @@ class Validator {
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
const error = ruleArray
|
||||
let error = ruleArray
|
||||
? validRule?.[1]?.replaceAll('{- name}', firstUpper(this.name?.toString()))
|
||||
: validatorErrors[rule]?.replaceAll('{- name}', firstUpper(this.name?.toString()));
|
||||
if (error) {
|
||||
if (inps?.length > 1) {
|
||||
inps.forEach((arg) => {
|
||||
if (arg) {
|
||||
error.replaceAll(`{- ${arg?.type}}`, firstUpper(arg?.name?.toString()));
|
||||
}
|
||||
});
|
||||
} else if (inps?.length == 1) {
|
||||
error = error.replaceAll('{- field}', firstUpper(inps[0]?.name?.toString()));
|
||||
}
|
||||
this.error = error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ class AppDropdownElement extends BaseComponentElement {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
validate = (): boolean => {
|
||||
validate = (change = false): boolean => {
|
||||
return this.validator.validate();
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ class AppFormElement extends BaseComponentElement {
|
||||
@querys inputField: NodeListOf<InputFieldElement>;
|
||||
@querys appDropdown: NodeListOf<AppDropdownElement>;
|
||||
@attr custom: string;
|
||||
@attr renderInput: string;
|
||||
@attr hasCancel: string;
|
||||
slotted: any;
|
||||
isValid: boolean = false;
|
||||
@@ -24,6 +25,10 @@ class AppFormElement extends BaseComponentElement {
|
||||
return findMethod(this.custom, this.appMain);
|
||||
}
|
||||
|
||||
get customRender() {
|
||||
return findMethod(this.renderInput, this.appMain);
|
||||
}
|
||||
|
||||
public inputChange = (e) => {
|
||||
this.validate();
|
||||
this.update();
|
||||
@@ -103,13 +108,15 @@ class AppFormElement extends BaseComponentElement {
|
||||
}
|
||||
|
||||
elementConnected = (): void => {
|
||||
if (this.renderInput) {
|
||||
this.update();
|
||||
} else {
|
||||
const _template = document.createElement('template');
|
||||
const _slot = this.innerHTML;
|
||||
_template.innerHTML = _slot;
|
||||
this.innerHTML = null;
|
||||
this.update();
|
||||
|
||||
this.formElement.replaceChild(_template.content, this.innerSlot);
|
||||
this.formElement?.replaceChild(_template.content, this.innerSlot);
|
||||
}
|
||||
};
|
||||
|
||||
render = (): TemplateResult => {
|
||||
@@ -139,7 +146,7 @@ class AppFormElement extends BaseComponentElement {
|
||||
return html`
|
||||
<div class="app-form">
|
||||
<form app-action="submit:app-form#onSubmit" data-target="app-form.formElement">
|
||||
<slot data-target="app-form.innerSlot"></slot>
|
||||
${this.renderInput ? this.customRender() : html`<slot data-target="app-form.innerSlot"></slot>`}
|
||||
${renderError(this.error)}
|
||||
<div class="form-buttons">
|
||||
<div class="button-content">${renderSubmit(this.isValid)}${renderCancel(isTrue(this.hasCancel))}</div>
|
||||
|
||||
@@ -13,7 +13,7 @@ class AppMainElement extends HTMLElement {
|
||||
public authStore: AuthStore;
|
||||
private httpClient: HttpClient;
|
||||
public appService: AppService;
|
||||
public shadow: any;
|
||||
//public shadow: any;
|
||||
@target appModal: AppModalElement;
|
||||
@target mainRoot: AppRootElement;
|
||||
@target appLoader: AppLoaderElement;
|
||||
|
||||
@@ -13,12 +13,14 @@ class InputFieldElement extends BaseComponentElement {
|
||||
@attr type: string;
|
||||
@attr label: string;
|
||||
@attr rules: string;
|
||||
@attr customAction: string;
|
||||
@target main: HTMLElement;
|
||||
@target inp: HTMLElement;
|
||||
@closest appForm: AppFormElement;
|
||||
valid: boolean;
|
||||
displayError: boolean;
|
||||
randId: string;
|
||||
changed: boolean = false;
|
||||
|
||||
validator: Validator;
|
||||
|
||||
@@ -54,7 +56,15 @@ class InputFieldElement extends BaseComponentElement {
|
||||
}
|
||||
|
||||
validate = (): boolean => {
|
||||
return this.validator.validate();
|
||||
const valid = this.validator.validate();
|
||||
if (valid && this.displayError) {
|
||||
this.displayError = false;
|
||||
this.update();
|
||||
} else if (this.changed && !valid) {
|
||||
this.displayError = true;
|
||||
this.update();
|
||||
}
|
||||
return valid;
|
||||
};
|
||||
|
||||
validateDisplay = () => {
|
||||
@@ -69,6 +79,9 @@ class InputFieldElement extends BaseComponentElement {
|
||||
};
|
||||
|
||||
inputChange = (e) => {
|
||||
if (!this.changed && e?.target?.value) {
|
||||
this.changed = true;
|
||||
}
|
||||
this.validate();
|
||||
this.appForm?.inputChange(e);
|
||||
};
|
||||
@@ -96,6 +109,7 @@ class InputFieldElement extends BaseComponentElement {
|
||||
app-action="
|
||||
input:input-field#inputChange
|
||||
blur:input-field#validateDisplay
|
||||
${this.customAction ? this.customAction : ''}
|
||||
"
|
||||
/>`;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import isEmail from 'validator/lib/isEmail';
|
||||
import isDate from 'validator/lib/isDate';
|
||||
import isNumeric from 'validator/lib/isNumeric';
|
||||
import isAfter from 'validator/lib/isAfter';
|
||||
import matches from 'validator/lib/matches';
|
||||
|
||||
const validator = {
|
||||
@@ -10,6 +11,7 @@ const validator = {
|
||||
matches: matches,
|
||||
is_same: [isSame, '{- name} needs to be same to {- field}.'],
|
||||
required: [required, '{- name} is required.'],
|
||||
is_after: [isAfter, '{- name} needs to be after {- field}.'],
|
||||
};
|
||||
|
||||
function required(str: string): boolean {
|
||||
|
||||
@@ -43,6 +43,14 @@ class SubscriptionCreateElement extends BasePageElement {
|
||||
}
|
||||
};
|
||||
|
||||
get hasEndCheck(): InputFieldElement | AppDropdownElement {
|
||||
for (const i in this.inputs) {
|
||||
if (this.inputs[i]?.name == 'hasEnd') {
|
||||
return this.inputs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get nameInput(): InputFieldElement | AppDropdownElement {
|
||||
for (const i in this.inputs) {
|
||||
if (this.inputs[i]?.name == 'name') {
|
||||
@@ -148,10 +156,16 @@ class SubscriptionCreateElement extends BasePageElement {
|
||||
return _return;
|
||||
}
|
||||
|
||||
render = (): TemplateResult => {
|
||||
const renderInput = (type, name, label, rules, hide?) => {
|
||||
onCheck = () => {
|
||||
this.appForm.update();
|
||||
this.appForm.validate();
|
||||
this.appForm.update();
|
||||
};
|
||||
|
||||
renderForms = () => {
|
||||
const renderInput = (type, name, label, rules, hide?, customAction?) => {
|
||||
if (hide) {
|
||||
return html``;
|
||||
return null;
|
||||
}
|
||||
return html`<input-field
|
||||
data-type="${type}"
|
||||
@@ -159,6 +173,7 @@ class SubscriptionCreateElement extends BasePageElement {
|
||||
data-label="${label}"
|
||||
data-targets="subscription-create.inputs"
|
||||
data-rules="${rules}"
|
||||
data-custom-action="${customAction || ''}"
|
||||
></input-field>`;
|
||||
};
|
||||
|
||||
@@ -174,15 +189,19 @@ class SubscriptionCreateElement extends BasePageElement {
|
||||
data-fetch="${fetch}"
|
||||
></app-dropdown>`;
|
||||
};
|
||||
|
||||
return html`
|
||||
<app-form
|
||||
data-custom="subscription-create#onSubmit"
|
||||
data-has-cancel="true"
|
||||
data-target="subscription-create.appForm"
|
||||
>
|
||||
<div slot="inputs">
|
||||
${renderInput('number', 'amount', 'Amount', 'required')}
|
||||
${renderInput('text', 'description', 'Description', 'required')}
|
||||
${renderInput('date', 'startDate', 'Start date', 'required')}
|
||||
${renderInput('checkbox', 'hasEnd', 'Existing End Date', '', false, 'change:subscription-create#onCheck')}
|
||||
${renderInput(
|
||||
'date',
|
||||
'endDate',
|
||||
'End date',
|
||||
'required|is_after[field(startDate)]',
|
||||
!(this.hasEndCheck?.inp as HTMLInputElement)?.checked
|
||||
)}
|
||||
${renderDropdown(
|
||||
'subscription-create#getWallets',
|
||||
'wallet',
|
||||
@@ -193,7 +212,18 @@ class SubscriptionCreateElement extends BasePageElement {
|
||||
${renderDropdown('subscription-create#getTypes', 'transactionType', 'Transaction Type', 'required')}
|
||||
${renderInput('number', 'customRange', 'Every', 'required')}
|
||||
${renderDropdown('subscription-create#getSubs', 'subscriptionType', 'Subscription Type', 'required')}
|
||||
${this.errorMessage ? html`<div>${this.errorMessage}</div>` : html``}
|
||||
${this.errorMessage ? html`<div>${this.errorMessage}</div>` : html``}</template
|
||||
>`;
|
||||
};
|
||||
|
||||
render = (): TemplateResult => {
|
||||
return html`
|
||||
<app-form
|
||||
data-custom="subscription-create#onSubmit"
|
||||
data-has-cancel="true"
|
||||
data-target="subscription-create.appForm"
|
||||
data-render-input="subscription-create#renderForms"
|
||||
>
|
||||
</app-form>
|
||||
`;
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ import { AppFormElement, InputFieldElement } from 'components/';
|
||||
import { RouterService } from 'core/services';
|
||||
import { BasePageElement } from 'common/';
|
||||
import { AppDropdownElement } from 'components/app-dropdown/AppDropdownElement';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@controller
|
||||
class TransactionCreateElement extends BasePageElement {
|
||||
@@ -84,7 +85,15 @@ class TransactionCreateElement extends BasePageElement {
|
||||
return;
|
||||
}
|
||||
|
||||
const { description: description, wallet: walletId, amount, transactionType: transactionTypeId } = values;
|
||||
const {
|
||||
description: description,
|
||||
wallet: walletId,
|
||||
amount,
|
||||
transactionType: transactionTypeId,
|
||||
transactionDate,
|
||||
} = values;
|
||||
|
||||
const formattedDate = dayjs(transactionDate).format();
|
||||
|
||||
const walletData = this.walletData;
|
||||
|
||||
@@ -92,9 +101,11 @@ class TransactionCreateElement extends BasePageElement {
|
||||
description,
|
||||
amount,
|
||||
walletId: walletData && walletData.walletId ? walletData.walletId : walletId,
|
||||
transactionDate: formattedDate,
|
||||
transactionTypeId:
|
||||
walletData && walletData.transactionTypeId ? walletData.transactionTypeId : transactionTypeId,
|
||||
};
|
||||
|
||||
const response = await this.transactionService.post(formData);
|
||||
|
||||
if (response?.id) {
|
||||
@@ -125,7 +136,7 @@ class TransactionCreateElement extends BasePageElement {
|
||||
}
|
||||
|
||||
render = (): TemplateResult => {
|
||||
const renderInput = (type, name, label, rules, hide?) => {
|
||||
const renderInput = (type, name, label, rules, hide?, customAction?) => {
|
||||
if (hide) {
|
||||
return html``;
|
||||
}
|
||||
@@ -135,6 +146,7 @@ class TransactionCreateElement extends BasePageElement {
|
||||
data-label="${label}"
|
||||
data-targets="transaction-create.inputs"
|
||||
data-rules="${rules}"
|
||||
custom-action="${customAction}"
|
||||
></input-field>`;
|
||||
};
|
||||
|
||||
@@ -159,6 +171,7 @@ class TransactionCreateElement extends BasePageElement {
|
||||
>
|
||||
${renderInput('number', 'amount', 'Amount', 'required')}
|
||||
${renderInput('text', 'description', 'Description', 'required')}
|
||||
${renderInput('date', 'transactionDate', 'Transaction date', 'required')}
|
||||
${renderDropdown(
|
||||
'transaction-create#getWallets',
|
||||
'wallet',
|
||||
|
||||
@@ -16,6 +16,7 @@ app-modal {
|
||||
width: 960px;
|
||||
min-height: 160px;
|
||||
max-height: 560px;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 10px;
|
||||
margin: 0;
|
||||
top: 50%;
|
||||
@@ -41,7 +42,7 @@ app-modal {
|
||||
.button-content {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
bottom: 4px;
|
||||
margin-top: 20pxf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2179,6 +2179,11 @@ dashdash@^1.12.0:
|
||||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
dayjs@^1.10.5:
|
||||
version "1.10.5"
|
||||
resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.5.tgz#5600df4548fc2453b3f163ebb2abbe965ccfb986"
|
||||
integrity sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
|
||||
|
||||
Reference in New Issue
Block a user