diff --git a/app/components/add-expense-item/component.js b/app/components/add-expense-item/component.js new file mode 100644 index 0000000..6ac06d4 --- /dev/null +++ b/app/components/add-expense-item/component.js @@ -0,0 +1,59 @@ +import Component from '@glimmer/component'; +import { tracked } from '@glimmer/tracking'; +import { action } from '@ember/object'; +import moment from 'moment'; + +export default class AddExpenseItemComponent extends Component { + + // @tracked newExpense = Expense.create(); + @tracked amount = '0'; + @tracked currency = 'EUR'; + @tracked date = moment().startOf('hour').toDate(); + @tracked title = ''; + @tracked description = ''; + @tracked url = ''; + @tracked tags = ''; + + defaultDate = moment().startOf('hour').toDate(); + + // TODO fetch/apply exchange rate to (W)BTC + currencies = [ + { code: 'EUR' }, + { code: 'USD' }, + { code: 'GBP' } + ]; + + get submitButtonEnabled () { + return true; + } + + get submitButtonDisabled () { + return !this.submitButtonEnabled; + } + + setDefaultValues () { + } + + @action + submit (e) { + e.preventDefault(); + + let dateInput = (this.date instanceof Array) ? + this.date[0] : this.date; + const [ date ] = dateInput.toISOString().split('T'); + + // TODO validate form + const expense = { + amount: parseFloat(this.amount), + currency: this.currency, + date: date, + title: this.title, + description: this.description, + url: this.url, + tags: this.tags.split(',').map(t => t.trim()) + } + + this.args.addExpenseItem(expense); + this.resetProperties(); + } +} diff --git a/app/components/add-expense-item/template.hbs b/app/components/add-expense-item/template.hbs new file mode 100644 index 0000000..ddc176c --- /dev/null +++ b/app/components/add-expense-item/template.hbs @@ -0,0 +1,64 @@ +
+
+ + +
+ + + + + + +

+ {{input type="submit" value="Add" disabled=this.submitButtonDisabled + class="green" title="Add item to reimbursement"}} +

+
\ No newline at end of file diff --git a/app/components/add-reimbursement/component.js b/app/components/add-reimbursement/component.js index 17d9c38..8dc305d 100644 --- a/app/components/add-reimbursement/component.js +++ b/app/components/add-reimbursement/component.js @@ -5,40 +5,39 @@ import { inject as service } from '@ember/service'; import { action } from '@ember/object'; import { A } from '@ember/array'; import Reimbursement from 'kredits-web/models/reimbursement'; -import Expense from 'kredits-web/models/expense'; export default class AddReimbursementComponent extends Component { @service kredits; + @alias('kredits.contributorsSorted') contributors; + @tracked recipientId = null; @tracked title = ''; @tracked total = '0'; - @tracked expenses = A([]);; - @tracked newExpense = Expense.create(); + @tracked expenses = A([]); + @tracked expenseFormVisible = true; - // TODO fetch/apply exchange rate to (W)BTC - currencies = [ - { code: 'EUR' }, - { code: 'USD' }, - { code: 'GBP' } - ]; - - get typeofTotal() { - return typeof this.total; - } - - get submitButtonEnabled() { + get submitButtonEnabled () { return this.expenses.length > 0; } - get submitButtonDisabled() { + get submitButtonDisabled () { return !this.submitButtonEnabled; } - @alias('kredits.contributorsSorted') contributors; + @action + showExpenseForm () { + this.expenseFormVisible = true; + } @action - submit(e) { + addExpenseItem (expenseItem) { + this.expenses.pushObject(expenseItem); + this.expenseFormVisible = false; + } + + @action + submit (e) { e.preventDefault(); console.log('submit', e); // TODO diff --git a/app/components/add-reimbursement/template.hbs b/app/components/add-reimbursement/template.hbs index 3dbb710..e42b008 100644 --- a/app/components/add-reimbursement/template.hbs +++ b/app/components/add-reimbursement/template.hbs @@ -17,82 +17,41 @@

-

- Expense items -

- {{#each this.expenses as |expense|}} - - - - - -
{{expense.title}} – {{expense.description}}{{fmt-fiat-currency expense.amount expense.currency}}
-

TODO: date, url, tags

+

Expense items

+ {{#if this.expenses}} + +

+ +

{{else}}

No line items yet.

- {{/each}} + {{/if}}

{{input type="submit" value="Submit" disabled=this.submitButtonDisabled title="Submit/propose this reimbursement"}}

-

- New expense item -

-
-
- - -
- - - - - -

- {{input type="submit" value="Add" disabled=this.addButtonDisabled - class="green" title="Add item to reimbursement"}} -

-
+ {{#if this.expenseFormVisible}} +

New expense item

+ + {{/if}} diff --git a/app/components/reimbursement-list/template.hbs b/app/components/reimbursement-list/template.hbs index 0bdd008..82d3404 100644 --- a/app/components/reimbursement-list/template.hbs +++ b/app/components/reimbursement-list/template.hbs @@ -11,14 +11,22 @@ {{sats-to-btc reimbursement.amount}} WBTC

- + - - - +
  • +
    +

    + {{expense.date}}: + {{expense.title}} +

    +

    {{expense.description}}

    +
    +
    + {{fmt-fiat-currency expense.amount expense.currency}} +
    +
  • {{/each}} -
    {{expense.title}} – {{expense.description}}{{fmt-fiat-currency expense.amount expense.currency}}
    + {{/each}} \ No newline at end of file diff --git a/app/models/expense.js b/app/models/expense.js deleted file mode 100644 index cd050af..0000000 --- a/app/models/expense.js +++ /dev/null @@ -1,43 +0,0 @@ -import EmberObject, { computed } from '@ember/object'; -import moment from 'moment'; -import { A } from '@ember/array'; - -export default EmberObject.extend({ - title: null, - description: null, - currency: null, - amount: null, - date: null, - url: null, - tags: null, - - init () { - this._super(...arguments); - this.setDefaultValues(); - }, - - iso8601Date: computed('date', 'time', function() { - return this.time ? `${this.date}T${this.time}` : this.date; - }), - - jsDate: computed('iso8601Date', function() { - return moment(this.iso8601Date).toDate(); - }), - - setDefaultValues () { - this.set('defaultDate', moment().startOf('hour').toDate()); - this.setProperties({ - title: '', - description: '', - currency: 'EUR', - amount: 0, - date: this.defaultDate, - url: null, - tags: A([]) - }); - }, - - serialize () { - return JSON.stringify(this); - } -}); diff --git a/app/styles/_forms.scss b/app/styles/_forms.scss index 443ab72..58e9ec0 100644 --- a/app/styles/_forms.scss +++ b/app/styles/_forms.scss @@ -13,18 +13,19 @@ section#signup { p { font-size: 1.2rem; - margin-bottom: 1.5rem; &.mg-bottom-md { margin-bottom: 2rem; } &.label { + margin-bottom: 1.5rem; font-size: 1rem; margin-bottom: .5rem; } &.actions { + margin-bottom: 1.5rem; padding-top: 1.5rem; text-align: center; a { @@ -38,6 +39,10 @@ section#signup { display: block; margin-bottom: 0.5rem; opacity: 0.7; + + > p { + margin-bottom: 1.5rem; + } } fieldset { diff --git a/app/styles/_item-list.scss b/app/styles/_item-list.scss index bdef14c..548bf3c 100644 --- a/app/styles/_item-list.scss +++ b/app/styles/_item-list.scss @@ -1,7 +1,7 @@ ul.item-list { list-style: none; - li { + > li { padding: 0.8rem 1.2rem; font-size: 1.2rem; background-color: $item-background-color; @@ -19,7 +19,7 @@ ul.item-list { &.loading { @include loading-border-top; - li { + > li { &:first-of-type { border-top: none; } @@ -27,7 +27,7 @@ ul.item-list { } &.spaced { - li { + > li { border-top: 1px solid $item-border-color; margin-bottom: 2rem; } diff --git a/app/styles/app.scss b/app/styles/app.scss index 14dba8f..ba4617f 100644 --- a/app/styles/app.scss +++ b/app/styles/app.scss @@ -96,6 +96,7 @@ section { @import "components/contribution-list"; @import "components/contributor-list"; @import "components/contributor-profile"; +@import "components/expense-list"; @import "components/external-account-link"; @import "components/loading-spinner"; @import "components/reimbursement-list"; diff --git a/app/styles/components/_budget-balances.scss b/app/styles/components/_budget-balances.scss index 05226bd..83d2d91 100644 --- a/app/styles/components/_budget-balances.scss +++ b/app/styles/components/_budget-balances.scss @@ -25,7 +25,7 @@ section#funds { text-align: right; &.amount { - font-size: 1.6rem; + font-size: 1.5rem; padding-right: 1.2rem; } diff --git a/app/styles/components/_expense-list.scss b/app/styles/components/_expense-list.scss new file mode 100644 index 0000000..b369f5f --- /dev/null +++ b/app/styles/components/_expense-list.scss @@ -0,0 +1,48 @@ +ul.expense-list { + grid-column-start: span 2; + width: 100%; + margin-top: 0.8rem; + border-collapse: collapse; + + li { + display: grid; + grid-template-columns: auto 10rem; + grid-row-gap: 0.5rem; + padding-top: 1.2rem; + border-top: 1px solid $item-border-color; + font-size: 1.2rem; + + &:not(:last-child) { + padding-bottom: 1.2rem; + } + } + + .description { + grid-row-start: 1; + grid-row-end: 3; + } + + .amount { + justify-self: end; + // font-weight: normal; + } + + .actions { + justify-self: end; + } + + h4 { + font-size: 1.2rem; + font-weight: normal; + line-height: 2rem; + } + + p { + line-height: 2rem; + + &.description { + font-size: 1rem; + opacity: 0.7; + } + } +} diff --git a/app/styles/components/_reimbursement-list.scss b/app/styles/components/_reimbursement-list.scss index c5f6458..2423ffd 100644 --- a/app/styles/components/_reimbursement-list.scss +++ b/app/styles/components/_reimbursement-list.scss @@ -1,7 +1,7 @@ ul.reimbursement-list { width: 100%; - li { + > li { display: grid; grid-template-columns: auto 10rem; grid-row-gap: 0.5rem; @@ -17,36 +17,13 @@ ul.reimbursement-list { } .amount { - font-weight: 500; + font-size: 1.5rem; } .symbol { - font-size: 0.8rem; + font-size: 1rem; padding-left: 0.2rem; } } - - table { - grid-column-start: span 2; - width: 100%; - margin-top: 0.8rem; - border-collapse: collapse; - - tr { - border-top: 1px solid $item-border-color; - } - - td { - padding: 0.8rem 0; - - &.amount { - text-align: right; - } - } - - @include media-max(small) { - td.date { display: none; } - } - } } } diff --git a/tests/integration/components/add-expense-item/component-test.js b/tests/integration/components/add-expense-item/component-test.js new file mode 100644 index 0000000..5508b95 --- /dev/null +++ b/tests/integration/components/add-expense-item/component-test.js @@ -0,0 +1,26 @@ +import { module, test } from 'qunit'; +import { setupRenderingTest } from 'ember-qunit'; +import { render } from '@ember/test-helpers'; +import { hbs } from 'ember-cli-htmlbars'; + +module('Integration | Component | add-expense-item', function(hooks) { + setupRenderingTest(hooks); + + test('it renders', async function(assert) { + // Set any properties with this.set('myProperty', 'value'); + // Handle any actions with this.set('myAction', function(val) { ... }); + + await render(hbs``); + + assert.equal(this.element.textContent.trim(), ''); + + // Template block usage: + await render(hbs` + + template block text + + `); + + assert.equal(this.element.textContent.trim(), 'template block text'); + }); +});