Skip to content

Commit

Permalink
feat: Allow to create accounts with specific category
Browse files Browse the repository at this point in the history
  • Loading branch information
letehaha committed Sep 25, 2024
1 parent 765db85 commit 92cb165
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 62 deletions.
10 changes: 3 additions & 7 deletions src/api/accounts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ACCOUNT_CATEGORIES, AccountModel, endpointsTypes } from "shared-types";
import { AccountModel, endpointsTypes } from "shared-types";
import { api } from "@/api/_api";
import { fromSystemAmount, toSystemAmount } from "@/api/helpers";

Expand All @@ -19,18 +19,14 @@ export const loadAccounts = async (): Promise<AccountModel[]> => {
};

export const createAccount = async (
payload: Omit<endpointsTypes.CreateAccountBody, "accountCategory">,
payload: endpointsTypes.CreateAccountBody,
): Promise<AccountModel> => {
const params = payload;

if (params.creditLimit) params.creditLimit = toSystemAmount(Number(params.creditLimit));
if (params.initialBalance) params.initialBalance = toSystemAmount(Number(params.initialBalance));

const result = await api.post("/accounts", {
...params,
// For now we just doesn't allow users to select account category on UI
accountCategory: ACCOUNT_CATEGORIES.general,
});
const result = await api.post("/accounts", params);

return result;
};
Expand Down
2 changes: 1 addition & 1 deletion src/common/const/account-categories-verbose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ export const ACCOUNT_CATEGORIES_VERBOSE = Object.freeze({
[ACCOUNT_CATEGORIES.mortgage]: "Mortgage",
[ACCOUNT_CATEGORIES.overdraft]: "Overdraft",
[ACCOUNT_CATEGORIES.crypto]: "Crypto",
});
}) as Record<ACCOUNT_CATEGORIES, string>;
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,12 @@
</template>
<template v-else>
<form-row>
<input-field model-value="No account exists" label="Account" readonly :disabled="disabled">
<input-field
model-value="No account exists"
label="Account"
readonly
:disabled="disabled"
>
<template #label-right>
<div
class="text-primary cursor-pointer hover:underline"
Expand Down Expand Up @@ -102,7 +107,11 @@ withDefaults(
},
);
const emit = defineEmits(["close-modal", "update:account", "update:to-account"]);
const emit = defineEmits([
"close-modal",
"update:account",
"update:to-account",
]);
const router = useRouter();
Expand Down
39 changes: 9 additions & 30 deletions src/components/fields/components/field-label.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<template>
<component :is="onlyTemplate ? 'div' : 'label'" class="field-label">
<template v-if="label">
<div class="field-label__label">
<div
class="text-base font-normal tracking-wide text-[var(--app-on-surface-color)] mb-1 flex items-center justify-between"
>
<span>{{ label }}</span>

<template v-if="$slots['label-right']">
Expand All @@ -12,38 +14,15 @@
<template v-else-if="$slots.label">
<slot name="label" />
</template>
<div class="field-label__field-wrapper">
<div class="relative">
<slot />
</div>
</component>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
props: {
label: { type: String, default: undefined },
// Used in case you want omit using `label` but still need to use styles and
// template. For example when `label` triggers unnecessary cliks of buttons inside
onlyTemplate: { type: Boolean, default: false },
},
});
<script lang="ts" setup>
defineProps<{
label?: string;
onlyTemplate?: boolean;
}>();
</script>

