Skip to content

Commit

Permalink
layout improvements and per page selection, ordering bug fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
samluiz committed May 27, 2024
1 parent c58c33f commit efc202e
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 63 deletions.
12 changes: 10 additions & 2 deletions backend/expense/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ func (r *repository) FindAllByProfileID(profileID int, pagination t.Pagination)
return t.PaginatedResult{}, fmt.Errorf("invalid sort by value: %s", dbPagination.SortBy)
}

var orderBy string

if dbPagination.OrderBy == "category" {
orderBy = "c.description"
} else {
orderBy = "e." + dbPagination.OrderBy
}

query := fmt.Sprintf(`
SELECT
e.id,
Expand All @@ -87,8 +95,8 @@ func (r *repository) FindAllByProfileID(profileID int, pagination t.Pagination)
categories AS c ON ec.category_id = c.id
WHERE
e.profile_id = ?
ORDER BY e.%s %s
LIMIT ? OFFSET ?`, dbPagination.OrderBy, dbPagination.SortBy)
ORDER BY %s %s
LIMIT ? OFFSET ?`, orderBy, dbPagination.SortBy)

err = r.db.Select(&expenses, query, profileID, dbPagination.Limit, dbPagination.Offset)

Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d3c13abbbfc455c08f8ff442ce98c26c
306073f1282c8f1f8789b7900fe179de
75 changes: 75 additions & 0 deletions frontend/src/components/BalanceTab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script setup lang="ts">
import { computed, ref, toRefs } from "vue";
import { maskCurrency } from "@/shared/utils";
const props = defineProps<{
earnings_subtotal: number;
expenses_subtotal: number;
}>();
const { earnings_subtotal, expenses_subtotal } = toRefs(props);
const isDropdownOpen = ref(false);
const balance = computed(() => {
return earnings_subtotal.value - expenses_subtotal.value;
});
const openDropdown = () => {
isDropdownOpen.value = true;
};
const closeDropdown = () => {
setTimeout(() => (isDropdownOpen.value = false), 1000);
};
</script>

<template>
<div
class="flex flex-col justify-self-end gap-2 text-sm min-w-44"
@mouseover="openDropdown"
@mouseleave="closeDropdown"
>
<div
class="p-2 rounded-md"
:class="{
'bg-red-600': balance < 0,
'bg-green-600': balance > 0,
'bg-gray-600': balance == 0,
}"
>
<span>Balance: {{ maskCurrency(balance) }}</span>
<span
class="ml-2 opacity-50 duration-200"
:class="{
'opacity-100': isDropdownOpen,
}"
>&#128712;</span
>
</div>
<transition name="fade">
<div class="grid grid-flow-row gap-2 min-w-44" v-if="isDropdownOpen">
<span
class="p-2 rounded-md bg-green-600 bg-opacity-50 hover:bg-opacity-100 duration-200"
>Total Earnings: {{ maskCurrency(earnings_subtotal) }}</span
>

<span
class="p-2 rounded-md bg-red-600 bg-opacity-50 hover:bg-opacity-100 duration-200"
>Total Expenses: {{ maskCurrency(expenses_subtotal) }}</span
>
</div>
</transition>
</div>
</template>

<style scoped>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
122 changes: 67 additions & 55 deletions frontend/src/components/Table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import EditItemModal from "./EditItemModal.vue";
import AddItemModal from "./AddItemModal.vue";
import TableHeader from "./ui/TableHeader.vue";
import TableData from "./ui/TableData.vue";
import BalanceTab from "./BalanceTab.vue";
import {
Create as createEarning,
Update as updateEarning,
Expand Down Expand Up @@ -61,6 +62,8 @@ const getSelectedTabFromLocalStorage = () => {
const tab = localStorage.getItem("selectedTab");
if (tab) {
selectedTab.value = tab as Tab;
} else {
selectedTab.value = Tab.EARNING;
}
};
Expand Down Expand Up @@ -282,40 +285,19 @@ const sortTableData = (orderBy: string) => {
fetchData();
};
const totalEarnings = computed(() => {
return earnings.value && earnings.value.length > 0
? earnings.value[0].sub_total
: 0;
});
const totalExpenses = computed(() => {
return expenses.value && expenses.value.length > 0
? expenses.value[0].sub_total
: 0;
});
const balance = computed(() => {
return totalEarnings.value - totalExpenses.value;
});
const handleSizeChange = (n: number) => {
if (selectedTab.value === Tab.EARNING) {
earningsPagination.value.size = n;
} else {
expensesPagination.value.size = n;
}
fetchData();
};
</script>

<template>
<div class="flex justify-center items-center mb-4 gap-2">
<button
v-for="tab in tabs"
:key="tab"
@click="handleChangeTab(tab)"
class="py-1.5 px-2 duration-200 text-black dark:text-white rounded-sm"
:class="{
'bg-primary dark:bg-secondary text-black dark:text-black':
selectedTab === tab,
'hover:bg-dark dark:hover:bg-light hover:bg-opacity-30':
selectedTab !== tab,
}"
>
{{ tab }}
</button>
<div class="grid place-items-center grid-flow-col absolute right-10">
<div class="flex justify-between w-full items-center my-6 gap-2">
<div class="w-full flex justify-start">
<ProfileSelector
:profile="profile!"
@on-profile-create="fetchData()"
Expand All @@ -328,7 +310,40 @@ const balance = computed(() => {
Edit profile
</button>
</div>
<div class="w-full flex justify-center gap-2">
<button
v-for="tab in tabs"
:key="tab"
@click="handleChangeTab(tab)"
class="py-1.5 px-2 duration-200 text-black dark:text-white rounded-sm"
:class="{
'bg-primary dark:bg-secondary bg-opacity-100 text-black dark:text-black':
selectedTab && selectedTab === tab,
'hover:bg-dark dark:hover:bg-light hover:bg-opacity-30 dark:hover:bg-opacity-30':
selectedTab && selectedTab !== tab,
}"
>
{{ tab }}
</button>
</div>
<div class="w-full flex justify-end gap-2 text-sm">
<span>Items per page:</span>
<div v-for="n in [5, 10]">
<span
@click="handleSizeChange(n)"
class="cursor-pointer text-center w-fit p-0.5 duration-200"
:class="{
'opacity-30 pointer-events-none':
(n === earningsPagination.size && selectedTab === Tab.EARNING) ||
(n === expensesPagination.size && selectedTab === Tab.EXPENSE),
}"
>
{{ n }}
</span>
</div>
</div>
</div>

<div v-if="tableData && tableData.length > 0">
<table class="min-w-full rounded-lg leading-normal">
<thead>
Expand Down Expand Up @@ -430,39 +445,36 @@ const balance = computed(() => {
No data available yet
</div>

<div class="w-full mt-4 flex items-center justify-center">
<div class="flex-1">
<IconButton class="text-black dark:text-white" @click="openAddModal">
<div class="w-full mt-4 flex justify-between items-center">
<div class="w-1/3 flex justify-start items-center">
<button
class="py-1.5 px-2 duration-100 grid gap-2 place-items-center grid-flow-col rounded-sm text-black dark:text-white hover:bg-dark dark:hover:bg-light hover:bg-opacity-30 dark:hover:bg-opacity-30"
@click="openAddModal"
>
<AddIcon />
</IconButton>
<span class="text-black dark:text-white"
>Add new
{{ selectedTab === Tab.EARNING ? "earning" : "expense" }}</span
>
</button>
</div>
<div class="flex-1 self-center">
<div class="w-1/3 flex justify-center">
<PaginationTab
:pagination="
selectedTab === Tab.EARNING ? earningsPagination : expensesPagination
"
@on-page-change="changePage"
/>
</div>
<div class="flex-1 grid grid-flow-col gap-2 text-sm min-w-fit">
<span
class="p-2 rounded-md bg-green-600 bg-opacity-50 hover:bg-opacity-100 duration-200"
>Total Earnings: {{ maskCurrency(totalEarnings) }}</span
>

<span class="p-2 rounded-md bg-red-600 bg-opacity-50 hover:bg-opacity-100"
>Total Expenses: {{ maskCurrency(totalExpenses) }}</span
>

<span
class="p-2 rounded-md"
:class="{
'bg-red-600': balance < 0,
'bg-green-600': balance > 0,
'bg-gray-600': balance == 0,
}"
>Balance: {{ maskCurrency(balance) }}</span
>
<div class="w-1/3 flex justify-end">
<BalanceTab
:earnings_subtotal="
earnings && earnings.length > 0 ? earnings[0].sub_total : 0
"
:expenses_subtotal="
expenses && expenses.length > 0 ? expenses[0].sub_total : 0
"
/>
</div>
</div>

Expand Down
9 changes: 5 additions & 4 deletions frontend/src/components/ui/PaginationTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const visiblePages = computed(() => {
<div class="flex justify-center gap-2 text-sm">
<button
@click="handlePageChange(pagination!.page - 1)"
class="px-2 text-black dark:text-white"
class="px-2 text-black dark:text-white duration-200"
:disabled="pagination && pagination.prev_page === 0"
:class="{
'opacity-30': pagination && pagination.prev_page === 0,
Expand All @@ -55,16 +55,17 @@ const visiblePages = computed(() => {
v-for="page in visiblePages"
:key="page"
@click="handlePageChange(page)"
class="px-2 text-black dark:text-white rounded-lg"
class="px-2 text-black dark:text-white rounded-lg duration-200"
:class="{
underline: pagination && pagination.page === page,
'opacity-30 pointer-events-none':
pagination && pagination.page === page,
}"
>
{{ page }}
</button>
<button
@click="handlePageChange(pagination!.page + 1)"
class="px-2 text-black dark:text-white rounded-lg"
class="px-2 text-black dark:text-white rounded-lg duration-200"
:disabled="pagination && pagination.next_page === 0"
:class="{
'opacity-30': pagination && pagination.next_page === 0,
Expand Down
1 change: 0 additions & 1 deletion frontend/wailsjs/go/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,4 +327,3 @@ export namespace types {
}

}

0 comments on commit efc202e

Please sign in to comment.