diff --git a/app/Http/Controllers/PaymentsController.php b/app/Http/Controllers/PaymentsController.php new file mode 100644 index 0000000..cd2cea9 --- /dev/null +++ b/app/Http/Controllers/PaymentsController.php @@ -0,0 +1,103 @@ + Request::all('search', 'trashed'), + 'payments' => Payment::orderBy('id', 'desc') + ->filter(Request::only('search', 'trashed')) + ->paginate() + ->transform(function ($payment) { + return [ + 'id' => $payment->id, + 'description' => $payment->description, + 'amount' => $payment->amount, + 'invoice_id' => $payment->invoice_id, + 'invoice_date' => $payment->invoice->created_at->format('d F Y'), + 'created_at' => $payment->created_at->format('d F Y'), + 'deleted_at' => $payment->deleted_at, + ]; + }), + // ->only('id', 'room_id', 'renter_id', 'start_at', 'end_at', 'deleted_at') + ]); + } + + public function create() + { + return Inertia::render('Payments/Create', [ + 'invoices' => Invoice::all(), + ]); + } + + public function store() + { + Payment::create( + Request::validate([ + 'description' => ['required'], + 'amount' => ['required', 'numeric'], + 'invoice_id' => ['required', 'exists:invoices,id'], + ]) + ); + + return Redirect::route('payments.index')->with('success', 'Data Pembayaran berhasil ditambahkan.'); + } + + public function edit(Payment $payment) + { + return Inertia::render('Payments/Edit', [ + 'payment' => [ + 'id' => $payment->id, + 'description' => $payment->description, + 'amount' => $payment->amount, + 'invoice_id' => $payment->invoice_id, + 'invoice' => $payment->invoice, + 'created_at' => $payment->created_at->format('Y-m-d'), + 'deleted_at' => $payment->deleted_at + ], + 'invoices' => Invoice::all()->transform(function ($invoice) { + return [ + 'id' => $invoice->id, + 'created_at' => $invoice->created_at->format('d F Y'), + ]; + }), + ]); + } + + public function update(Payment $payment) + { + $payment->update( + Request::validate([ + 'description' => ['required'], + 'amount' => ['required', 'numeric'], + 'invoice_id' => ['required', 'exists:invoices,id'], + ]) + ); + + return Redirect::back()->with('success', 'Data Pembayaran berhasil diperbarui.'); + } + + public function destroy(Payment $payment) + { + $payment->delete(); + + return Redirect::back()->with('success', 'Data Pembayaran berhasil dihapus.'); + } + + public function restore(Payment $payment) + { + $payment->restore(); + + return Redirect::back()->with('success', 'Data Pembayaran berhasil dipulihkan.'); + } +} diff --git a/app/Payment.php b/app/Payment.php new file mode 100644 index 0000000..4b3a4dc --- /dev/null +++ b/app/Payment.php @@ -0,0 +1,30 @@ +belongsTo(Invoice::class); + } + + public function scopeFilter($query, array $filters) + { + $query->when($filters['search'] ?? null, function ($query, $search) { + $query->where('invoice_id', 'like', "%$search$"); + $query->orWhere('description', 'like', "%$search$"); + $query->orWhere('amount', 'like', "%$search$"); + })->when($filters['trashed'] ?? null, function ($query, $trashed) { + if ($trashed === 'with') { + $query->withTrashed(); + } elseif ($trashed === 'only') { + $query->onlyTrashed(); + } + }); + } +} diff --git a/database/migrations/2020_05_05_113952_create_payments_table.php b/database/migrations/2020_05_05_113952_create_payments_table.php index c9b8553..39a6014 100644 --- a/database/migrations/2020_05_05_113952_create_payments_table.php +++ b/database/migrations/2020_05_05_113952_create_payments_table.php @@ -18,6 +18,7 @@ public function up() $table->foreignId('invoice_id')->constrained()->onDelete('cascade'); $table->text('description'); $table->integer('amount'); + $table->softDeletes(); $table->timestamps(); }); } diff --git a/resources/js/Pages/Payments/Create.jsx b/resources/js/Pages/Payments/Create.jsx new file mode 100644 index 0000000..704a9de --- /dev/null +++ b/resources/js/Pages/Payments/Create.jsx @@ -0,0 +1,100 @@ +import React, { useState } from 'react'; +import Helmet from 'react-helmet'; +import { Inertia } from '@inertiajs/inertia'; +import { InertiaLink, usePage } from '@inertiajs/inertia-react'; +import Layout from '@/Shared/Layout'; +import LoadingButton from '@/Shared/LoadingButton'; +import TextInput from '@/Shared/TextInput'; +import SelectInput from '@/Shared/SelectInput'; + +export default () => { + const { errors, invoices } = usePage(); + const [sending, setSending] = useState(false); + + const [values, setValues] = useState({ + description: '', + amount: '', + invoice_id: '' + }); + + function handleChange(e) { + const key = e.target.name; + const value = e.target.value; + setValues(values => ({ + ...values, + [key]: value + })); + } + + function handleSubmit(e) { + e.preventDefault(); + setSending(true); + Inertia.post(route('payments.store'), values).then(() => { + setSending(false); + }); + } + + return ( + + +
+

+ + Pembayaran + + / Buat +

