From 6e3eb5edabb2cac595c790140b6077035dabff4a Mon Sep 17 00:00:00 2001 From: Aji Kamaludin Date: Wed, 15 Dec 2021 03:02:19 +0700 Subject: [PATCH] summary --- app/Http/Controllers/CategoryController.php | 4 +- app/Http/Controllers/ExpenseController.php | 63 +++--- app/Http/Controllers/SummaryController.php | 31 +++ app/Models/Budget.php | 5 + app/Models/Category.php | 2 +- app/Models/Transaction.php | 2 +- database/database.sqlite | Bin 61440 -> 61440 bytes jsconfig.json | 2 +- public/css/app.css | 225 +++++++++++-------- public/js/app.js | 228 +++++++++++++++++++- resources/js/Pages/ModalClosing.js | 21 ++ resources/js/Pages/Summary.js | 81 +++++++ resources/js/Pages/Transaction.js | 15 +- resources/js/app.js | 2 +- routes/web.php | 4 +- 15 files changed, 551 insertions(+), 134 deletions(-) create mode 100644 app/Http/Controllers/SummaryController.php create mode 100644 resources/js/Pages/ModalClosing.js create mode 100644 resources/js/Pages/Summary.js diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 29bd87c..1aad92e 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -31,7 +31,7 @@ class CategoryController extends Controller $category->budgets()->create([ 'budget' => $request->amount, 'start_date' => now()->toDateString(), - 'end_date' => now()->endOfMonth()->toDateString(), + 'end_date' => null, ]); return redirect()->route('categories'); @@ -51,7 +51,7 @@ class CategoryController extends Controller 'default_budget' => $request->amount ]); - $budget = $category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString()); + $budget = $category->budgets()->whereDate('end_date', null); $budget->update(['budget' => $request->amount]); return redirect()->route('categories'); diff --git a/app/Http/Controllers/ExpenseController.php b/app/Http/Controllers/ExpenseController.php index 3c8d5bf..41f74d2 100644 --- a/app/Http/Controllers/ExpenseController.php +++ b/app/Http/Controllers/ExpenseController.php @@ -31,15 +31,16 @@ class ExpenseController extends Controller DB::beginTransaction(); $transaction = Transaction::create($request->input()); - if ($request->is_income == 0 && $request->income_type == 0) { //total expense nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['total_used' => $budget->total_used + $request->amount]); + if ($request->is_income == 0) { + $budget = $transaction->category->budgets()->where('end_date', null)->first(); + if ($request->income_type == 0) { + $budget->update(['total_used' => $budget->total_used + $request->amount]); + } + if ($request->income_type == 1) { + $budget->update(['remain' => $budget->remain + $request->amount]); + } } - if ($request->is_income == 0 && $request->income_type == 1) { //total remain nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['remain' => $budget->remain + $request->amount]); - } DB::commit(); return redirect()->route('transactions'); @@ -58,27 +59,27 @@ class ExpenseController extends Controller DB::beginTransaction(); // return when it create - if ($transaction->is_income == 0 && $transaction->income_type == 0) { //total expense nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['total_used' => $budget->total_used - $transaction->amount]); - } - - if ($transaction->is_income == 0 && $transaction->income_type == 1) { //total remain nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['remain' => $budget->remain - $transaction->amount]); + if ($transaction->is_income == 0) { // pasti ada + $budget = $transaction->category->budgets()->where('end_date', null)->first(); + if ($request->income_type == 0) { + $budget->update(['total_used' => $budget->total_used - $request->amount]); + } + if ($request->income_type == 1) { + $budget->update(['remain' => $budget->remain - $request->amount]); + } } $transaction->update($request->input()); // add new - if ($request->is_income == 0 && $request->income_type == 0) { //total expense nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['total_used' => $budget->total_used + $request->amount]); - } - - if ($request->is_income == 0 && $request->income_type == 1) { //total remain nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['remain' => $budget->remain + $request->amount]); + if ($transaction->is_income == 0) { + $budget = $transaction->category->budgets()->where('end_date', null)->first(); + if ($request->income_type == 0) { + $budget->update(['total_used' => $budget->total_used + $request->amount]); + } + if ($request->income_type == 1) { + $budget->update(['remain' => $budget->remain + $request->amount]); + } } DB::commit(); @@ -89,14 +90,14 @@ class ExpenseController extends Controller { DB::beginTransaction(); // return when it create - if ($transaction->is_income == 0 && $transaction->income_type == 0) { //total expense nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['total_used' => $budget->total_used - $transaction->amount]); - } - - if ($transaction->is_income == 0 && $transaction->income_type == 1) { //total remain nambah - $budget = $transaction->category->budgets()->whereDate('end_date', now()->endOfMonth()->toDateString())->first(); - $budget->update(['remain' => $budget->remain - $transaction->amount]); + if ($transaction->is_income == 0 && $transaction->category->deleted_at == null) { // pasti ada + $budget = $transaction->category->budgets()->where('end_date', null)->first(); + if ($transaction->income_type == 0) { + $budget->update(['total_used' => $budget->total_used - $transaction->amount]); + } + if ($transaction->income_type == 1) { + $budget->update(['remain' => $budget->remain - $transaction->amount]); + } } $transaction->delete(); diff --git a/app/Http/Controllers/SummaryController.php b/app/Http/Controllers/SummaryController.php new file mode 100644 index 0000000..5f1160f --- /dev/null +++ b/app/Http/Controllers/SummaryController.php @@ -0,0 +1,31 @@ + Budget::where('end_date', null)->with(['category'])->paginate(10), + 'income' => Transaction::where('is_income', 1)->sum('amount'), + 'expense' => Transaction::where('is_income', 0)->sum('amount'), + 'balance' => Transaction::where('is_income', 1)->sum('amount') - Transaction::where('is_income', 0)->sum('amount') + ]); + } + + public function close(Request $request) + { + $request->validate([ + 'is_rolling' => 'required|in:0,1' + ]); + + if ($request->is_rolling == 1) { + // rolling is count + } + } +} diff --git a/app/Models/Budget.php b/app/Models/Budget.php index 16cd25f..26049dd 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -19,4 +19,9 @@ class Budget extends Model 'total_used', 'remain' ]; + + public function category() + { + return $this->belongsTo(Category::class)->withTrashed(); + } } diff --git a/app/Models/Category.php b/app/Models/Category.php index 2e02bdd..de1834f 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -18,7 +18,7 @@ class Category extends Model public function budgets() { - return $this->hasMany(Budget::class); + return $this->hasMany(Budget::class)->withTrashed(); } public function transactions() diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 2424f41..3b34ab2 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -21,6 +21,6 @@ class Transaction extends Model public function category() { - return $this->belongsTo(Category::class); + return $this->belongsTo(Category::class)->withTrashed(); } } diff --git a/database/database.sqlite b/database/database.sqlite index f92f342967b9ac3af76f698cd888e872ed4c0ebc..53e7229465c1bf39a7942af0e4b398d5509d66e0 100644 GIT binary patch delta 693 zcmaJ18g3nxjwb8DZ zMn|Qtoi#}JKlmaT6fb{0=6y@E+{`Y3It4uTSN`{>X-?UU zzzE8tvA>r;*PJvrX8lJ{AV^-s=qw->xfLBrkj^0rfKQPyj(~_H1^1(&>1t*&%+Jp) gbq@ysDOgcl5j-7dPCx)tf5Pv63R4$TE82Gc2XXj_F#rGn delta 1787 zcma)7J#W)c6n)Qu*7-C=h!#>Bdq4x$8w3;yb-+zrYBjM-ZL_)) zVxv|@76!x!q8<1F2#JvqF_oPGu`$85(=W#vh!Q0_dH39V&%5_{b2qiQo7yUlNC+VT zKKrj5!6d`dhsX01c)a_5;u0=)zfVl#v)xQ-3ZLn!B@K^t-O@B3?Y=27e0t|w>8F4T z-Otk+9^WQ-D+^4Vu!@9jVRdIjToU}79FIoj6l3U)zNTBVUh9eBiVrN;TN5J$KYvXL zmCG_M%N0?sYjRCv$^d8%^Qfd?U|KX6l{Ewu-UPD0jGv02Mm~$Mgi(})J2;>`I`|psPgRY|M<5^WB#iG9 zF@hG-QQbYtgBazIyvJD8n0oMU1VJ=O3PI`%!wJG!7>op?GB7-;HmT-*BQppL|H1K) znH$}ccyHpA3ny3gcH53uC##7Ogn}zHeky_*xrnx3f#I+5vvdkXOy1K#DE|(P1y@h` zjqLwXLuJXkVaW+#wMJ&}1SIcEsnUzFtqiZ5#CwV$A&X{%V8(Co1B*pp;xSawlw@U< zBy)u<4}qIVn5BDbSC?TS%A|Jhu4jsd?TC7_={dUPnjY+(f7C%}MN^W)MOnNQD4(+C zu}Bfdr(w4_S*^pcffv<>uY;wm+m2&)VDU^#^sH7q92QSGlwI1NYBGZ8K63gMB&-PA;PfNHknjdx9MoV=C~Zfda,.menu :where(li).disabled>span { cursor: auto; } +.modal { + display: flex; + align-items: flex-end; + justify-content: center; + opacity: 0; + pointer-events: none; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + visibility: hidden; + z-index: 999; + --tw-bg-opacity: 1; + --tw-bg-opacity: 0.4; + background-color: hsla(var(--nf)/var(--tw-bg-opacity,1)); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,transform; + transition-duration: .15s; + transition-duration: .2s; + transition-timing-function: cubic-bezier(.4,0,.2,1); +} +@media (min-width:640px) { + + .modal { + align-items: center; + } + + .modal-box { + max-width: 32rem; + --tw-scale-x: .9; + --tw-scale-y: .9; + --tw-translate-y: 0px; + border-bottom-left-radius: var(--rounded-box,1rem); + border-bottom-right-radius: var(--rounded-box,1rem); + } +} +.modal-open,.modal-toggle:checked+.modal,.modal:target { + opacity: 1; + pointer-events: auto; + visibility: visible; +} +.modal-action { + display: flex; + justify-content: flex-end; + margin-top: 1.5rem; +} .select { -webkit-appearance: none; -moz-appearance: none; @@ -2038,13 +2084,6 @@ html { --tw-text-opacity: 1; color: hsla(var(--s)/var(--tw-text-opacity,1)); } -.btn-outline.btn-accent .badge-outline { - background-color: transparent; - --tw-border-opacity: 1; - border-color: hsla(var(--a)/var(--tw-border-opacity,1)); - --tw-text-opacity: 1; - color: hsla(var(--a)/var(--tw-text-opacity,1)); -} .btn-outline:hover .badge { --tw-bg-opacity: 1; background-color: hsla(var(--b2)/var(--tw-bg-opacity,1)); @@ -2196,20 +2235,6 @@ html { .btn.glass:focus-visible { box-shadow: 0 0 0 2px currentColor; } -.btn-outline { - background-color: transparent; - border-color: currentColor; - --tw-text-opacity: 1; - color: hsla(var(--bc)/var(--tw-text-opacity,1)); -} -.btn-outline:hover { - --tw-bg-opacity: 1; - background-color: hsla(var(--bc)/var(--tw-bg-opacity,1)); - --tw-border-opacity: 1; - border-color: hsla(var(--bc)/var(--tw-border-opacity,1)); - --tw-text-opacity: 1; - color: hsla(var(--b1)/var(--tw-text-opacity,1)); -} .btn-outline.btn-primary { --tw-text-opacity: 1; color: hsla(var(--p)/var(--tw-text-opacity,1)); @@ -2234,42 +2259,6 @@ html { --tw-text-opacity: 1; color: hsla(var(--sc)/var(--tw-text-opacity,1)); } -.btn-outline.btn-accent { - --tw-text-opacity: 1; - color: hsla(var(--a)/var(--tw-text-opacity,1)); -} -.btn-outline.btn-accent:hover { - --tw-bg-opacity: 1; - background-color: hsla(var(--af)/var(--tw-bg-opacity,1)); - --tw-border-opacity: 1; - border-color: hsla(var(--af)/var(--tw-border-opacity,1)); - --tw-text-opacity: 1; - color: hsla(var(--ac)/var(--tw-text-opacity,1)); -} -.btn-outline.btn-success { - --tw-text-opacity: 1; - color: hsla(var(--su)/var(--tw-text-opacity,1)); -} -.btn-outline.btn-success:hover { - --tw-bg-opacity: 1; - background-color: hsla(var(--su)/var(--tw-bg-opacity,1)); - --tw-border-opacity: 1; - border-color: hsla(var(--su)/var(--tw-border-opacity,1)); - --tw-text-opacity: 1; - color: hsla(var(--nc)/var(--tw-text-opacity,1)); -} -.btn-outline.btn-info { - --tw-text-opacity: 1; - color: hsla(var(--in)/var(--tw-text-opacity,1)); -} -.btn-outline.btn-info:hover { - --tw-bg-opacity: 1; - background-color: hsla(var(--in)/var(--tw-bg-opacity,1)); - --tw-border-opacity: 1; - border-color: hsla(var(--in)/var(--tw-border-opacity,1)); - --tw-text-opacity: 1; - color: hsla(var(--nc)/var(--tw-text-opacity,1)); -} .btn-outline.btn-warning { --tw-text-opacity: 1; color: hsla(var(--wa)/var(--tw-text-opacity,1)); @@ -2401,6 +2390,27 @@ html { animation: checkmark var(--animation-input,.2s) ease-in-out; background-image: linear-gradient(-45deg,transparent 65%,hsl(var(--chkbg)) 0),linear-gradient(45deg,transparent 75%,hsl(var(--chkbg)) 0),linear-gradient(-45deg,hsl(var(--chkbg)) 40%,transparent 0),linear-gradient(45deg,hsl(var(--chkbg)) 30%,hsl(var(--chkfg)) 0,hsl(var(--chkfg)) 40%,transparent 0),linear-gradient(-45deg,hsl(var(--chkfg)) 50%,hsl(var(--chkbg)) 0); } +.checkbox-primary { + --chkbg: var(--p); + --chkfg: var(--pc); + --tw-border-opacity: 1; + border-color: hsla(var(--p)/var(--tw-border-opacity,1)); +} +.checkbox-primary:hover { + --tw-border-opacity: 1; + border-color: hsla(var(--p)/var(--tw-border-opacity,1)); +} +.checkbox-primary:focus-visible { + box-shadow: 0 0 0 2px hsl(var(--b1)),0 0 0 4px hsl(var(--p)); +} +.checkbox-primary:checked { + --tw-bg-opacity: 1; + background-color: hsla(var(--p)/var(--tw-bg-opacity,1)); + --tw-border-opacity: 1; + border-color: hsla(var(--p)/var(--tw-border-opacity,1)); + --tw-text-opacity: 1; + color: hsla(var(--pc)/var(--tw-text-opacity,1)); +} .checkbox:disabled { --tw-bg-opacity: 1; background-color: hsla(var(--bc)/var(--tw-bg-opacity,1)); @@ -2584,6 +2594,38 @@ html { --tw-text-opacity: 0.4; color: hsla(var(--bc)/var(--tw-text-opacity,1)); } +.modal-box { + --tw-bg-opacity: 1; + background-color: hsla(var(--b1)/var(--tw-bg-opacity,1)); + padding: 1.5rem; + width: 100%; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-translate-y: 2.5rem; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); + transition-property: background-color,border-color,color,fill,stroke,opacity,box-shadow,transform; + transition-duration: .15s; + transition-duration: .2s; + transition-timing-function: cubic-bezier(.4,0,.2,1); + border-top-left-radius: var(--rounded-box,1rem); + border-top-right-radius: var(--rounded-box,1rem); + box-shadow: 0 25px 50px -12px rgba(0,0,0,.25); +} +.modal-open .modal-box,.modal-toggle:checked+.modal .modal-box,.modal:target .modal-box { + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-translate-y: 0px; +} +.modal-action>:not([hidden])~:not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem*var(--tw-space-x-reverse)); + margin-left: calc(0.5rem*(1 - var(--tw-space-x-reverse))); +} @-webkit-keyframes radiomark { 0% { @@ -2739,24 +2781,6 @@ html { border-color: transparent; cursor: not-allowed; } -.btn-sm { - height: 2rem; - padding-left: .75rem; - padding-right: .75rem; - min-height: 2rem; - font-size: .875rem; -} -.btn-square.btn-sm { - height: 2rem; - padding: 0; - width: 2rem; -} -.btn-circle.btn-sm { - border-radius: 9999px; - height: 2rem; - padding: 0; - width: 2rem; -} .badge-primary { --tw-bg-opacity: 1; background-color: hsla(var(--p)/var(--tw-bg-opacity,1)); @@ -2793,9 +2817,6 @@ html { --tw-text-opacity: 1; color: hsla(var(--a)/var(--tw-text-opacity,1)); } -.invisible { - visibility: hidden; -} .fixed { position: fixed; } @@ -3043,9 +3064,6 @@ html { .justify-between { justify-content: space-between; } -.justify-items-end { - justify-items: end; -} .space-x-8 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(2rem * var(--tw-space-x-reverse)); @@ -3061,6 +3079,21 @@ html { margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)); } +.space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); +} +.space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); +} +.space-x-0 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0px * var(--tw-space-x-reverse)); + margin-left: calc(0px * calc(1 - var(--tw-space-x-reverse))); +} .overflow-hidden { overflow: hidden; } @@ -3198,6 +3231,10 @@ html { padding-top: 3rem; padding-bottom: 3rem; } +.py-8 { + padding-top: 2rem; + padding-bottom: 2rem; +} .pt-8 { padding-top: 2rem; } @@ -3219,15 +3256,15 @@ html { .pt-6 { padding-top: 1.5rem; } +.pb-8 { + padding-bottom: 2rem; +} .text-left { text-align: left; } .text-center { text-align: center; } -.text-right { - text-align: right; -} .font-sans { font-family: Nunito, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; } @@ -3606,10 +3643,6 @@ html { } @media (min-width: 768px) { - .md\:visible { - visibility: visible; - } - .md\:w-1\/3 { width: 33.333333%; } @@ -3618,6 +3651,10 @@ html { width: 66.666667%; } + .md\:w-1\/4 { + width: 25%; + } + .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } @@ -3632,6 +3669,18 @@ html { margin-bottom: calc(0px * var(--tw-space-y-reverse)); } + .md\:space-x-0 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0px * var(--tw-space-x-reverse)); + margin-left: calc(0px * calc(1 - var(--tw-space-x-reverse))); + } + + .md\:space-x-4 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(1rem * var(--tw-space-x-reverse)); + margin-left: calc(1rem * calc(1 - var(--tw-space-x-reverse))); + } + .md\:border-t-0 { border-top-width: 0px; } diff --git a/public/js/app.js b/public/js/app.js index f3f6548..f6b8c75 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -3534,6 +3534,206 @@ function Category(props) { /***/ }), +/***/ "./resources/js/Pages/ModalClosing.js": +/*!********************************************!*\ + !*** ./resources/js/Pages/ModalClosing.js ***! + \********************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (/* binding */ ModalClosing) +/* harmony export */ }); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); +/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js"); + + + +function ModalClosing() { + return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("div", { + id: "my-modal", + className: "modal", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)("div", { + className: "modal-box", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("h1", { + className: "font-bold text-2xl pb-8", + children: "Form Closing" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("div", { + className: "form-control py-4 px-6", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)("label", { + className: "cursor-pointer label", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("span", { + className: "label-text", + children: "Roll forward Budget per Category" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("input", { + type: "checkbox", + checked: "checked", + className: "checkbox", + value: "", + onChange: function onChange() {} + })] + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)("div", { + className: "modal-action", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("a", { + href: "#", + className: "btn btn-primary", + children: "Download" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)("a", { + href: "#", + className: "btn", + children: "Close" + })] + })] + }) + }); +} + +/***/ }), + +/***/ "./resources/js/Pages/Summary.js": +/*!***************************************!*\ + !*** ./resources/js/Pages/Summary.js ***! + \***************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ "default": () => (/* binding */ Summary) +/* harmony export */ }); +/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); +/* harmony import */ var _Components_Pagination__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/Components/Pagination */ "./resources/js/Components/Pagination.js"); +/* harmony import */ var _Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/Layouts/Authenticated */ "./resources/js/Layouts/Authenticated.js"); +/* harmony import */ var _inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @inertiajs/inertia-react */ "./node_modules/@inertiajs/inertia-react/dist/index.js"); +/* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @/utils */ "./resources/js/utils.js"); +/* harmony import */ var _ModalClosing__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./ModalClosing */ "./resources/js/Pages/ModalClosing.js"); +/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js"); + + + + + + + + +function Summary(props) { + var _props$budgets = props.budgets, + budgets = _props$budgets.data, + links = _props$budgets.links; + return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)(_Layouts_Authenticated__WEBPACK_IMPORTED_MODULE_2__["default"], { + errors: props.errors, + header: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("h2", { + className: "font-semibold text-xl text-gray-800 leading-tight", + children: "Summary" + }), + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_inertiajs_inertia_react__WEBPACK_IMPORTED_MODULE_3__.Head, { + title: "Summary" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { + className: "flex flex-col space-x-0 space-y-2 md:space-y-0 md:space-x-4 md:flex-row pt-6 px-6", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card bg-white w-full md:w-1/4", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card-body", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("h1", { + className: "font-bold text-xl", + children: ["Total Income : ", (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(props.income)] + }) + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card bg-white w-full md:w-1/4", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card-body", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("h1", { + className: "font-bold text-xl", + children: ["Total Expense : ", (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(props.expense)] + }) + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card bg-white w-full md:w-1/4", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card-body", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("h1", { + className: "font-bold text-xl", + children: ["Balance : ", (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(props.balance)] + }) + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card bg-white w-full md:w-1/4", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card-body", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("a", { + href: "#my-modal", + className: "btn btn-primary", + children: "Form Closing" + }) + }) + })] + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "flex flex-col space-y-2 md:space-y-0 md:flex-row py-6", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "w-full px-6 md:pr-8", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "card bg-white", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("div", { + className: "card-body", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("div", { + className: "overflow-x-auto", + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("table", { + className: "table w-full table-zebra", + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("thead", { + children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("tr", { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", {}), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: "Category" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: "Description" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: "Budget" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: "Previous Budget" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: "Total Expense/month" + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: "Remain per Category" + })] + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("tbody", { + children: budgets === null || budgets === void 0 ? void 0 : budgets.map(function (budget) { + var _budget$category, _budget$category2; + + return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsxs)("tr", { + children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("th", { + children: budget.id + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("td", { + children: budget === null || budget === void 0 ? void 0 : (_budget$category = budget.category) === null || _budget$category === void 0 ? void 0 : _budget$category.name + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("td", { + children: budget === null || budget === void 0 ? void 0 : (_budget$category2 = budget.category) === null || _budget$category2 === void 0 ? void 0 : _budget$category2.description + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("td", { + children: (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(budget.budget) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("td", { + children: (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(budget.rollover) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("td", { + children: (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(budget.total_used) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)("td", { + children: (0,_utils__WEBPACK_IMPORTED_MODULE_4__.formatIDR)(budget.remain) + })] + }, budget.id); + }) + })] + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_Components_Pagination__WEBPACK_IMPORTED_MODULE_1__["default"], { + links: links + })] + }) + }) + }) + }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_6__.jsx)(_ModalClosing__WEBPACK_IMPORTED_MODULE_5__["default"], {})] + }); +} + +/***/ }), + /***/ "./resources/js/Pages/Transaction.js": /*!*******************************************!*\ !*** ./resources/js/Pages/Transaction.js ***! @@ -3554,6 +3754,12 @@ __webpack_require__.r(__webpack_exports__); /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var _utils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @/utils */ "./resources/js/utils.js"); /* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! react/jsx-runtime */ "./node_modules/react/jsx-runtime.js"); +function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } + +function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } @@ -3607,11 +3813,20 @@ function Transaction(props) { }; var toggleIncome = function toggleIncome() { - setData('is_income', data.is_income === 0 ? 1 : 0); + setData(_objectSpread(_objectSpread({}, data), {}, { + category_id: '', + is_income: data.is_income === 0 ? 1 : 0 + })); }; var handleSelectedcategory = function handleSelectedcategory(e) { - setData('category_id', e.target.value); + var category = categories.find(function (cat) { + return +cat.id === +e.target.value; + }); + setData(_objectSpread(_objectSpread({}, data), {}, { + description: category.description, + category_id: e.target.value + })); }; var handleChange = function handleChange(e) { @@ -3718,7 +3933,8 @@ function Transaction(props) { children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsx)("input", { type: "checkbox", checked: data.is_income === 1 ? true : false, - onChange: toggleIncome + onChange: toggleIncome, + className: "checkbox checkbox-primary" }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_7__.jsx)("span", { className: "label-text font-bold", children: "Income" @@ -3964,7 +4180,7 @@ var appName = ((_window$document$getE = window.document.getElementsByTagName('ti } }); _inertiajs_progress__WEBPACK_IMPORTED_MODULE_3__.InertiaProgress.init({ - color: '#4B5563' + color: '#570df8' }); /***/ }), @@ -80603,6 +80819,10 @@ var map = { "./Auth/VerifyEmail.js": "./resources/js/Pages/Auth/VerifyEmail.js", "./Category": "./resources/js/Pages/Category.js", "./Category.js": "./resources/js/Pages/Category.js", + "./ModalClosing": "./resources/js/Pages/ModalClosing.js", + "./ModalClosing.js": "./resources/js/Pages/ModalClosing.js", + "./Summary": "./resources/js/Pages/Summary.js", + "./Summary.js": "./resources/js/Pages/Summary.js", "./Transaction": "./resources/js/Pages/Transaction.js", "./Transaction.js": "./resources/js/Pages/Transaction.js" }; diff --git a/resources/js/Pages/ModalClosing.js b/resources/js/Pages/ModalClosing.js new file mode 100644 index 0000000..e471814 --- /dev/null +++ b/resources/js/Pages/ModalClosing.js @@ -0,0 +1,21 @@ +import React from 'react' + +export default function ModalClosing() { + return ( +
+
+

Form Closing

+
+ +
+
+ Download + Close +
+
+
+ ) +} \ No newline at end of file diff --git a/resources/js/Pages/Summary.js b/resources/js/Pages/Summary.js new file mode 100644 index 0000000..787046e --- /dev/null +++ b/resources/js/Pages/Summary.js @@ -0,0 +1,81 @@ +import React from 'react'; +import Pagination from '@/Components/Pagination' +import Authenticated from '@/Layouts/Authenticated'; +import { Head } from '@inertiajs/inertia-react'; +import { formatIDR } from '@/utils'; +import ModalClosing from './ModalClosing'; + +export default function Summary(props) { + const { data: budgets , links } = props.budgets + + return ( + Summary} + > + + +
+
+
+

Total Income : {formatIDR(props.income)}

+
+
+
+
+

Total Expense : {formatIDR(props.expense)}

+
+
+
+
+

Balance : {formatIDR(props.balance)}

+
+
+
+ +
+
+
+ +
+
+
+
+ + + + + + + + + + + + + + {budgets?.map(budget => ( + + + + + + + + + + ))} + +
CategoryDescriptionBudgetPrevious BudgetTotal Expense/monthRemain per Category
{budget.id}{budget?.category?.name}{budget?.category?.description}{formatIDR(budget.budget)}{formatIDR(budget.rollover)}{formatIDR(budget.total_used)}{formatIDR(budget.remain)}
+
+ +
+
+
+
+ +
+ ); +} diff --git a/resources/js/Pages/Transaction.js b/resources/js/Pages/Transaction.js index 5097b25..6d2c56a 100644 --- a/resources/js/Pages/Transaction.js +++ b/resources/js/Pages/Transaction.js @@ -23,11 +23,20 @@ export default function Transaction(props) { } const toggleIncome = () => { - setData('is_income', data.is_income === 0 ? 1 : 0) + setData({ + ...data, + category_id: '', + is_income: data.is_income === 0 ? 1 : 0 + }) } const handleSelectedcategory = (e) => { - setData('category_id', e.target.value) + const category = categories.find(cat => +cat.id === +e.target.value) + setData({ + ...data, + description: category.description, + category_id: e.target.value + }) } const handleChange = (e) => { @@ -118,7 +127,7 @@ export default function Transaction(props) {
diff --git a/resources/js/app.js b/resources/js/app.js index 43bb5be..43be37c 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -16,4 +16,4 @@ createInertiaApp({ }, }); -InertiaProgress.init({ color: '#4B5563' }); +InertiaProgress.init({ color: '#570df8' }); diff --git a/routes/web.php b/routes/web.php index 0e12c90..631c346 100644 --- a/routes/web.php +++ b/routes/web.php @@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Route; use Inertia\Inertia; use App\Http\Controllers\ExpenseController; use App\Http\Controllers\CategoryController; +use App\Http\Controllers\SummaryController; /* |-------------------------------------------------------------------------- @@ -27,8 +28,7 @@ Route::post('/categories', [CategoryController::class, 'store'])->name('categori Route::put('/categories/{category}', [CategoryController::class, 'update'])->name('categories.update'); Route::delete('/categories/{category}', [CategoryController::class, 'destroy'])->name('categories.destroy'); -Route::get('/summary', function () { -})->name('summary'); +Route::get('/summary', SummaryController::class)->name('summary'); // Route::get('/dashboard', function () { // return Inertia::render('Dashboard');