Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: logic of adding expenses to signals after submitting #8

Merged
merged 2 commits into from
Jun 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion islands/Loader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default function Loader() {
categories.value = labels;
});

fetch("/api/paymentMethods").then(async (res) => {
fetch("/api/payment-methods").then(async (res) => {
if (!res.ok) {
// TODO show error message
return;
Expand Down
24 changes: 5 additions & 19 deletions islands/forms/ExpenseForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useRef, useState } from "preact/hooks";
import { PaymentType } from "@/utils/constants.ts";
import InputSelector from "@/islands/InputSelector.tsx";
import { daysInMonth, formDate, stripDate } from "@/utils/date.ts";
import { daysInMonth, formDate } from "@/utils/date.ts";
import { expenses } from "@/signals/expenses.ts";
import { ExpenseWithoutUser } from "@/db/models/expense.ts";
import { activeMonth, activeYear } from "@/signals/menu.ts";
Expand Down Expand Up @@ -78,16 +78,9 @@ export default function ExpenseForm(props: ExpenseFormProps) {
}

const updatedExpense = await res.json() as ExpenseWithoutUser;
const updatedExpenseDate = stripDate(new Date(updatedExpense.payment.date));

if (
updatedExpenseDate.month === activeMonth.value &&
updatedExpenseDate.year === activeYear.value
) {
expenses.value = expenses.value.map((exp) =>
exp.id === updatedExpense.id ? updatedExpense : exp
);
}
expenses.value = expenses.value.map((exp) =>
exp.id === updatedExpense.id ? updatedExpense : exp
);

// TODO trigger toast
updateAfterSubmit(
Expand Down Expand Up @@ -130,14 +123,7 @@ export default function ExpenseForm(props: ExpenseFormProps) {
}

const addedExpense = await res.json() as ExpenseWithoutUser;
const addedExpenseDate = stripDate(new Date(addedExpense.payment.date));

if (
addedExpenseDate.month === activeMonth.value &&
addedExpenseDate.year === activeYear.value
) {
expenses.value = [...expenses.value, addedExpense];
}
expenses.value = [...expenses.value, addedExpense];

// TODO trigger toast
updateAfterSubmit(
Expand Down
28 changes: 22 additions & 6 deletions routes/api/expenses/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { Handlers } from "$fresh/server.ts";
import { PaymentType } from "@/utils/constants.ts";
import { z } from "zod";
import ExpenseService, { ExpenseWithoutUser } from "@/db/models/expense.ts";
import ExpenseService, {
ExpenseWithoutUser,
RawExpense,
} from "@/db/models/expense.ts";
import { SignedInState } from "@/plugins/session.ts";
import logger from "@/utils/logger.ts";
import ExpenseInputFactory from "@/utils/expenses/factory.ts";
import { stripDate, today } from "@/utils/date.ts";

const CreateExpenseSchema = z
.object({
Expand Down Expand Up @@ -39,12 +43,24 @@ export const handler: Handlers<ExpenseWithoutUser, SignedInState> = {
const factory = new ExpenseInputFactory(data, userId);
const inputs = await factory.build();
const promises = inputs.map((input) => ExpenseService.create(input));
const expenses = await Promise.all(promises);
const expenses: RawExpense[] = await Promise.all(promises);
logger.info("Expenses created", { amount: expenses.length });

const firstExpense = expenses.sort(
(a, b) => a.payment.date.getTime() - b.payment.date.getTime(),
)[0];
return Response.json(firstExpense, { status: 201 });
let currentMonthExpense: RawExpense = expenses[0];
if (expenses.length > 0) {
const found = expenses.find((expense) => {
const { month } = today();
const { month: expenseMonth } = stripDate(
new Date(expense.payment.date),
);
return expenseMonth === month;
});

if (found) {
currentMonthExpense = found;
}
}

return Response.json(currentMonthExpense, { status: 201 });
},
};
61 changes: 30 additions & 31 deletions signals/expenses.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,43 @@
import { computed, signal } from "@preact/signals";
import { ExpenseWithoutUser } from "@/db/models/expense.ts";
import { PaymentType } from "@/utils/constants.ts";
import { stripDate } from "@/utils/date.ts";
import { activeMonth } from "@/signals/menu.ts";
import { SignalLike } from "$fresh/src/types.ts";

export const expenses = signal<ExpenseWithoutUser[]>([]);

export const fixedExpenses = computed(() => {
return expenses.value.filter(
(expense) => expense.payment.type === PaymentType.FIXED,
);
});
export const totalFixedExpenses = computed(() => {
return fixedExpenses.value.reduce((acc, expense) => acc + expense.price, 0);
});
const filterExpensesByType = (type: PaymentType) => {
return computed(() => {
return expenses.value.filter(
(expense) =>
stripDate(new Date(expense.payment.date)).month === activeMonth.value &&
expense.payment.type === type,
);
});
};

export const overTimeExpenses = computed(() => {
return expenses.value.filter(
(expense) => expense.payment.type === PaymentType.OVER_TIME,
);
});
export const totalOverTimeExpenses = computed(() => {
return overTimeExpenses.value.reduce(
(acc, expense) => acc + expense.price,
0,
);
});
export const fixedExpenses = filterExpensesByType(PaymentType.FIXED);
export const overTimeExpenses = filterExpensesByType(PaymentType.OVER_TIME);
export const currentMonthExpenses = filterExpensesByType(PaymentType.CURRENT);

export const currentMonthExpenses = computed(() => {
return expenses.value.filter(
(expense) => expense.payment.type === PaymentType.CURRENT,
);
});
export const totalCurrentMonthExpenses = computed(() => {
return currentMonthExpenses.value.reduce(
(acc, expense) => acc + expense.price,
0,
);
});
const computeTotal = (expenseSignal: SignalLike<ExpenseWithoutUser[]>) => {
return computed(() => {
return expenseSignal.value.reduce((acc, expense) => acc + expense.price, 0);
});
};

export const totalFixedExpenses = computeTotal(fixedExpenses);
export const totalOverTimeExpenses = computeTotal(overTimeExpenses);
export const totalCurrentMonthExpenses = computeTotal(currentMonthExpenses);

export const totalExpenses = computed(() => {
return expenses.value.reduce((acc, expense) => acc + expense.price, 0);
return expenses.value
.filter(
(expense) =>
stripDate(new Date(expense.payment.date)).month === activeMonth.value,
)
.reduce((acc, expense) => acc + expense.price, 0);
});

export function getSignalFromPaymentType(type: PaymentType) {
Expand Down