First steps towards reusing the abstract API for expenses
This commit is contained in:
parent
0cdfccb0ca
commit
b15b90b494
@ -1,40 +1,40 @@
|
||||
/* Copyright (C) 2024 Manuel Bustillo*/
|
||||
// /* Copyright (C) 2024 Manuel Bustillo*/
|
||||
|
||||
import { Expense } from '@/app/lib/definitions';
|
||||
import { getCsrfToken, getSlug } from '@/app/lib/utils';
|
||||
// import { Expense } from '@/app/lib/definitions';
|
||||
// import { getCsrfToken, getSlug } from '@/app/lib/utils';
|
||||
|
||||
export function loadExpenses(onLoad?: (expenses: Expense[]) => void) {
|
||||
fetch(`/api/${getSlug()}/expenses`)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
onLoad && onLoad(data.map((record: any) => {
|
||||
return ({
|
||||
id: record.id,
|
||||
name: record.name,
|
||||
amount: record.amount,
|
||||
pricingType: record.pricing_type
|
||||
});
|
||||
}));
|
||||
}, (error) => {
|
||||
return [];
|
||||
});
|
||||
}
|
||||
// export function loadExpenses(onLoad?: (expenses: Expense[]) => void) {
|
||||
// fetch(`/api/${getSlug()}/expenses`)
|
||||
// .then((response) => response.json())
|
||||
// .then((data) => {
|
||||
// onLoad && onLoad(data.map((record: any) => {
|
||||
// return ({
|
||||
// id: record.id,
|
||||
// name: record.name,
|
||||
// amount: record.amount,
|
||||
// pricingType: record.pricing_type
|
||||
// });
|
||||
// }));
|
||||
// }, (error) => {
|
||||
// return [];
|
||||
// });
|
||||
// }
|
||||
|
||||
export function updateExpense(expense: Expense) {
|
||||
fetch(`/api/${getSlug()}/expenses/${expense.id}`,
|
||||
{
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({
|
||||
expense: {
|
||||
name: expense.name,
|
||||
amount: expense.amount,
|
||||
pricing_type: expense.pricingType,
|
||||
}
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': getCsrfToken(),
|
||||
}
|
||||
})
|
||||
.catch((error) => console.error(error));
|
||||
}
|
||||
// export function updateExpense(expense: Expense) {
|
||||
// fetch(`/api/${getSlug()}/expenses/${expense.id}`,
|
||||
// {
|
||||
// method: 'PUT',
|
||||
// body: JSON.stringify({
|
||||
// expense: {
|
||||
// name: expense.name,
|
||||
// amount: expense.amount,
|
||||
// pricing_type: expense.pricingType,
|
||||
// }
|
||||
// }),
|
||||
// headers: {
|
||||
// 'Content-Type': 'application/json',
|
||||
// 'X-CSRF-TOKEN': getCsrfToken(),
|
||||
// }
|
||||
// })
|
||||
// .catch((error) => console.error(error));
|
||||
// }
|
@ -6,12 +6,12 @@ export interface Entity {
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export type Expense = {
|
||||
id: string;
|
||||
name: string;
|
||||
amount: number;
|
||||
pricingType: 'fixed' | 'per person';
|
||||
};
|
||||
// export type Expense = {
|
||||
// id: string;
|
||||
// name: string;
|
||||
// amount: number;
|
||||
// pricingType: 'fixed' | 'per person';
|
||||
// };
|
||||
|
||||
export type TableArrangement = {
|
||||
id: string;
|
||||
|
39
app/lib/expense.tsx
Normal file
39
app/lib/expense.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import { Serializable } from "../api/abstract-api";
|
||||
import { Entity } from "./definitions";
|
||||
|
||||
export const pricingTypes = ['fixed', 'per person'] as const;
|
||||
export type PricingType = typeof pricingTypes[number];
|
||||
|
||||
export class Expense implements Entity {
|
||||
id?: string;
|
||||
name: string;
|
||||
amount: number;
|
||||
pricingType: PricingType;
|
||||
|
||||
constructor(id?: string, name?: string, amount?: number, pricingType?: PricingType) {
|
||||
this.id = id;
|
||||
this.name = name || '';
|
||||
this.amount = amount || 0;
|
||||
this.pricingType = pricingType || 'fixed';
|
||||
}
|
||||
}
|
||||
|
||||
export class ExpenseSerializer implements Serializable<Expense>{
|
||||
fromJson(data: any): Expense {
|
||||
return new Expense(data.id, data.name, data.amount, data.pricing_type);
|
||||
}
|
||||
|
||||
toJson(expense: Expense): string {
|
||||
return JSON.stringify({
|
||||
expense: {
|
||||
name: expense.name,
|
||||
amount: expense.amount,
|
||||
pricing_type: expense.pricingType
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
apiPath(): string {
|
||||
return 'expenses';
|
||||
}
|
||||
}
|
@ -2,18 +2,19 @@
|
||||
|
||||
'use client'
|
||||
|
||||
import { loadExpenses, updateExpense } from '@/app/api/expenses';
|
||||
import { Expense } from '@/app/lib/definitions';
|
||||
import { useState } from "react";
|
||||
import InlineTextField from "../components/form/inlineTextField";
|
||||
import TableOfContents from "../components/table-of-contents";
|
||||
import { AbstractApi } from '@/app/api/abstract-api';
|
||||
import { Expense, ExpenseSerializer } from '@/app/lib/expense';
|
||||
|
||||
export default function ExpensesTable() {
|
||||
const [expenses, setExpenses] = useState<Array<Expense>>([]);
|
||||
const [expensesLoaded, setExpensesLoaded] = useState(false);
|
||||
|
||||
|
||||
function refreshExpenses() {
|
||||
loadExpenses((expenses) => {
|
||||
new AbstractApi<Expense>().getAll(new ExpenseSerializer(), (expenses: Expense[]) => {
|
||||
setExpenses(expenses);
|
||||
setExpensesLoaded(true);
|
||||
});
|
||||
@ -21,6 +22,9 @@ export default function ExpensesTable() {
|
||||
|
||||
!expensesLoaded && refreshExpenses();
|
||||
|
||||
const api = new AbstractApi<Expense>();
|
||||
const serializer = new ExpenseSerializer();
|
||||
|
||||
return (
|
||||
<TableOfContents
|
||||
headers={['Name', 'Amount (€)', 'Pricing Type']}
|
||||
|
Loading…
x
Reference in New Issue
Block a user