<style lang="scss">
.field-label__label {
font-size: 16px;
font-weight: 400;
letter-spacing: 0.5px;
line-height: 1;
color: var(--app-on-surface-color);
margin-bottom: 5px;
display: flex;
align-items: center;
justify-content: space-between;
}
.field-label__field-wrapper {
position: relative;
}
</style>
29 changes: 27 additions & 2 deletions src/components/forms/create-account-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { storeToRefs } from "pinia";
import { useQueryClient } from "@tanstack/vue-query";
import { useAccountsStore, useCurrenciesStore } from "@/stores";
import { VUE_QUERY_CACHE_KEYS } from "@/common/const";
import { ACCOUNT_CATEGORIES_VERBOSE, VUE_QUERY_CACHE_KEYS } from "@/common/const";
import * as Select from "@/components/lib/ui/select";
import { useNotificationCenter, NotificationType } from "@/components/notification-center";
Expand All @@ -13,6 +13,7 @@ import UiButton from "@/components/lib/ui/button/Button.vue";
import FieldLabel from "@/components/fields/components/field-label.vue";
import AddCurrencyDialog from "@/components/dialogs/add-currency-dialog.vue";
import { ACCOUNT_CATEGORIES } from "shared-types";
const emit = defineEmits(["created"]);
Expand All @@ -28,16 +29,24 @@ const defaultCurrency = computed(
systemCurrenciesVerbose.value.linked.find((i) => i.id === baseCurrency.value.currencyId).id ||
0,
);
const accountCategories = Object.entries(ACCOUNT_CATEGORIES_VERBOSE).map(
(entry: [keyof typeof ACCOUNT_CATEGORIES_VERBOSE, string]) => ({
value: entry[0],
label: entry[1],
}),
);
const form = reactive<{
name: string;
currencyId: string;
initialBalance: number;
creditLimit: number;
accountCategory: ACCOUNT_CATEGORIES;
}>({
name: "",
currencyId: String(defaultCurrency.value),
initialBalance: 0,
creditLimit: 0,
accountCategory: ACCOUNT_CATEGORIES.creditCard,
});
const isLoading = ref(false);
Expand All @@ -47,10 +56,11 @@ const submit = async () => {
isLoading.value = true;
await accountsStore.createAccount({
currencyId: form.currencyId,
currencyId: Number(form.currencyId),
name: form.name,
creditLimit: form.creditLimit,
initialBalance: form.initialBalance,
accountCategory: form.accountCategory,
});
addNotification({
Expand Down Expand Up @@ -109,6 +119,21 @@ const submit = async () => {

<input-field v-model="form.creditLimit" label="Credit limit" placeholder="Credit limit" />

<FieldLabel label="Account type">
<Select.Select v-model="form.accountCategory">
<Select.SelectTrigger>
<Select.SelectValue placeholder="Select account type" />
</Select.SelectTrigger>
<Select.SelectContent>
<template v-for="item of accountCategories" :key="item.id">
<Select.SelectItem :value="item.value">
{{ item.label }}
</Select.SelectItem>
</template>
</Select.SelectContent>
</Select.Select>
</FieldLabel>

<div class="flex">
<ui-button type="submit" class="ml-auto min-w-[120px]" :disabled="isLoading">
{{ isLoading ? "Creating..." : "Create" }}
Expand Down
10 changes: 8 additions & 2 deletions src/pages/account/components/account-details-tab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ const isOpen = ref(false);
<div class="flex gap-2">
{{ currenciesMap[account.currencyId].currency.code }}

<span v-if="currenciesMap[account.currencyId].isDefaultCurrency"> (main) </span>
<span v-if="currenciesMap[account.currencyId].isDefaultCurrency">
(main)
</span>

<template v-if="isOpen">
<ChevronUpIcon />
Expand All @@ -88,7 +90,11 @@ const isOpen = ref(false);
<div class="flex items-center justify-between gap-2">
<span> Exchange Rate Live Update: </span>

{{ currenciesMap[account.currencyId].liveRateUpdate ? "Enabled" : "Disabled" }}
{{
currenciesMap[account.currencyId].liveRateUpdate
? "Enabled"
: "Disabled"
}}
</div>
</div>
</Collapsible.CollapsibleContent>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/investment-account/investment-account.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<Card.CardContent class="grid gap-1">
<template v-if="holdings.length">
<div
class="grid grid-cols-5 gap-1 px-4 py-2 mb-1 text-left border-b border-white/20"
class="grid grid-cols-[2fr,1fr,0.7fr,1fr,1fr] gap-1 px-4 py-2 mb-1 text-left border-b border-white/20"
>
<span>Name</span>
<span>Symbol</span>
Expand All @@ -29,7 +29,7 @@
<template v-if="securitiesRecord[holding.securityId]">
<Button
variant="ghost"
class="grid grid-cols-5 gap-1 text-left"
class="grid grid-cols-[2fr,1fr,0.7fr,1fr,1fr] gap-1 text-left"
@click="() => (activeHolding = holding)"
>
<span>
Expand Down
23 changes: 7 additions & 16 deletions src/stores/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ export const useAccountsStore = defineStore("accounts", () => {
}
});

const getAccountById: WritableComputedRef<
(id: number) => AccountModel | undefined
> = computed(() => (id: number) => accounts.value.find((i) => i.id === id));
const getAccountById: WritableComputedRef<(id: number) => AccountModel | undefined> = computed(
() => (id: number) => accounts.value.find((i) => i.id === id),
);

const accountsCurrencyIds = computed(() => [
...new Set(accounts.value.map((item) => item.currencyId)),
Expand All @@ -42,18 +42,12 @@ export const useAccountsStore = defineStore("accounts", () => {
const systemAccounts = computed(() =>
accounts.value.filter((item) => item.type === ACCOUNT_TYPES.system),
);
const enabledAccounts = computed(() =>
accounts.value.filter((item) => item.isEnabled),
);
const enabledAccounts = computed(() => accounts.value.filter((item) => item.isEnabled));
const investmentAccounts = computed(() =>
accounts.value.filter(
(item) => item.accountCategory === ACCOUNT_CATEGORIES.investment,
),
accounts.value.filter((item) => item.accountCategory === ACCOUNT_CATEGORIES.investment),
);

const createAccount = async (
payload: Parameters<typeof apiCreateAccount>[0],
) => {
const createAccount = async (payload: Parameters<typeof apiCreateAccount>[0]) => {
try {
await apiCreateAccount(payload);
await refetchAccounts();
Expand All @@ -63,10 +57,7 @@ export const useAccountsStore = defineStore("accounts", () => {
}
};

const editAccount = async ({
id,
...data
}: Parameters<typeof apiEditAccount>[0]) => {
const editAccount = async ({ id, ...data }: Parameters<typeof apiEditAccount>[0]) => {
try {
await apiEditAccount({ id, ...data });
await refetchAccounts();
Expand Down

0 comments on commit 92cb165

Please sign in to comment.