Skip to content

Commit

Permalink
Fix some bugs and styles
Browse files Browse the repository at this point in the history
  • Loading branch information
ya-erm committed Mar 12, 2023
1 parent 629a932 commit 8cf758f
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 33 deletions.
11 changes: 11 additions & 0 deletions src/lib/ui/GridCircleItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
export let onClick: () => void;
export let selected: boolean = false;
export let testId: string | undefined = undefined;
export let dashed: boolean = false;
</script>

<button
on:click={onClick}
class:selected
class:dashed
data-testId={testId}
class="grid-item flex-col flex-center gap-0.5 cursor-pointer"
type="button"
Expand Down Expand Up @@ -48,6 +50,9 @@
white-space: nowrap;
overflow: hidden;
}
.grid-item.dashed .text {
color: var(--active-color);
}
.grid-item .circle {
display: flex;
flex-direction: column;
Expand All @@ -60,6 +65,12 @@
height: 4rem;
background: var(--header-background-color);
}
.grid-item.dashed .circle {
border-style: dashed;
background-color: transparent;
border-color: var(--active-color);
color: var(--active-color);
}
.grid-item:focus .circle,
.grid-item.selected .circle {
border: 2px solid var(--active-color);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/ui/InputLabel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
.label-text {
font-size: 0.9rem;
}
.label-text.error {
.error {
color: var(--red-color);
}
.optional {
Expand Down
38 changes: 29 additions & 9 deletions src/lib/utils/formatMoney.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,39 @@
import { join } from './join';

export type FormatMoneyOptions = {
currency?: string;
/** true, if need add sign '+' before positive value */
withSign?: boolean;
/** minimal number of digits in fractional part */
minPrecision?: number;
/** maximal number of digits in fractional part */
maxPrecision?: number;
};

/**
* Display money value (with thousand separator)
* @param value money value
* @param currency currency
* @param withSign true, if need add sign '-' before negative value
* @param precision number of digits in fractional part
* @param options format options
*/
export function formatMoney(value: number, currency: string | undefined = undefined, withSign = false, precision = 2) {
export function formatMoney(value: number, options?: FormatMoneyOptions) {
if (value == null || value == undefined || isNaN(value)) {
return '';
}

const currency = options?.currency;
const withSign = options?.withSign ?? false;
const minPrecision = options?.minPrecision ?? 0;
const maxPrecision = options?.maxPrecision ?? 2;

const sign = withSign && value > 0 ? '+' : '';
const parts = value.toFixed(precision).split('.');
const fractionalPart = parts.length > 1 ? '.' + parts[1] : '';

return [`${sign}${parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ' ')}${fractionalPart}`, currency]
.filter((x) => x !== undefined)
.join(' ');
const parts = value.toFixed(maxPrecision).split('.');
let fractionalPart = parts.length > 1 ? parts[1] : undefined;
if (fractionalPart?.match(`0{${maxPrecision}}`)) {
fractionalPart = new Array(minPrecision).fill('0').join();
}

const numValue = join([`${sign}${parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, '\u00A0')}`, fractionalPart], '.');

return join([numValue, currency], '\u00A0');
}
30 changes: 22 additions & 8 deletions src/routes/accounts/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { useRightButton } from '$lib/ui/header/header';
import Input from '$lib/ui/Input.svelte';
import { getSearchParam } from '$lib/utils';
import Icon from '$lib/ui/Icon.svelte';
import TransactionListItem from '../transactions/TransactionListItem.svelte';
Expand Down Expand Up @@ -73,14 +74,14 @@
return res;
}, {} as { [key: string]: TransactionFullDto[] });
const findCurrencyRate = (currency: string) =>
settings?.currency !== currency
const findCurrencyRate = (mainCurrency?: string | null, currency?: string | null) =>
mainCurrency && currency && mainCurrency !== currency
? currencyRates.find(
({ cur1, cur2 }) => [cur1, cur2].includes(settings?.currency) && [cur1, cur2].includes(currency),
({ cur1, cur2 }) => [cur1, cur2].includes(mainCurrency) && [cur1, cur2].includes(currency),
) ?? null
: null;
$: currencyRate = findCurrencyRate(account?.currency ?? '');
$: currencyRate = findCurrencyRate(settings?.currency, account?.currency ?? '');
onMount(() => {
if (cardId) {
Expand Down Expand Up @@ -127,12 +128,15 @@
<div class="accounts-list" bind:this={accountListElement} on:scroll={handleScroll}>
{#each accounts as account}
<div class="account-card" on:click={() => scrollToCard(account.id)} aria-hidden>
<AccountCard {account} currencyRate={findCurrencyRate(account.currency)} />
<AccountCard {account} currencyRate={findCurrencyRate(settings?.currency, account.currency)} />
<div id={`account-card-${account.id}`} class="account-card-anchor" />
</div>
{/each}
<a id="create-account" class="account-card" href={routes['accounts.create'].path}>
{$translate('accounts.create_account')}
<a id="create-account" class="account-card dashed text-decoration-none" href={routes['accounts.create'].path}>
<span class="flex items-center gap-0.25">
<Icon name="mdi:plus" />
{$translate('accounts.create_account')}
</span>
</a>
</div>
</div>
Expand All @@ -154,7 +158,11 @@
{#each Object.entries(groups) as [date, transactions] (date)}
<div>{date}</div>
{#each transactions as transaction (transaction.id)}
<TransactionListItem hideAccount={!!account} {transaction} {currencyRate} />
<TransactionListItem
hideAccount={!!account}
currencyRate={currencyRate ?? findCurrencyRate(settings?.currency, transaction.account.currency)}
{transaction}
/>
{/each}
{/each}
</div>
Expand Down Expand Up @@ -201,6 +209,12 @@
transition: box-shadow 0.2s;
box-shadow: 4px 4px 8px 0px rgba(127, 127, 127, 0.1);
}
.account-card.dashed {
border-style: dashed;
background-color: transparent;
border-color: var(--active-color);
color: var(--active-color);
}
@media (hover: hover) {
.account-card:hover {
box-shadow: 4px 4px 8px 0px rgba(127, 127, 127, 0.2);
Expand Down
4 changes: 2 additions & 2 deletions src/routes/accounts/AccountCard.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@
</div>
<div class="flex-col items-center gap-0.25">
<div class="money-value">
{formatMoney(account.sum, account.currency)}
{formatMoney(account.sum, { currency: account.currency })}
</div>
{#if currencyRate}
<div class="other-money-value">
{formatMoney(account.sum * rate, otherCurrency)}
{formatMoney(account.sum * rate, { currency: otherCurrency })}
</div>
{/if}
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/routes/categories/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
onClick={() => goto(`${routes['categories.create'].path}?type=IN`)}
text={$translate('common.add')}
icon="mdi:plus"
dashed
/>
</div>

Expand All @@ -40,6 +41,7 @@
onClick={() => goto(`${routes['categories.create'].path}?type=OUT`)}
text={$translate('common.add')}
icon="mdi:plus"
dashed
/>
</div>

Expand Down
1 change: 1 addition & 0 deletions src/routes/transactions/CategorySelect.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
onClick={() => (createCategoryModalOpened = true)}
text={$translate('common.add')}
icon="mdi:plus"
dashed
/>
{/if}
</div>
Expand Down
56 changes: 46 additions & 10 deletions src/routes/transactions/TransactionForm.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,18 @@
import { isApiErrorData } from '$lib/api';
import { deps } from '$lib/deps';
import type { TransactionFullDto } from '$lib/interfaces';
import { translate } from '$lib/translate';
import Input from '$lib/ui/Input.svelte';
import InputLabel from '$lib/ui/InputLabel.svelte';
import { showErrorToast } from '$lib/ui/toasts';
import { formatMoney } from '$lib/utils/formatMoney';
import { getNumberSearchParam, getSearchParam } from '$lib/utils/getSearchParam';
import type { TransactionFullDto } from '$lib/interfaces';
import AccountSelect from './AccountSelect.svelte';
import CategorySelect from './CategorySelect.svelte';
import TypeSwitch from './TypeSwitch.svelte';
import TagsList from './TagsList.svelte';
import TypeSwitch from './TypeSwitch.svelte';
export let accounts: Account[];
export let categories: Category[];
Expand All @@ -40,16 +41,25 @@
let categoryId = transaction?.categoryId ?? getNumberSearchParam($page, 'categoryId');
let date = dayjs(transaction?.date).format('YYYY-MM-DD');
let time = dayjs(transaction?.date).format('HH:mm');
$: datetime = new Date([date, time].join('T')).toISOString();
let inputRef: HTMLInputElement | null = null;
let accountId = isTransfer
? sourceTransaction?.accountId
: transaction?.accountId ?? getNumberSearchParam($page, 'accountId');
let destinationAccountId = isTransfer
? destinationTransaction?.accountId
: getNumberSearchParam($page, 'destinationAccountId');
let date = dayjs(transaction?.date).format('YYYY-MM-DD');
let time = dayjs(transaction?.date).format('HH:mm');
$: datetime = new Date([date, time].join('T')).toISOString();
$: accountCurrency = accounts.find(({ id }) => id === accountId)?.currency;
$: destinationAccountCurrency = accounts.find(({ id }) => id === destinationAccountId)?.currency;
let _value1 = (isTransfer ? sourceTransaction?.amount : transaction?.amount)?.toString() ?? '';
let _value2 = destinationTransaction?.amount?.toString() ?? '';
$: _rate = Number(_value1) / Number(_value2);
let selectedTags = transaction?.tags.map((t) => `${t.id}`) ?? [];
Expand Down Expand Up @@ -111,7 +121,15 @@
/>
{/if}
{#if type === 'IN' || type === 'OUT'}
<CategorySelect {type} bind:categoryId categories={categories.filter((c) => c.type === type)} />
<CategorySelect
{type}
bind:categoryId
categories={categories.filter((c) => c.type === type)}
onChange={() => {
inputRef?.focus({ preventScroll: true });
inputRef?.scrollIntoView({ behavior: 'smooth' });
}}
/>
{/if}
{#if type === 'IN'}
<AccountSelect {accounts} bind:accountId testId="DestinationAccountSelect" />
Expand All @@ -130,20 +148,30 @@
<Input
type="number"
name="amount"
value={(isTransfer ? sourceTransaction?.amount : transaction?.amount)?.toString()}
endText={accounts.find(({ id }) => id === accountId)?.currency}
bind:ref={inputRef}
bind:value={_value1}
endText={accountCurrency}
required
/>
{#if type === 'TRANSFER'}
<Input
type="number"
name="destinationAmount"
value={destinationTransaction?.amount.toString()}
endText={accounts.find(({ id }) => id === destinationAccountId)?.currency}
bind:value={_value2}
endText={destinationAccountCurrency}
required
/>
{/if}
</div>
{#if type === 'TRANSFER' && Number(_value1) && Number(_value2)}
<div class="currency-rate-info">
{`1 ${accountCurrency} = ${formatMoney(1 / _rate, {
maxPrecision: 4,
currency: destinationAccountCurrency,
})}`}
{`(1 ${destinationAccountCurrency} = ${formatMoney(_rate, { maxPrecision: 4, currency: accountCurrency })})`}
</div>
{/if}
</div>
<Input label={$translate('transactions.comment')} name="comment" value={transaction?.comment} optional />
<div class="flex-col gap-0.5">
Expand All @@ -155,3 +183,11 @@
<slot name="footer" />
</div>
</form>

<style>
.currency-rate-info {
font-size: 0.9rem;
text-align: right;
color: var(--secondary-text-color);
}
</style>
6 changes: 3 additions & 3 deletions src/routes/transactions/TransactionListItem.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
}
};
const rate = currencyRate?.cur1 === transaction.account.currency ? currencyRate.rate : 1 / (currencyRate?.rate ?? 1);
const otherCurrency = currencyRate?.cur1 === transaction.account.currency ? currencyRate.cur2 : currencyRate?.cur1;
$: rate = currencyRate?.cur1 === transaction.account.currency ? currencyRate.rate : 1 / (currencyRate?.rate ?? 1);
$: otherCurrency = currencyRate?.cur1 === transaction.account.currency ? currencyRate.cur2 : currencyRate?.cur1;
</script>

<a
Expand Down Expand Up @@ -82,7 +82,7 @@
</span>
{#if currencyRate}
<span class="other-money-value">
{formatMoney(transaction.amount * rate, otherCurrency)}
{formatMoney(transaction.amount * rate, { currency: otherCurrency })}
</span>
{/if}
</div>
Expand Down

1 comment on commit 8cf758f

@vercel
Copy link

@vercel vercel bot commented on 8cf758f Mar 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.