83 lines
2.8 KiB
TypeScript
83 lines
2.8 KiB
TypeScript
/* Copyright (C) 2024 Manuel Bustillo*/
|
|
|
|
'use client';
|
|
|
|
import { AbstractApi } from '@/app/api/abstract-api';
|
|
import { Expense, ExpenseSerializer, PricingType, pricingTypes } from '@/app/lib/expense';
|
|
import { capitalize } from '@/app/lib/utils';
|
|
import { classNames } from '@/app/ui/components/button';
|
|
import { Dialog } from 'primereact/dialog';
|
|
import { Dropdown } from 'primereact/dropdown';
|
|
import { FloatLabel } from 'primereact/floatlabel';
|
|
import { InputText } from 'primereact/inputtext';
|
|
import { useState } from 'react';
|
|
|
|
export default function ExpenseFormDialog({ onCreate, onHide, expense, visible }: {
|
|
onCreate?: () => void,
|
|
onHide: () => void,
|
|
expense?: Expense,
|
|
visible: boolean,
|
|
}) {
|
|
|
|
const [name, setName] = useState<string>(expense?.name || '');
|
|
const [amount, setAmount] = useState<number>(expense?.amount || 0);
|
|
const [pricingType, setPricingType] = useState<PricingType>(expense?.pricingType || 'fixed');
|
|
|
|
const api = new AbstractApi<Expense>();
|
|
const serializer = new ExpenseSerializer();
|
|
|
|
function resetForm() {
|
|
setName('');
|
|
setAmount(0);
|
|
setPricingType('fixed');
|
|
}
|
|
|
|
function submitGroup() {
|
|
if (expense?.id !== undefined) {
|
|
expense.name = name;
|
|
expense.amount = amount;
|
|
expense.pricingType = pricingType;
|
|
|
|
api.update(serializer, expense, () => {
|
|
resetForm();
|
|
onCreate && onCreate();
|
|
});
|
|
} else {
|
|
|
|
api.create(serializer, new Expense(undefined, name, amount, pricingType), () => {
|
|
resetForm();
|
|
onCreate && onCreate();
|
|
});
|
|
}
|
|
}
|
|
|
|
return (
|
|
<>
|
|
|
|
<Dialog header="Add/edit expense" visible={visible} style={{ width: '60vw' }} onHide={onHide}>
|
|
<div className="card flex justify-evenly py-5">
|
|
<FloatLabel>
|
|
<InputText id="name" className='rounded-sm' value={name} onChange={(e) => setName(e.target.value)} />
|
|
<label htmlFor="name">Name</label>
|
|
</FloatLabel>
|
|
<FloatLabel>
|
|
<InputText id="amount" className='rounded-sm' value={amount.toString()} onChange={(e) => setAmount(parseFloat(e.target.value))} />
|
|
<label htmlFor="amount">Amount</label>
|
|
</FloatLabel>
|
|
<FloatLabel>
|
|
<Dropdown id="pricingType" className='rounded-sm min-w-32' value={pricingType} onChange={(e) => setPricingType(e.target.value)} options={
|
|
pricingTypes.map((type) => {
|
|
return { label: capitalize(type), value: type };
|
|
})
|
|
} />
|
|
<label htmlFor="pricingType">Pricing type</label>
|
|
</FloatLabel>
|
|
|
|
<button className={classNames('primary')} onClick={submitGroup} disabled={!(name.length > 0)}>
|
|
{expense?.id !== undefined ? 'Update' : 'Create'}
|
|
</button>
|
|
</div>
|
|
</Dialog>
|
|
</>
|
|
);
|
|
} |