+
+
+
+ + + + + { + invoices.map((invoice) => ( + + )) + } + +
+
+ + Tambah Pembayaran + +
+
+
+
+
+ ); +}; diff --git a/resources/js/Pages/Payments/Edit.jsx b/resources/js/Pages/Payments/Edit.jsx new file mode 100644 index 0000000..f67d854 --- /dev/null +++ b/resources/js/Pages/Payments/Edit.jsx @@ -0,0 +1,205 @@ +import React, { useState } from 'react'; +import Helmet from 'react-helmet'; +import { Inertia } from '@inertiajs/inertia'; +import { InertiaLink, usePage } from '@inertiajs/inertia-react'; +import Layout from '@/Shared/Layout'; +import DeleteButton from '@/Shared/DeleteButton'; +import LoadingButton from '@/Shared/LoadingButton'; +import TextInput from '@/Shared/TextInput'; +import SelectInput from '@/Shared/SelectInput'; +import TrashedMessage from '@/Shared/TrashedMessage'; +import Icon from '@/Shared/Icon'; + +export default () => { + const { errors, payment, invoices } = usePage(); + const [sending, setSending] = useState(false); + + const [values, setValues] = useState({ + description: payment.description || '', + amount: payment.amount || '', + invoice_id: payment.invoice_id || '' + }); + + function handleChange(e) { + const key = e.target.name; + const value = e.target.value; + setValues(values => ({ + ...values, + [key]: value + })); + } + + function handleSubmit(e) { + e.preventDefault(); + setSending(true); + Inertia.put( + route('payments.update', payment.id), + values + ).then(() => setSending(false)); + } + + function destroy() { + if (confirm('Apa anda yakin ingin menghapus data pembayaran ini?')) { + Inertia.delete(route('payments.destroy', payment.id)); + } + } + + function restore() { + if (confirm('Apa anda yakin ingin memulihkan data pembayaran ini?')) { + Inertia.put(route('payments.restore', payment.id)); + } + } + + return ( + + +
+

+ + Pembayaran + + / + {`Penagihan #${payment.invoice_id}`} +

+ {payment.deleted_at && ( + + Data pembayaran ini telah dihapus. + + )} +
+
+
+ + + + + { + invoices.map((invoice) => ( + + )) + } + +
+
+ {!payment.deleted_at && ( + + Hapus Pembayaran + + )} + + Perbarui Pembayaran + +
+
+
+ {/*

Contacts

+
+ + + + + + + + + + {payment.contacts.map( + ({ id, name, phone, city, deleted_at }) => { + return ( + + + + + + + ); + } + )} + {payment.contacts.length === 0 && ( + + + + )} + +
NameCity + Phone +
+ + {name} + {deleted_at && ( + + )} + + + + {city} + + + + {phone} + + + + + +
+ No contacts found. +
+
*/} +
+
+ ); +}; diff --git a/resources/js/Pages/Payments/Index.jsx b/resources/js/Pages/Payments/Index.jsx new file mode 100644 index 0000000..fb44803 --- /dev/null +++ b/resources/js/Pages/Payments/Index.jsx @@ -0,0 +1,132 @@ +import React from 'react'; +import Helmet from 'react-helmet'; +import { InertiaLink, usePage } from '@inertiajs/inertia-react'; +import Layout from '@/Shared/Layout'; +import Icon from '@/Shared/Icon'; +import SearchFilter from '@/Shared/SearchFilter'; +import Pagination from '@/Shared/Pagination'; + +const Payments = () => { + const { payments } = usePage(); + const { links, data } = payments; + return ( +
+ +
+

Pembayaran

+
+ + + Tambah + Pembayaran + +
+
+ + + + + + + + + + + + {data.map(({ id, description, amount, invoice_id, invoice_date, created_at, deleted_at }) => { + return ( + + + + + + + + + ); + })} + {data.length === 0 && ( + + + + )} + +
ID InvoiceKeteranganJumlahTanggal penagihan + Tanggal pembayaran +
+ + {invoice_id} + {deleted_at && ( + + )} + + + + {description} + + + + {amount} + + + + {invoice_date} + + + + {created_at} + + + + + +
+ No payments found. +
+
+ +
+
+ ); +}; + +// Persisten layout +// Docs: https://inertiajs.com/pages#persistent-layouts +Payments.layout = page => ; + +export default Payments; diff --git a/resources/js/Shared/MainMenu.jsx b/resources/js/Shared/MainMenu.jsx index b2110e5..fd7fe51 100644 --- a/resources/js/Shared/MainMenu.jsx +++ b/resources/js/Shared/MainMenu.jsx @@ -10,7 +10,7 @@ export default ({ className }) => { - + ); }; \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index f6d9b60..48e4097 100644 --- a/routes/web.php +++ b/routes/web.php @@ -83,6 +83,17 @@ Route::delete('{lodging}', 'LodgingsController@destroy')->name('destroy'); Route::put('{lodging}/restore', 'LodgingsController@restore')->name('restore'); }); + + // Payments + Route::prefix('payments')->name('payments.')->group(function () { + Route::get('/', 'PaymentsController@index')->name('index')->middleware('remember'); + Route::get('create', 'PaymentsController@create')->name('create'); + Route::post('/', 'PaymentsController@store')->name('store'); + Route::get('{payment}/edit', 'PaymentsController@edit')->name('edit'); + Route::put('{payment}', 'PaymentsController@update')->name('update'); + Route::delete('{payment}', 'PaymentsController@destroy')->name('destroy'); + Route::put('{payment}/restore', 'PaymentsController@restore')->name('restore'); + }); });