Skip to content

Commit

Permalink
feat: Add filters for refunds
Browse files Browse the repository at this point in the history
  • Loading branch information
letehaha committed Sep 22, 2024
1 parent fa8ee80 commit 4eee813
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
<script setup lang="ts">
import { computed } from "vue";
import { computed, ref } from "vue";
import { TRANSACTION_TYPES, TransactionModel } from "shared-types";
import { useInfiniteQuery } from "@tanstack/vue-query";
import { CircleAlert } from "lucide-vue-next";
import { isEqual } from "lodash-es";
import { isDate } from "date-fns";
import { ListFilterIcon, CircleAlert } from "lucide-vue-next";
import { VUE_QUERY_CACHE_KEYS } from "@/common/const";
import { cn } from "@/lib/utils";
import { loadTransactions } from "@/api/transactions";
import TransactionRecrod from "@/components/transactions-list/transaction-record.vue";
import * as Dialog from "@/components/lib/ui/dialog";
import Button from "@/components/lib/ui/button/Button.vue";
import DateField from "@/components/fields/date-field.vue";
import InputField from "@/components/fields/input-field.vue";
import { removeValuesFromObject } from "@/common/utils/remove-values-from-object";
export interface RecordListModalProps {
transactionType: TRANSACTION_TYPES;
Expand All @@ -17,16 +23,60 @@ export interface RecordListModalProps {
const props = defineProps<RecordListModalProps>();
const DEFAULT_FILTERS: {
start: Date | null;
end: Date | null;
amountGte: number | null;
amountLte: number | null;
} = {
// TODO: by accounts
// TODO: by categories
start: null,
end: null,
amountGte: null,
amountLte: null,
};
const isFiltersDialogOpen = ref(false);
const filters = ref({ ...DEFAULT_FILTERS });
const appliedFilters = ref({ ...DEFAULT_FILTERS });
const isResetButtonDisabled = computed(() => isEqual(filters.value, DEFAULT_FILTERS));
const isAnyFiltersApplied = computed(() => !isEqual(appliedFilters.value, DEFAULT_FILTERS));
const isFiltersOutOfSync = computed(() => !isEqual(filters.value, appliedFilters.value));
const resetFilters = () => {
filters.value = { ...DEFAULT_FILTERS };
appliedFilters.value = { ...DEFAULT_FILTERS };
isFiltersDialogOpen.value = false;
};
const applyFilters = () => {
appliedFilters.value = { ...filters.value };
isFiltersDialogOpen.value = false;
};
const limit = 15;
const fetchTransactions = ({ pageParam = 0 }) => {
const fetchTransactions = ({
pageParam,
filter,
}: {
pageParam: number;
filter: typeof appliedFilters.value;
}) => {
const from = pageParam * limit;
return loadTransactions({
limit,
from,
transactionType: props.transactionType,
excludeTransfer: true,
excludeRefunds: true,
});
return loadTransactions(
removeValuesFromObject<Parameters<typeof loadTransactions>[0]>({
limit,
from,
transactionType: props.transactionType,
excludeTransfer: true,
excludeRefunds: true,
endDate: isDate(filter.end) ? filter.end.toISOString() : undefined,
startDate: isDate(filter.start) ? filter.start.toISOString() : undefined,
amountGte: filter.amountGte,
amountLte: filter.amountLte,
}),
);
};
const {
Expand All @@ -35,8 +85,12 @@ const {
hasNextPage,
isFetched,
} = useInfiniteQuery({
queryKey: [VUE_QUERY_CACHE_KEYS.recordsPageTransactionList, props.transactionType],
queryFn: fetchTransactions,
queryKey: [
VUE_QUERY_CACHE_KEYS.recordsPageTransactionList,
props.transactionType,
appliedFilters,
],
queryFn: ({ pageParam }) => fetchTransactions({ pageParam, filter: appliedFilters.value }),
initialPageParam: 0,
getNextPageParam: (lastPage, pages) => {
// No more pages to load
Expand All @@ -55,7 +109,70 @@ const handlerRecordClick = (transaction: TransactionModel) => {
</script>

<template>
<div class="grid gap-4 grid-rows-[minmax(0,1fr)_max-content]">
<div class="grid gap-2 grid-rows-[minmax(0,1fr)_max-content]">
<div class="flex">
<Dialog.Dialog v-model:open="isFiltersDialogOpen">
<Dialog.DialogTrigger as-child>
<Button variant="ghost" size="icon" class="ml-auto">
<div class="relative">
<ListFilterIcon />

<template v-if="isAnyFiltersApplied">
<div class="size-3 rounded-full bg-primary absolute -top-1 -right-1" />
</template>
</div>
</Button>
</Dialog.DialogTrigger>
<Dialog.DialogContent class="max-w-[350px]">
<Dialog.DialogHeader class="mb-6">
<Dialog.DialogTitle> Select filters </Dialog.DialogTitle>
</Dialog.DialogHeader>
<div class="grid gap-4">
<DateField
v-model="filters.start"
:calendar-options="{
maxDate: filters.end,
}"
label="From date"
/>
<DateField
v-model="filters.end"
:calendar-options="{
minDate: filters.start,
}"
label="To date"
/>

<div class="flex gap-2">
<InputField
v-model="filters.amountGte"
label="Amount from (gte)"
placeholder=">= than"
/>
<InputField v-model="filters.amountLte" label="To (lte)" placeholder="<= than" />
</div>

<div class="flex gap-2">
<Button
variant="secondary"
:disabled="isResetButtonDisabled"
class="flex-shrink w-full"
@click="resetFilters"
>
Reset
</Button>

<template v-if="isFiltersOutOfSync">
<Button variant="default" class="flex-shrink w-full" @click="applyFilters">
Apply
</Button>
</template>
</div>
</div>
</Dialog.DialogContent>
</Dialog.Dialog>
</div>

<div class="overflow-y-auto">
<template v-if="isFetched && transactionsPages">
<template v-for="item in transactionsPages?.pages?.flat()" :key="item.id">
Expand Down Expand Up @@ -94,6 +211,12 @@ const handlerRecordClick = (transaction: TransactionModel) => {
Create some to proceed
</template>
<template v-else> There's no transactions to select. Create some to proceed </template>
<template v-if="isAnyFiltersApplied">
<Button class="mt-4 w-full" variant="secondary" @click="resetFilters">
Reset filters
</Button>
</template>
</p>
</template>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/records/records.vue
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ const fetchTransactions = ({
filter,
}: {
pageParam: number;
filter: typeof filters.value;
filter: typeof appliedFilters.value;
}) => {
const from = pageParam * limit;
Expand Down

0 comments on commit 4eee813

Please sign in to comment.