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
+
+
+
+
+ );
+};
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.
+
+ )}
+
+ {/*
Contacts
+
+
+
+
+ Name |
+ City |
+
+ Phone
+ |
+
+
+
+ {payment.contacts.map(
+ ({ id, name, phone, city, deleted_at }) => {
+ return (
+
+
+
+ {name}
+ {deleted_at && (
+
+ )}
+
+ |
+
+
+ {city}
+
+ |
+
+
+ {phone}
+
+ |
+
+
+
+
+ |
+
+ );
+ }
+ )}
+ {payment.contacts.length === 0 && (
+
+
+ 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
+
+
+
+
+
+
+ ID Invoice |
+ Keterangan |
+ Jumlah |
+ Tanggal penagihan |
+
+ Tanggal pembayaran
+ |
+
+
+
+ {data.map(({ id, description, amount, invoice_id, invoice_date, created_at, deleted_at }) => {
+ return (
+
+
+
+ {invoice_id}
+ {deleted_at && (
+
+ )}
+
+ |
+
+
+ {description}
+
+ |
+
+
+ {amount}
+
+ |
+
+
+ {invoice_date}
+
+ |
+
+
+ {created_at}
+
+ |
+
+
+
+
+ |
+
+ );
+ })}
+ {data.length === 0 && (
+
+
+ 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');
+ });
});