You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

275 lines
10 KiB
JavaScript

3 years ago
import React, { useState } from 'react';
import Pagination from '@/Components/Pagination';
import Authenticated from '@/Layouts/Authenticated';
3 years ago
import { Head, useForm } from '@inertiajs/inertia-react';
import { toast } from 'react-toastify';
import moment from 'moment';
3 years ago
import NumberFormat from 'react-number-format';
3 years ago
import { formatIDR } from '@/utils';
export default function Transaction(props) {
3 years ago
const { categories, transactions } = props
const [transaction, setTransaction] = useState(null)
3 years ago
const [showForm, setShowForm] = useState(false)
3 years ago
const { data, setData, errors, post, put, processing, delete: destroy } = useForm({
category_id: '',
description: '',
amount: 0,
date: moment().format('yyyy-MM-DD'),
is_income: 0,
income_type: 0
})
3 years ago
const toggleForm = (transaction = null) => {
setShowForm(!showForm)
if(transaction !== null) {
handleEdit(transaction)
}else{
handleReset()
}
}
3 years ago
const toggleCashType = () => {
setData('income_type', data.income_type === 0 ? 1 : 0)
}
const toggleIncome = () => {
3 years ago
setData({
...data,
category_id: '',
3 years ago
description: '',
is_income: data.is_income === 0 ? 1 : 0,
income_type: 1,
3 years ago
})
3 years ago
}
const handleSelectedcategory = (e) => {
3 years ago
const category = categories.find(cat => +cat.id === +e.target.value)
setData({
...data,
description: category.description,
category_id: e.target.value
})
3 years ago
}
const handleChange = (e) => {
const key = e.target.id;
const value = e.target.value
setData(key, value)
}
const handleReset = () => {
setTransaction(null)
setData({
category_id: '',
description: '',
amount: 0,
date: moment().format('yyyy-MM-DD'),
is_income: 0,
income_type: 0
})
}
const handleDelete = (transaction) => {
destroy(route('transactions.destroy', transaction), {
onBefore: () => confirm('Are you sure you want to delete this record?'),
onSuccess: () => Promise.all([
handleReset(),
toast.success('data has been deleted')
])
})
}
const handleEdit = (transaction) => {
setTransaction(transaction)
setData({
category_id: transaction.category_id === null ? '' : transaction.category_id,
description: transaction.description,
amount: transaction.amount,
date: moment(transaction.date).format('yyyy-MM-DD'),
is_income: +transaction.is_income,
income_type: +transaction.income_type
})
}
const handleSubmit = (e) => {
e.preventDefault()
if(transaction !== null) {
put(route('transactions.update', transaction), {
onSuccess: () => Promise.all([
3 years ago
toggleForm(),
3 years ago
handleReset(),
toast.success('The Data has been changed')
])})
return
}
post(route('transactions.store'), {
onSuccess: () => Promise.all([
3 years ago
toggleForm(),
3 years ago
handleReset(),
toast.success('Data has been saved')
])
})
}
return (
<Authenticated
errors={props.errors}
header={<h2 className="font-semibold text-xl text-gray-800 leading-tight">Transaction</h2>}
>
<Head title="Transaction" />
3 years ago
<div className="flex flex-col space-y-2 py-12">
<div className="w-full px-6 md:pr-8">
3 years ago
<div className="card bg-white">
<div className="card-body">
3 years ago
<div className="btn btn-outline max-w-min my-2" onClick={() => toggleForm()}>Tambah</div>
3 years ago
<div className="overflow-x-auto">
<table className="table w-full table-zebra">
<thead>
<tr>
<th>Date</th>
3 years ago
<th>Type</th>
<th>Category Name</th>
<th className="w-32">Cash In/Out</th>
3 years ago
<th>Description</th>
<th>Amount</th>
3 years ago
<th className="w-52"></th>
3 years ago
</tr>
</thead>
<tbody className={processing ? "opacity-70" : ""}>
{transactions?.data?.map(transaction => (
<tr key={transaction.id}>
<td>{moment(transaction.date).format('DD/MM/yyyy')}</td>
<td>
{+transaction.is_income === 0 ? (
<div className="badge badge-secondary">Expense</div>
) : (
<div className="badge badge-primary">Income</div>
)}
</td>
<td>{transaction?.category?.name}</td>
<td>
{+transaction.income_type === 0 ? (
<div className="badge badge-secondary">Cash Out</div>
) : (
<div className="badge badge-accent">Cash In</div>
)}
</td>
<td>{transaction.description}</td>
<td>{formatIDR(transaction.amount)}</td>
<td>
3 years ago
<div className="btn btn-warning mx-1" onClick={() => toggleForm(transaction)}>Edit</div>
3 years ago
<div className="btn btn-error mx-1" onClick={() => handleDelete(transaction)}>Delete</div>
</td>
</tr>
3 years ago
))}
</tbody>
</table>
</div>
3 years ago
<Pagination links={transactions?.links} />
</div>
</div>
</div>
3 years ago
</div>
<div id="create-modal" className="modal" style={showForm ? {opacity: 1, pointerEvents: 'auto', visibility: 'visible'} : {}}>
<div className="modal-box">
<div className="form-control">
<label className="label">
<span className="label-text">Date</span>
</label>
<input
type="date"
className={`input input-bordered ${errors.date ? 'input-error' : ''}`}
id="date"
value={data.date}
onChange={handleChange}
/>
<label className="label">
<span className="label-text-alt">
{errors.date}
</span>
</label>
</div>
<div className="form-control">
<label className="cursor-pointer label">
<input type="checkbox" checked={data.is_income === 1 ? true : false} onChange={toggleIncome} className="checkbox checkbox-primary"/>
<span className="label-text font-bold">Income</span>
</label>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Category</span>
</label>
<select
className={`select select-bordered w-full ${errors.category_id && 'select-error'}`}
id="category_id"
onChange={handleSelectedcategory}
disabled={data.is_income === 1}
value={data.category_id}
>
<option disabled="disabled" selected={'' === data.category_id} value=''>Choose your category</option>
{categories.map(category => (
<option key={category.id} value={category.id} selected={category.id === data.category_id}>{category.name}</option>
)
)}
</select>
<label className="label">
<span className="label-text-alt">
{errors.category_id}
</span>
</label>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Description</span>
</label>
<input
type="text"
placeholder="Description"
className={`input input-bordered ${errors.description ? 'input-error' : ''}`}
id="description"
value={data.description}
onChange={handleChange}
/>
<label className="label">
<span className="label-text-alt">
{errors.description}
</span>
</label>
</div>
<div className="form-control">
<label className="cursor-pointer label">
<span className="label-text font-bold">{data.income_type === 0 ? 'Cash Out' : 'Cash In'}</span>
<input type="checkbox" checked={data.income_type === 0 ? true : false} disabled={data.is_income === 1} className="toggle" onChange={toggleCashType}/>
</label>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Amount</span>
</label>
<NumberFormat
thousandSeparator={true}
className={`input input-bordered ${errors.amount ? 'input-error' : ''}`}
value={data.amount}
thousandSeparator="."
decimalSeparator=","
onValueChange={({value}) => setData('amount', value)}
/>
<label className="label">
<span className="label-text-alt">
{errors.amount}
</span>
</label>
</div>
<div className="modal-action">
<button className={`btn btn-primary ${processing && 'animate-spin'}`} onClick={handleSubmit} disabled={processing}>Add</button>
<button className="btn btn-secondary" onClick={handleReset} disabled={processing}>Clear</button>
<button className="btn btn-outline btn-secondary" onClick={() => toggleForm()} disabled={processing}>Close</button>
</div>
</div>
3 years ago
</div>
</Authenticated>
);
}