Browse Source

feat: master mutation

Muhammad Iqbal Afandi 3 years ago
parent
commit
3c479013e0
40 changed files with 20226 additions and 233 deletions
  1. 67
    0
      app/Exports/MutationExport.php
  2. 52
    0
      app/Http/Controllers/ReportMutationController.php
  3. 42
    1
      app/Models/Mutation.php
  4. 72
    0
      app/Services/MutationService.php
  5. 1
    1
      composer.json
  6. 7
    7
      composer.lock
  7. 2
    2
      database/migrations/2022_04_23_130216_create_mutations_table.php
  8. 13
    24
      public/js/resources_js_pages_auth_VerifyEmail_vue.js
  9. 9
    0
      public/js/resources_js_pages_expense_Create_vue.js
  10. 22
    24
      public/js/resources_js_pages_expense_Index_vue.js
  11. 9
    0
      public/js/resources_js_pages_expense_Show_vue.js
  12. 9
    0
      public/js/resources_js_pages_home_Index_vue.js
  13. 9
    0
      public/js/resources_js_pages_member_Create_vue.js
  14. 9
    0
      public/js/resources_js_pages_member_Edit_vue.js
  15. 22
    24
      public/js/resources_js_pages_member_Index_vue.js
  16. 81
    0
      public/js/resources_js_pages_mutation_Index_vue.js
  17. 19236
    0
      public/js/resources_js_pages_mutation_Report_vue.js
  18. 81
    0
      public/js/resources_js_pages_mutation_Show_vue.js
  19. 27
    0
      public/js/resources_js_pages_mutation_TableHeader_js.js
  20. 9
    0
      public/js/resources_js_pages_topup_Create_vue.js
  21. 22
    24
      public/js/resources_js_pages_topup_Index_vue.js
  22. 17
    17
      public/js/resources_js_pages_topup_Show_vue.js
  23. 9
    0
      public/js/resources_js_pages_typemember_Create_vue.js
  24. 9
    0
      public/js/resources_js_pages_typemember_Edit_vue.js
  25. 22
    24
      public/js/resources_js_pages_typemember_Index_vue.js
  26. 9
    0
      public/js/resources_js_pages_typevehicle_Create_vue.js
  27. 9
    0
      public/js/resources_js_pages_typevehicle_Edit_vue.js
  28. 22
    24
      public/js/resources_js_pages_typevehicle_Index_vue.js
  29. 9
    0
      public/js/resources_js_pages_user_Create_vue.js
  30. 22
    24
      public/js/resources_js_pages_user_Edit_vue.js
  31. 22
    24
      public/js/resources_js_pages_user_Index_vue.js
  32. 9
    0
      public/js/resources_js_pages_user_Show_vue.js
  33. 17
    1
      public/js/vue.js
  34. 4
    4
      resources/js/components/AppButton.vue
  35. 182
    0
      resources/js/pages/mutation/Report.vue
  36. 5
    0
      resources/js/pages/mutation/TableHeader.js
  37. 1
    7
      resources/js/pages/topup/Show.vue
  38. 8
    1
      resources/js/utils/menu.js
  39. 45
    0
      resources/views/excel/mutation-report.blade.php
  40. 4
    0
      routes/web.php

+ 67
- 0
app/Exports/MutationExport.php View File

@@ -0,0 +1,67 @@
1
+<?php
2
+
3
+namespace App\Exports;
4
+
5
+use App\Models\Mutation;
6
+use Illuminate\Contracts\Support\Responsable;
7
+use Illuminate\Contracts\View\View;
8
+use Illuminate\Http\Request;
9
+use Maatwebsite\Excel\Concerns\Exportable;
10
+use Maatwebsite\Excel\Concerns\FromView;
11
+use Maatwebsite\Excel\Concerns\ShouldAutoSize;
12
+use Maatwebsite\Excel\Concerns\WithStyles;
13
+use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
14
+
15
+class MutationExport implements ShouldAutoSize, Responsable, FromView, WithStyles
16
+{
17
+    use Exportable;
18
+
19
+    private $fileName = 'mutation-report.xls';
20
+
21
+    public function __construct(private Request $request)
22
+    {}
23
+
24
+    public function view(): View
25
+    {
26
+        $mutations = Mutation::filter($this->request->only('startDate', 'endDate'))->get();
27
+        return view('excel.mutation-report', compact('mutations'));
28
+    }
29
+
30
+    public function styles(Worksheet $sheet)
31
+    {
32
+        $lastRow = $sheet->getHighestDataRow();
33
+        $lastSecondRow = $lastRow - 1;
34
+        $lastThirdRow = $lastSecondRow - 1;
35
+        $lastFourRow = $lastThirdRow - 1;
36
+
37
+        return [
38
+            1 => [
39
+                'font' => ['bold' => true, 'size' => 12],
40
+                'alignment' => ['vertical' => 'center', 'horizontal' => 'center'],
41
+            ],
42
+            2 => [
43
+                'font' => ['bold' => true, 'size' => 12],
44
+                'alignment' => ['vertical' => 'center', 'horizontal' => 'center'],
45
+            ],
46
+            4 => [
47
+                'font' => ['bold' => true],
48
+            ],
49
+            $lastRow => [
50
+                'font' => ['bold' => true, 'size' => 12],
51
+                'alignment' => ['horizontal' => 'left'],
52
+            ],
53
+            $lastSecondRow => [
54
+                'font' => ['bold' => true, 'size' => 12],
55
+                'alignment' => ['horizontal' => 'left'],
56
+            ],
57
+            $lastThirdRow => [
58
+                'font' => ['bold' => true, 'size' => 12],
59
+                'alignment' => ['horizontal' => 'left'],
60
+            ],
61
+            $lastFourRow => [
62
+                'font' => ['bold' => true, 'size' => 12],
63
+                'alignment' => ['horizontal' => 'left'],
64
+            ],
65
+        ];
66
+    }
67
+}

+ 52
- 0
app/Http/Controllers/ReportMutationController.php View File

@@ -0,0 +1,52 @@
1
+<?php
2
+
3
+namespace App\Http\Controllers;
4
+
5
+use App\Exports\MutationExport;
6
+use App\Models\Mutation;
7
+use App\Services\MutationService;
8
+use Inertia\Inertia;
9
+
10
+class ReportMutationController extends Controller
11
+{
12
+    /**
13
+     * Display a listing of the resource.
14
+     *
15
+     * @return \Inertia\Response
16
+     */
17
+    public function index()
18
+    {
19
+        $mutations = Mutation::filter(request()->only('startDate', 'endDate'));
20
+
21
+        return inertia('mutation/Report', [
22
+            'filters' => request()->all('startDate', 'endDate', 'outlet'),
23
+            'mutations' => Inertia::lazy(
24
+                fn() => [
25
+                    'totalIncome' => (new MutationService)->totalIncomeAsString($mutations->get()),
26
+                    'totalExpense' => (new MutationService)->totalExpenseAsString($mutations->get()),
27
+                    'totalAmount' => (new MutationService)->totalAmountAsString($mutations->get()),
28
+                    'details' => $mutations
29
+                        ->latest()
30
+                        ->paginate(10)
31
+                        ->withQueryString()
32
+                        ->through(fn($mutation) => [
33
+                            'createdAt' => $mutation->created_at,
34
+                            'amount' => $mutation->amount,
35
+                            'type' => $mutation->type,
36
+                            'transactionOutId' => $mutation->transaction_out,
37
+                            'expenseId' => $mutation->expense_id,
38
+                            'topupId' => $mutation->top_up_id,
39
+                        ]),
40
+                ]
41
+            ),
42
+        ]);
43
+    }
44
+
45
+    /**
46
+     * Export to excel
47
+     */
48
+    public function exportExcel()
49
+    {
50
+        return new MutationExport(request());
51
+    }
52
+}

+ 42
- 1
app/Models/Mutation.php View File

@@ -2,6 +2,9 @@
2 2
 
3 3
 namespace App\Models;
4 4
 
5
+use App\Services\CurrencyFormatService;
6
+use Carbon\Carbon;
7
+use Illuminate\Database\Eloquent\Casts\Attribute;
5 8
 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 9
 use Illuminate\Database\Eloquent\Model;
7 10
 
@@ -12,8 +15,46 @@ class Mutation extends Model
12 15
     protected $fillable = [
13 16
         'type',
14 17
         'amount',
15
-        'transaction_id',
18
+        'transaction_out_id',
16 19
         'expense_id',
17 20
         'topup_id',
18 21
     ];
22
+
23
+    protected function createdAt(): Attribute
24
+    {
25
+        return Attribute::make(
26
+            get:fn($value) => Carbon::parse($value)->translatedFormat('l d/m/Y')
27
+        );
28
+    }
29
+
30
+    protected function amount(): Attribute
31
+    {
32
+        return Attribute::make(
33
+            get:function ($value) {
34
+                if ($this->getRawOriginal('type') == 1) {
35
+                    return (new CurrencyFormatService)->setRupiahFormat($value, true);
36
+                } else {
37
+                    return (new CurrencyFormatService)->setRupiahFormat(-$value, true);
38
+                }
39
+            },
40
+        );
41
+    }
42
+
43
+    protected function type(): Attribute
44
+    {
45
+        return Attribute::make(
46
+            get:fn($value) => $value == 1 ? __('words.income') : __('words.expense')
47
+        );
48
+    }
49
+
50
+    public function scopeFilter($query, array $filters)
51
+    {
52
+        $query->when($filters['startDate'] ?? null, function ($query, $date) {
53
+            $query->whereDate('created_at', '>=', $date);
54
+        })->when($filters['endDate'] ?? null, function ($query, $date) {
55
+            $query->whereDate('created_at', '<=', $date);
56
+        })->when($filters['outlet'] ?? null, function ($query, $outlet) {
57
+            $query->where('outlet_id', $outlet);
58
+        });
59
+    }
19 60
 }

+ 72
- 0
app/Services/MutationService.php View File

@@ -0,0 +1,72 @@
1
+<?php
2
+
3
+namespace App\Services;
4
+
5
+use Illuminate\Database\Eloquent\Collection as EloquentCollection;
6
+use Illuminate\Support\Collection as SupportCollection;
7
+
8
+class MutationService extends CurrencyFormatService
9
+{
10
+    public function totalIncome(EloquentCollection $collections)
11
+    {
12
+        foreach ($collections->chunk(100) as $chunk) {
13
+            return $chunk->sum(function ($collect) {
14
+                if ($collect->getRawOriginal('type') == 1) {
15
+                    return $collect->getRawOriginal('amount');
16
+                }
17
+            });
18
+        }
19
+    }
20
+
21
+    public function totalExpense(EloquentCollection $collections)
22
+    {
23
+        foreach ($collections->chunk(100) as $chunk) {
24
+            return $chunk->sum(function ($collect) {
25
+                if ($collect->getRawOriginal('type') == 2) {
26
+                    return $collect->getRawOriginal('amount');
27
+                }
28
+            });
29
+        }
30
+    }
31
+
32
+    public function totalIncomeAsString(EloquentCollection $collections)
33
+    {
34
+        if ($collections->count()) {
35
+            return $this->setRupiahFormat($this->totalIncome($collections), true);
36
+        } else {
37
+            return $this->setRupiahFormat(0, true);
38
+        }
39
+    }
40
+
41
+    public function totalExpenseAsString(EloquentCollection $collections)
42
+    {
43
+        if ($collections->count()) {
44
+            return $this->setRupiahFormat($this->totalExpense($collections), true);
45
+        } else {
46
+            return $this->setRupiahFormat(0, true);
47
+        }
48
+    }
49
+
50
+    public function totalAmountAsString(EloquentCollection $collections)
51
+    {
52
+        if ($collections->count()) {
53
+            $amount = $this->totalIncome($collections) - $this->totalExpense($collections);
54
+        } else {
55
+            $amount = 0;
56
+        }
57
+
58
+        return $this->setRupiahFormat($amount, true);
59
+    }
60
+
61
+    public function totalPerMonth(EloquentCollection $collections)
62
+    {
63
+        return $collections->transform(fn($collection) => $collection->sum(fn($collect) => $collect->getRawOriginal('amount')));
64
+    }
65
+
66
+    public function statisticData(SupportCollection $collections, int $take = -1)
67
+    {
68
+        $collections = $collections->take($take);
69
+        $collections->transform(fn($collections) => $this->totalPerMonth($collections));
70
+        return $collections;
71
+    }
72
+}

+ 1
- 1
composer.json View File

@@ -15,7 +15,7 @@
15 15
     "laravel/framework": "^9.0",
16 16
     "laravel/sanctum": "^2.14",
17 17
     "laravel/tinker": "^2.7",
18
-    "maatwebsite/excel": "3.1.38",
18
+    "maatwebsite/excel": "^3.1",
19 19
     "psr/simple-cache": "^1.0",
20 20
     "tightenco/ziggy": "^1.4"
21 21
   },

+ 7
- 7
composer.lock View File

@@ -4,7 +4,7 @@
4 4
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
5 5
         "This file is @generated automatically"
6 6
     ],
7
-    "content-hash": "9a2698e624f694cb0e44c83110cbc609",
7
+    "content-hash": "c95b0e2a152a8654b1f0ff918e5d0d09",
8 8
     "packages": [
9 9
         {
10 10
             "name": "asm89/stack-cors",
@@ -1855,16 +1855,16 @@
1855 1855
         },
1856 1856
         {
1857 1857
             "name": "maatwebsite/excel",
1858
-            "version": "3.1.38",
1858
+            "version": "3.1.40",
1859 1859
             "source": {
1860 1860
                 "type": "git",
1861 1861
                 "url": "https://github.com/SpartnerNL/Laravel-Excel.git",
1862
-                "reference": "dff132ce4d30b19863f4e84de1613fca99604992"
1862
+                "reference": "8a54972e3d616c74687c3cbff15765555761885c"
1863 1863
             },
1864 1864
             "dist": {
1865 1865
                 "type": "zip",
1866
-                "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/dff132ce4d30b19863f4e84de1613fca99604992",
1867
-                "reference": "dff132ce4d30b19863f4e84de1613fca99604992",
1866
+                "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/8a54972e3d616c74687c3cbff15765555761885c",
1867
+                "reference": "8a54972e3d616c74687c3cbff15765555761885c",
1868 1868
                 "shasum": ""
1869 1869
             },
1870 1870
             "require": {
@@ -1917,7 +1917,7 @@
1917 1917
             ],
1918 1918
             "support": {
1919 1919
                 "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
1920
-                "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.38"
1920
+                "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.40"
1921 1921
             },
1922 1922
             "funding": [
1923 1923
                 {
@@ -1929,7 +1929,7 @@
1929 1929
                     "type": "github"
1930 1930
                 }
1931 1931
             ],
1932
-            "time": "2022-03-24T16:00:29+00:00"
1932
+            "time": "2022-05-02T13:50:01+00:00"
1933 1933
         },
1934 1934
         {
1935 1935
             "name": "maennchen/zipstream-php",

+ 2
- 2
database/migrations/2022_04_23_130216_create_mutations_table.php View File

@@ -15,9 +15,9 @@ return new class extends Migration
15 15
     {
16 16
         Schema::create('mutations', function (Blueprint $table) {
17 17
             $table->id();
18
-            $table->string('type');
18
+            $table->enum('type', [1, 2]); // 1(income) 2(expense)
19 19
             $table->unsignedInteger('amount');
20
-            $table->foreignId('transaction_out')->nullable()->default(null)->constrained();
20
+            $table->foreignId('transaction_out_id')->nullable()->default(null)->constrained();
21 21
             $table->foreignId('expense_id')->nullable()->default(null)->constrained();
22 22
             $table->foreignId('top_up_id')->nullable()->default(null)->constrained();
23 23
             $table->timestamps();

+ 13
- 24
public/js/resources_js_pages_auth_VerifyEmail_vue.js View File

@@ -143,15 +143,10 @@ var _hoisted_1 = {
143 143
   "class": "p-button-label"
144 144
 };
145 145
 var _hoisted_2 = {
146
-  key: 1
147
-};
148
-var _hoisted_3 = {
149 146
   key: 1,
150 147
   "class": "p-button-label"
151 148
 };
152 149
 function render(_ctx, _cache, $props, $setup, $data, $options) {
153
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
154
-
155 150
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
156 151
     key: 0,
157 152
     "class": "p-button p-component",
@@ -171,25 +166,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
171 166
     _: 1
172 167
     /* STABLE */
173 168
 
174
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
175
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
176
-  }, {
177
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
178
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
179
-        key: 0,
180
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
181
-      }, null, 2
182
-      /* CLASS */
183
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
184
-      /* TEXT */
185
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
186
-    }),
187
-    _: 1
188
-    /* STABLE */
189
-
190
-  }, 8
191
-  /* PROPS */
192
-  , ["class"])]));
169
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
170
+    key: 1,
171
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
172
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
173
+    key: 0,
174
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
175
+  }, null, 2
176
+  /* CLASS */
177
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
178
+  /* TEXT */
179
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
180
+  /* CLASS */
181
+  ));
193 182
 }
194 183
 
195 184
 /***/ }),

+ 9
- 0
public/js/resources_js_pages_expense_Create_vue.js View File

@@ -1387,6 +1387,15 @@ __webpack_require__.r(__webpack_exports__);
1387 1387
       icon: 'pi pi-wallet',
1388 1388
       to: '/expenses',
1389 1389
       component: 'expense/Index'
1390
+    }, {
1391
+      label: 'Laporan',
1392
+      icon: 'pi pi-book',
1393
+      items: [{
1394
+        label: 'Mutasi',
1395
+        icon: 'pi pi-circle',
1396
+        to: '/reports/mutations',
1397
+        component: 'mutation/Report'
1398
+      }]
1390 1399
     }]
1391 1400
   }, {
1392 1401
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_expense_Index_vue.js View File

@@ -532,15 +532,10 @@ var _hoisted_1 = {
532 532
   "class": "p-button-label"
533 533
 };
534 534
 var _hoisted_2 = {
535
-  key: 1
536
-};
537
-var _hoisted_3 = {
538 535
   key: 1,
539 536
   "class": "p-button-label"
540 537
 };
541 538
 function render(_ctx, _cache, $props, $setup, $data, $options) {
542
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
543
-
544 539
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
545 540
     key: 0,
546 541
     "class": "p-button p-component",
@@ -560,25 +555,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
560 555
     _: 1
561 556
     /* STABLE */
562 557
 
563
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
564
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
565
-  }, {
566
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
567
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
568
-        key: 0,
569
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
570
-      }, null, 2
571
-      /* CLASS */
572
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
573
-      /* TEXT */
574
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
575
-    }),
576
-    _: 1
577
-    /* STABLE */
578
-
579
-  }, 8
580
-  /* PROPS */
581
-  , ["class"])]));
558
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
559
+    key: 1,
560
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
561
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
562
+    key: 0,
563
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
564
+  }, null, 2
565
+  /* CLASS */
566
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
567
+  /* TEXT */
568
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
569
+  /* CLASS */
570
+  ));
582 571
 }
583 572
 
584 573
 /***/ }),
@@ -1329,6 +1318,15 @@ __webpack_require__.r(__webpack_exports__);
1329 1318
       icon: 'pi pi-wallet',
1330 1319
       to: '/expenses',
1331 1320
       component: 'expense/Index'
1321
+    }, {
1322
+      label: 'Laporan',
1323
+      icon: 'pi pi-book',
1324
+      items: [{
1325
+        label: 'Mutasi',
1326
+        icon: 'pi pi-circle',
1327
+        to: '/reports/mutations',
1328
+        component: 'mutation/Report'
1329
+      }]
1332 1330
     }]
1333 1331
   }, {
1334 1332
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_expense_Show_vue.js View File

@@ -1052,6 +1052,15 @@ __webpack_require__.r(__webpack_exports__);
1052 1052
       icon: 'pi pi-wallet',
1053 1053
       to: '/expenses',
1054 1054
       component: 'expense/Index'
1055
+    }, {
1056
+      label: 'Laporan',
1057
+      icon: 'pi pi-book',
1058
+      items: [{
1059
+        label: 'Mutasi',
1060
+        icon: 'pi pi-circle',
1061
+        to: '/reports/mutations',
1062
+        component: 'mutation/Report'
1063
+      }]
1055 1064
     }]
1056 1065
   }, {
1057 1066
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_home_Index_vue.js View File

@@ -926,6 +926,15 @@ __webpack_require__.r(__webpack_exports__);
926 926
       icon: 'pi pi-wallet',
927 927
       to: '/expenses',
928 928
       component: 'expense/Index'
929
+    }, {
930
+      label: 'Laporan',
931
+      icon: 'pi pi-book',
932
+      items: [{
933
+        label: 'Mutasi',
934
+        icon: 'pi pi-circle',
935
+        to: '/reports/mutations',
936
+        component: 'mutation/Report'
937
+      }]
929 938
     }]
930 939
   }, {
931 940
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_member_Create_vue.js View File

@@ -1711,6 +1711,15 @@ __webpack_require__.r(__webpack_exports__);
1711 1711
       icon: 'pi pi-wallet',
1712 1712
       to: '/expenses',
1713 1713
       component: 'expense/Index'
1714
+    }, {
1715
+      label: 'Laporan',
1716
+      icon: 'pi pi-book',
1717
+      items: [{
1718
+        label: 'Mutasi',
1719
+        icon: 'pi pi-circle',
1720
+        to: '/reports/mutations',
1721
+        component: 'mutation/Report'
1722
+      }]
1714 1723
     }]
1715 1724
   }, {
1716 1725
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_member_Edit_vue.js View File

@@ -1802,6 +1802,15 @@ __webpack_require__.r(__webpack_exports__);
1802 1802
       icon: 'pi pi-wallet',
1803 1803
       to: '/expenses',
1804 1804
       component: 'expense/Index'
1805
+    }, {
1806
+      label: 'Laporan',
1807
+      icon: 'pi pi-book',
1808
+      items: [{
1809
+        label: 'Mutasi',
1810
+        icon: 'pi pi-circle',
1811
+        to: '/reports/mutations',
1812
+        component: 'mutation/Report'
1813
+      }]
1805 1814
     }]
1806 1815
   }, {
1807 1816
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_member_Index_vue.js View File

@@ -500,15 +500,10 @@ var _hoisted_1 = {
500 500
   "class": "p-button-label"
501 501
 };
502 502
 var _hoisted_2 = {
503
-  key: 1
504
-};
505
-var _hoisted_3 = {
506 503
   key: 1,
507 504
   "class": "p-button-label"
508 505
 };
509 506
 function render(_ctx, _cache, $props, $setup, $data, $options) {
510
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
511
-
512 507
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
513 508
     key: 0,
514 509
     "class": "p-button p-component",
@@ -528,25 +523,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
528 523
     _: 1
529 524
     /* STABLE */
530 525
 
531
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
532
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
533
-  }, {
534
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
535
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
536
-        key: 0,
537
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
538
-      }, null, 2
539
-      /* CLASS */
540
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
541
-      /* TEXT */
542
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
543
-    }),
544
-    _: 1
545
-    /* STABLE */
546
-
547
-  }, 8
548
-  /* PROPS */
549
-  , ["class"])]));
526
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
527
+    key: 1,
528
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
529
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
530
+    key: 0,
531
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
532
+  }, null, 2
533
+  /* CLASS */
534
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
535
+  /* TEXT */
536
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
537
+  /* CLASS */
538
+  ));
550 539
 }
551 540
 
552 541
 /***/ }),
@@ -1302,6 +1291,15 @@ __webpack_require__.r(__webpack_exports__);
1302 1291
       icon: 'pi pi-wallet',
1303 1292
       to: '/expenses',
1304 1293
       component: 'expense/Index'
1294
+    }, {
1295
+      label: 'Laporan',
1296
+      icon: 'pi pi-book',
1297
+      items: [{
1298
+        label: 'Mutasi',
1299
+        icon: 'pi pi-circle',
1300
+        to: '/reports/mutations',
1301
+        component: 'mutation/Report'
1302
+      }]
1305 1303
     }]
1306 1304
   }, {
1307 1305
     label: 'Master',

+ 81
- 0
public/js/resources_js_pages_mutation_Index_vue.js View File

@@ -0,0 +1,81 @@
1
+"use strict";
2
+(self["webpackChunk"] = self["webpackChunk"] || []).push([["resources_js_pages_mutation_Index_vue"],{
3
+
4
+/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/pages/mutation/Index.vue?vue&type=template&id=38c13d75":
5
+/*!*******************************************************************************************************************************************************************************************************************************************************************************!*\
6
+  !*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/pages/mutation/Index.vue?vue&type=template&id=38c13d75 ***!
7
+  \*******************************************************************************************************************************************************************************************************************************************************************************/
8
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9
+
10
+__webpack_require__.r(__webpack_exports__);
11
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
12
+/* harmony export */   "render": () => (/* binding */ render)
13
+/* harmony export */ });
14
+function render(_ctx, _cache) {
15
+  return null;
16
+}
17
+
18
+/***/ }),
19
+
20
+/***/ "./node_modules/vue-loader/dist/exportHelper.js":
21
+/*!******************************************************!*\
22
+  !*** ./node_modules/vue-loader/dist/exportHelper.js ***!
23
+  \******************************************************/
24
+/***/ ((__unused_webpack_module, exports) => {
25
+
26
+
27
+Object.defineProperty(exports, "__esModule", ({ value: true }));
28
+// runtime helper for setting properties on components
29
+// in a tree-shakable way
30
+exports["default"] = (sfc, props) => {
31
+    const target = sfc.__vccOpts || sfc;
32
+    for (const [key, val] of props) {
33
+        target[key] = val;
34
+    }
35
+    return target;
36
+};
37
+
38
+
39
+/***/ }),
40
+
41
+/***/ "./resources/js/pages/mutation/Index.vue":
42
+/*!***********************************************!*\
43
+  !*** ./resources/js/pages/mutation/Index.vue ***!
44
+  \***********************************************/
45
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
46
+
47
+__webpack_require__.r(__webpack_exports__);
48
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
49
+/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
50
+/* harmony export */ });
51
+/* harmony import */ var _Index_vue_vue_type_template_id_38c13d75__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Index.vue?vue&type=template&id=38c13d75 */ "./resources/js/pages/mutation/Index.vue?vue&type=template&id=38c13d75");
52
+/* harmony import */ var _home_dijitalcode_Projects_parkirin_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./node_modules/vue-loader/dist/exportHelper.js */ "./node_modules/vue-loader/dist/exportHelper.js");
53
+
54
+const script = {}
55
+
56
+;
57
+const __exports__ = /*#__PURE__*/(0,_home_dijitalcode_Projects_parkirin_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_1__["default"])(script, [['render',_Index_vue_vue_type_template_id_38c13d75__WEBPACK_IMPORTED_MODULE_0__.render],['__file',"resources/js/pages/mutation/Index.vue"]])
58
+/* hot reload */
59
+if (false) {}
60
+
61
+
62
+/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (__exports__);
63
+
64
+/***/ }),
65
+
66
+/***/ "./resources/js/pages/mutation/Index.vue?vue&type=template&id=38c13d75":
67
+/*!*****************************************************************************!*\
68
+  !*** ./resources/js/pages/mutation/Index.vue?vue&type=template&id=38c13d75 ***!
69
+  \*****************************************************************************/
70
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
71
+
72
+__webpack_require__.r(__webpack_exports__);
73
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
74
+/* harmony export */   "render": () => (/* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_5_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_Index_vue_vue_type_template_id_38c13d75__WEBPACK_IMPORTED_MODULE_0__.render)
75
+/* harmony export */ });
76
+/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_5_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_Index_vue_vue_type_template_id_38c13d75__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!../../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!../../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./Index.vue?vue&type=template&id=38c13d75 */ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/pages/mutation/Index.vue?vue&type=template&id=38c13d75");
77
+
78
+
79
+/***/ })
80
+
81
+}]);

+ 19236
- 0
public/js/resources_js_pages_mutation_Report_vue.js
File diff suppressed because it is too large
View File


+ 81
- 0
public/js/resources_js_pages_mutation_Show_vue.js View File

@@ -0,0 +1,81 @@
1
+"use strict";
2
+(self["webpackChunk"] = self["webpackChunk"] || []).push([["resources_js_pages_mutation_Show_vue"],{
3
+
4
+/***/ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/pages/mutation/Show.vue?vue&type=template&id=00b8c2ac":
5
+/*!******************************************************************************************************************************************************************************************************************************************************************************!*\
6
+  !*** ./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/pages/mutation/Show.vue?vue&type=template&id=00b8c2ac ***!
7
+  \******************************************************************************************************************************************************************************************************************************************************************************/
8
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9
+
10
+__webpack_require__.r(__webpack_exports__);
11
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
12
+/* harmony export */   "render": () => (/* binding */ render)
13
+/* harmony export */ });
14
+function render(_ctx, _cache) {
15
+  return null;
16
+}
17
+
18
+/***/ }),
19
+
20
+/***/ "./node_modules/vue-loader/dist/exportHelper.js":
21
+/*!******************************************************!*\
22
+  !*** ./node_modules/vue-loader/dist/exportHelper.js ***!
23
+  \******************************************************/
24
+/***/ ((__unused_webpack_module, exports) => {
25
+
26
+
27
+Object.defineProperty(exports, "__esModule", ({ value: true }));
28
+// runtime helper for setting properties on components
29
+// in a tree-shakable way
30
+exports["default"] = (sfc, props) => {
31
+    const target = sfc.__vccOpts || sfc;
32
+    for (const [key, val] of props) {
33
+        target[key] = val;
34
+    }
35
+    return target;
36
+};
37
+
38
+
39
+/***/ }),
40
+
41
+/***/ "./resources/js/pages/mutation/Show.vue":
42
+/*!**********************************************!*\
43
+  !*** ./resources/js/pages/mutation/Show.vue ***!
44
+  \**********************************************/
45
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
46
+
47
+__webpack_require__.r(__webpack_exports__);
48
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
49
+/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
50
+/* harmony export */ });
51
+/* harmony import */ var _Show_vue_vue_type_template_id_00b8c2ac__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Show.vue?vue&type=template&id=00b8c2ac */ "./resources/js/pages/mutation/Show.vue?vue&type=template&id=00b8c2ac");
52
+/* harmony import */ var _home_dijitalcode_Projects_parkirin_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./node_modules/vue-loader/dist/exportHelper.js */ "./node_modules/vue-loader/dist/exportHelper.js");
53
+
54
+const script = {}
55
+
56
+;
57
+const __exports__ = /*#__PURE__*/(0,_home_dijitalcode_Projects_parkirin_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_1__["default"])(script, [['render',_Show_vue_vue_type_template_id_00b8c2ac__WEBPACK_IMPORTED_MODULE_0__.render],['__file',"resources/js/pages/mutation/Show.vue"]])
58
+/* hot reload */
59
+if (false) {}
60
+
61
+
62
+/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (__exports__);
63
+
64
+/***/ }),
65
+
66
+/***/ "./resources/js/pages/mutation/Show.vue?vue&type=template&id=00b8c2ac":
67
+/*!****************************************************************************!*\
68
+  !*** ./resources/js/pages/mutation/Show.vue?vue&type=template&id=00b8c2ac ***!
69
+  \****************************************************************************/
70
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
71
+
72
+__webpack_require__.r(__webpack_exports__);
73
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
74
+/* harmony export */   "render": () => (/* reexport safe */ _node_modules_babel_loader_lib_index_js_clonedRuleSet_5_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_Show_vue_vue_type_template_id_00b8c2ac__WEBPACK_IMPORTED_MODULE_0__.render)
75
+/* harmony export */ });
76
+/* harmony import */ var _node_modules_babel_loader_lib_index_js_clonedRuleSet_5_use_0_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_2_node_modules_vue_loader_dist_index_js_ruleSet_0_use_0_Show_vue_vue_type_template_id_00b8c2ac__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!../../../../node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!../../../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./Show.vue?vue&type=template&id=00b8c2ac */ "./node_modules/babel-loader/lib/index.js??clonedRuleSet-5.use[0]!./node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[2]!./node_modules/vue-loader/dist/index.js??ruleSet[0].use[0]!./resources/js/pages/mutation/Show.vue?vue&type=template&id=00b8c2ac");
77
+
78
+
79
+/***/ })
80
+
81
+}]);

+ 27
- 0
public/js/resources_js_pages_mutation_TableHeader_js.js View File

@@ -0,0 +1,27 @@
1
+"use strict";
2
+(self["webpackChunk"] = self["webpackChunk"] || []).push([["resources_js_pages_mutation_TableHeader_js"],{
3
+
4
+/***/ "./resources/js/pages/mutation/TableHeader.js":
5
+/*!****************************************************!*\
6
+  !*** ./resources/js/pages/mutation/TableHeader.js ***!
7
+  \****************************************************/
8
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
9
+
10
+__webpack_require__.r(__webpack_exports__);
11
+/* harmony export */ __webpack_require__.d(__webpack_exports__, {
12
+/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
13
+/* harmony export */ });
14
+/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ([{
15
+  field: 'createdAt',
16
+  header: 'Tanggal'
17
+}, {
18
+  field: 'type',
19
+  header: 'Tipe'
20
+}, {
21
+  field: 'amount',
22
+  header: 'Nilai'
23
+}]);
24
+
25
+/***/ })
26
+
27
+}]);

+ 9
- 0
public/js/resources_js_pages_topup_Create_vue.js View File

@@ -1406,6 +1406,15 @@ __webpack_require__.r(__webpack_exports__);
1406 1406
       icon: 'pi pi-wallet',
1407 1407
       to: '/expenses',
1408 1408
       component: 'expense/Index'
1409
+    }, {
1410
+      label: 'Laporan',
1411
+      icon: 'pi pi-book',
1412
+      items: [{
1413
+        label: 'Mutasi',
1414
+        icon: 'pi pi-circle',
1415
+        to: '/reports/mutations',
1416
+        component: 'mutation/Report'
1417
+      }]
1409 1418
     }]
1410 1419
   }, {
1411 1420
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_topup_Index_vue.js View File

@@ -534,15 +534,10 @@ var _hoisted_1 = {
534 534
   "class": "p-button-label"
535 535
 };
536 536
 var _hoisted_2 = {
537
-  key: 1
538
-};
539
-var _hoisted_3 = {
540 537
   key: 1,
541 538
   "class": "p-button-label"
542 539
 };
543 540
 function render(_ctx, _cache, $props, $setup, $data, $options) {
544
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
545
-
546 541
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
547 542
     key: 0,
548 543
     "class": "p-button p-component",
@@ -562,25 +557,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
562 557
     _: 1
563 558
     /* STABLE */
564 559
 
565
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
566
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
567
-  }, {
568
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
569
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
570
-        key: 0,
571
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
572
-      }, null, 2
573
-      /* CLASS */
574
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
575
-      /* TEXT */
576
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
577
-    }),
578
-    _: 1
579
-    /* STABLE */
580
-
581
-  }, 8
582
-  /* PROPS */
583
-  , ["class"])]));
560
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
561
+    key: 1,
562
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
563
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
564
+    key: 0,
565
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
566
+  }, null, 2
567
+  /* CLASS */
568
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
569
+  /* TEXT */
570
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
571
+  /* CLASS */
572
+  ));
584 573
 }
585 574
 
586 575
 /***/ }),
@@ -1398,6 +1387,15 @@ __webpack_require__.r(__webpack_exports__);
1398 1387
       icon: 'pi pi-wallet',
1399 1388
       to: '/expenses',
1400 1389
       component: 'expense/Index'
1390
+    }, {
1391
+      label: 'Laporan',
1392
+      icon: 'pi pi-book',
1393
+      items: [{
1394
+        label: 'Mutasi',
1395
+        icon: 'pi pi-circle',
1396
+        to: '/reports/mutations',
1397
+        component: 'mutation/Report'
1398
+      }]
1401 1399
     }]
1402 1400
   }, {
1403 1401
     label: 'Master',

+ 17
- 17
public/js/resources_js_pages_topup_Show_vue.js View File

@@ -374,12 +374,10 @@ __webpack_require__.r(__webpack_exports__);
374 374
 /* harmony export */ __webpack_require__.d(__webpack_exports__, {
375 375
 /* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
376 376
 /* harmony export */ });
377
-/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "./node_modules/vue/dist/vue.esm-bundler.js");
378
-/* harmony import */ var _inertiajs_inertia_vue3__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @inertiajs/inertia-vue3 */ "./node_modules/@inertiajs/inertia-vue3/dist/index.js");
379
-/* harmony import */ var _components_AppPagination_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/components/AppPagination.vue */ "./resources/js/components/AppPagination.vue");
380
-/* harmony import */ var _layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @/layouts/AppLayout.vue */ "./resources/js/layouts/AppLayout.vue");
381
-/* harmony import */ var _TableHeader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./TableHeader */ "./resources/js/pages/topup/TableHeader.js");
382
-
377
+/* harmony import */ var _inertiajs_inertia_vue3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @inertiajs/inertia-vue3 */ "./node_modules/@inertiajs/inertia-vue3/dist/index.js");
378
+/* harmony import */ var _components_AppPagination_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @/components/AppPagination.vue */ "./resources/js/components/AppPagination.vue");
379
+/* harmony import */ var _layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @/layouts/AppLayout.vue */ "./resources/js/layouts/AppLayout.vue");
380
+/* harmony import */ var _TableHeader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./TableHeader */ "./resources/js/pages/topup/TableHeader.js");
383 381
 
384 382
 
385 383
 
@@ -392,18 +390,11 @@ __webpack_require__.r(__webpack_exports__);
392 390
   setup: function setup(__props, _ref) {
393 391
     var expose = _ref.expose;
394 392
     expose();
395
-    var props = __props;
396
-    (0,vue__WEBPACK_IMPORTED_MODULE_0__.onMounted)(function () {
397
-      console.info(props.member);
398
-      console.table(props.topUp);
399
-    });
400 393
     var __returned__ = {
401
-      props: props,
402
-      onMounted: vue__WEBPACK_IMPORTED_MODULE_0__.onMounted,
403
-      Head: _inertiajs_inertia_vue3__WEBPACK_IMPORTED_MODULE_1__.Head,
404
-      AppPagination: _components_AppPagination_vue__WEBPACK_IMPORTED_MODULE_2__["default"],
405
-      AppLayout: _layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_3__["default"],
406
-      TopUpsTable: _TableHeader__WEBPACK_IMPORTED_MODULE_4__.TopUpsTable
394
+      Head: _inertiajs_inertia_vue3__WEBPACK_IMPORTED_MODULE_0__.Head,
395
+      AppPagination: _components_AppPagination_vue__WEBPACK_IMPORTED_MODULE_1__["default"],
396
+      AppLayout: _layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_2__["default"],
397
+      TopUpsTable: _TableHeader__WEBPACK_IMPORTED_MODULE_3__.TopUpsTable
407 398
     };
408 399
     Object.defineProperty(__returned__, '__isScriptSetup', {
409 400
       enumerable: false,
@@ -1174,6 +1165,15 @@ __webpack_require__.r(__webpack_exports__);
1174 1165
       icon: 'pi pi-wallet',
1175 1166
       to: '/expenses',
1176 1167
       component: 'expense/Index'
1168
+    }, {
1169
+      label: 'Laporan',
1170
+      icon: 'pi pi-book',
1171
+      items: [{
1172
+        label: 'Mutasi',
1173
+        icon: 'pi pi-circle',
1174
+        to: '/reports/mutations',
1175
+        component: 'mutation/Report'
1176
+      }]
1177 1177
     }]
1178 1178
   }, {
1179 1179
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_typemember_Create_vue.js View File

@@ -1875,6 +1875,15 @@ __webpack_require__.r(__webpack_exports__);
1875 1875
       icon: 'pi pi-wallet',
1876 1876
       to: '/expenses',
1877 1877
       component: 'expense/Index'
1878
+    }, {
1879
+      label: 'Laporan',
1880
+      icon: 'pi pi-book',
1881
+      items: [{
1882
+        label: 'Mutasi',
1883
+        icon: 'pi pi-circle',
1884
+        to: '/reports/mutations',
1885
+        component: 'mutation/Report'
1886
+      }]
1878 1887
     }]
1879 1888
   }, {
1880 1889
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_typemember_Edit_vue.js View File

@@ -2050,6 +2050,15 @@ __webpack_require__.r(__webpack_exports__);
2050 2050
       icon: 'pi pi-wallet',
2051 2051
       to: '/expenses',
2052 2052
       component: 'expense/Index'
2053
+    }, {
2054
+      label: 'Laporan',
2055
+      icon: 'pi pi-book',
2056
+      items: [{
2057
+        label: 'Mutasi',
2058
+        icon: 'pi pi-circle',
2059
+        to: '/reports/mutations',
2060
+        component: 'mutation/Report'
2061
+      }]
2053 2062
     }]
2054 2063
   }, {
2055 2064
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_typemember_Index_vue.js View File

@@ -428,15 +428,10 @@ var _hoisted_1 = {
428 428
   "class": "p-button-label"
429 429
 };
430 430
 var _hoisted_2 = {
431
-  key: 1
432
-};
433
-var _hoisted_3 = {
434 431
   key: 1,
435 432
   "class": "p-button-label"
436 433
 };
437 434
 function render(_ctx, _cache, $props, $setup, $data, $options) {
438
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
439
-
440 435
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
441 436
     key: 0,
442 437
     "class": "p-button p-component",
@@ -456,25 +451,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
456 451
     _: 1
457 452
     /* STABLE */
458 453
 
459
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
460
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
461
-  }, {
462
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
463
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
464
-        key: 0,
465
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
466
-      }, null, 2
467
-      /* CLASS */
468
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
469
-      /* TEXT */
470
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
471
-    }),
472
-    _: 1
473
-    /* STABLE */
474
-
475
-  }, 8
476
-  /* PROPS */
477
-  , ["class"])]));
454
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
455
+    key: 1,
456
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
457
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
458
+    key: 0,
459
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
460
+  }, null, 2
461
+  /* CLASS */
462
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
463
+  /* TEXT */
464
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
465
+  /* CLASS */
466
+  ));
478 467
 }
479 468
 
480 469
 /***/ }),
@@ -1147,6 +1136,15 @@ __webpack_require__.r(__webpack_exports__);
1147 1136
       icon: 'pi pi-wallet',
1148 1137
       to: '/expenses',
1149 1138
       component: 'expense/Index'
1139
+    }, {
1140
+      label: 'Laporan',
1141
+      icon: 'pi pi-book',
1142
+      items: [{
1143
+        label: 'Mutasi',
1144
+        icon: 'pi pi-circle',
1145
+        to: '/reports/mutations',
1146
+        component: 'mutation/Report'
1147
+      }]
1150 1148
     }]
1151 1149
   }, {
1152 1150
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_typevehicle_Create_vue.js View File

@@ -1131,6 +1131,15 @@ __webpack_require__.r(__webpack_exports__);
1131 1131
       icon: 'pi pi-wallet',
1132 1132
       to: '/expenses',
1133 1133
       component: 'expense/Index'
1134
+    }, {
1135
+      label: 'Laporan',
1136
+      icon: 'pi pi-book',
1137
+      items: [{
1138
+        label: 'Mutasi',
1139
+        icon: 'pi pi-circle',
1140
+        to: '/reports/mutations',
1141
+        component: 'mutation/Report'
1142
+      }]
1134 1143
     }]
1135 1144
   }, {
1136 1145
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_typevehicle_Edit_vue.js View File

@@ -1301,6 +1301,15 @@ __webpack_require__.r(__webpack_exports__);
1301 1301
       icon: 'pi pi-wallet',
1302 1302
       to: '/expenses',
1303 1303
       component: 'expense/Index'
1304
+    }, {
1305
+      label: 'Laporan',
1306
+      icon: 'pi pi-book',
1307
+      items: [{
1308
+        label: 'Mutasi',
1309
+        icon: 'pi pi-circle',
1310
+        to: '/reports/mutations',
1311
+        component: 'mutation/Report'
1312
+      }]
1304 1313
     }]
1305 1314
   }, {
1306 1315
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_typevehicle_Index_vue.js View File

@@ -463,15 +463,10 @@ var _hoisted_1 = {
463 463
   "class": "p-button-label"
464 464
 };
465 465
 var _hoisted_2 = {
466
-  key: 1
467
-};
468
-var _hoisted_3 = {
469 466
   key: 1,
470 467
   "class": "p-button-label"
471 468
 };
472 469
 function render(_ctx, _cache, $props, $setup, $data, $options) {
473
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
474
-
475 470
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
476 471
     key: 0,
477 472
     "class": "p-button p-component",
@@ -491,25 +486,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
491 486
     _: 1
492 487
     /* STABLE */
493 488
 
494
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
495
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
496
-  }, {
497
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
498
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
499
-        key: 0,
500
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
501
-      }, null, 2
502
-      /* CLASS */
503
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
504
-      /* TEXT */
505
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
506
-    }),
507
-    _: 1
508
-    /* STABLE */
509
-
510
-  }, 8
511
-  /* PROPS */
512
-  , ["class"])]));
489
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
490
+    key: 1,
491
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
492
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
493
+    key: 0,
494
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
495
+  }, null, 2
496
+  /* CLASS */
497
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
498
+  /* TEXT */
499
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
500
+  /* CLASS */
501
+  ));
513 502
 }
514 503
 
515 504
 /***/ }),
@@ -1216,6 +1205,15 @@ __webpack_require__.r(__webpack_exports__);
1216 1205
       icon: 'pi pi-wallet',
1217 1206
       to: '/expenses',
1218 1207
       component: 'expense/Index'
1208
+    }, {
1209
+      label: 'Laporan',
1210
+      icon: 'pi pi-book',
1211
+      items: [{
1212
+        label: 'Mutasi',
1213
+        icon: 'pi pi-circle',
1214
+        to: '/reports/mutations',
1215
+        component: 'mutation/Report'
1216
+      }]
1219 1217
     }]
1220 1218
   }, {
1221 1219
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_user_Create_vue.js View File

@@ -1352,6 +1352,15 @@ __webpack_require__.r(__webpack_exports__);
1352 1352
       icon: 'pi pi-wallet',
1353 1353
       to: '/expenses',
1354 1354
       component: 'expense/Index'
1355
+    }, {
1356
+      label: 'Laporan',
1357
+      icon: 'pi pi-book',
1358
+      items: [{
1359
+        label: 'Mutasi',
1360
+        icon: 'pi pi-circle',
1361
+        to: '/reports/mutations',
1362
+        component: 'mutation/Report'
1363
+      }]
1355 1364
     }]
1356 1365
   }, {
1357 1366
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_user_Edit_vue.js View File

@@ -687,15 +687,10 @@ var _hoisted_1 = {
687 687
   "class": "p-button-label"
688 688
 };
689 689
 var _hoisted_2 = {
690
-  key: 1
691
-};
692
-var _hoisted_3 = {
693 690
   key: 1,
694 691
   "class": "p-button-label"
695 692
 };
696 693
 function render(_ctx, _cache, $props, $setup, $data, $options) {
697
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
698
-
699 694
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
700 695
     key: 0,
701 696
     "class": "p-button p-component",
@@ -715,25 +710,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
715 710
     _: 1
716 711
     /* STABLE */
717 712
 
718
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
719
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
720
-  }, {
721
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
722
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
723
-        key: 0,
724
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
725
-      }, null, 2
726
-      /* CLASS */
727
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
728
-      /* TEXT */
729
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
730
-    }),
731
-    _: 1
732
-    /* STABLE */
733
-
734
-  }, 8
735
-  /* PROPS */
736
-  , ["class"])]));
713
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
714
+    key: 1,
715
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
716
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
717
+    key: 0,
718
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
719
+  }, null, 2
720
+  /* CLASS */
721
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
722
+  /* TEXT */
723
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
724
+  /* CLASS */
725
+  ));
737 726
 }
738 727
 
739 728
 /***/ }),
@@ -1642,6 +1631,15 @@ __webpack_require__.r(__webpack_exports__);
1642 1631
       icon: 'pi pi-wallet',
1643 1632
       to: '/expenses',
1644 1633
       component: 'expense/Index'
1634
+    }, {
1635
+      label: 'Laporan',
1636
+      icon: 'pi pi-book',
1637
+      items: [{
1638
+        label: 'Mutasi',
1639
+        icon: 'pi pi-circle',
1640
+        to: '/reports/mutations',
1641
+        component: 'mutation/Report'
1642
+      }]
1645 1643
     }]
1646 1644
   }, {
1647 1645
     label: 'Master',

+ 22
- 24
public/js/resources_js_pages_user_Index_vue.js View File

@@ -500,15 +500,10 @@ var _hoisted_1 = {
500 500
   "class": "p-button-label"
501 501
 };
502 502
 var _hoisted_2 = {
503
-  key: 1
504
-};
505
-var _hoisted_3 = {
506 503
   key: 1,
507 504
   "class": "p-button-label"
508 505
 };
509 506
 function render(_ctx, _cache, $props, $setup, $data, $options) {
510
-  var _component_Button = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button");
511
-
512 507
   return $props.inertiaLink ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createBlock)($setup["Link"], {
513 508
     key: 0,
514 509
     "class": "p-button p-component",
@@ -528,25 +523,19 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
528 523
     _: 1
529 524
     /* STABLE */
530 525
 
531
-  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", _hoisted_2, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button, {
532
-    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)($props.classButton)
533
-  }, {
534
-    "default": (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
535
-      return [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
536
-        key: 0,
537
-        "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
538
-      }, null, 2
539
-      /* CLASS */
540
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_3, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
541
-      /* TEXT */
542
-      )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)];
543
-    }),
544
-    _: 1
545
-    /* STABLE */
546
-
547
-  }, 8
548
-  /* PROPS */
549
-  , ["class"])]));
526
+  })) : ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("a", {
527
+    key: 1,
528
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)([$props.classButton, "p-button p-component"])
529
+  }, [$props.icon ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", {
530
+    key: 0,
531
+    "class": (0,vue__WEBPACK_IMPORTED_MODULE_0__.normalizeClass)(["p-button-icon p-button-icon-left", $props.icon])
532
+  }, null, 2
533
+  /* CLASS */
534
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true), $props.label ? ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("span", _hoisted_2, (0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.label), 1
535
+  /* TEXT */
536
+  )) : (0,vue__WEBPACK_IMPORTED_MODULE_0__.createCommentVNode)("v-if", true)], 2
537
+  /* CLASS */
538
+  ));
550 539
 }
551 540
 
552 541
 /***/ }),
@@ -1288,6 +1277,15 @@ __webpack_require__.r(__webpack_exports__);
1288 1277
       icon: 'pi pi-wallet',
1289 1278
       to: '/expenses',
1290 1279
       component: 'expense/Index'
1280
+    }, {
1281
+      label: 'Laporan',
1282
+      icon: 'pi pi-book',
1283
+      items: [{
1284
+        label: 'Mutasi',
1285
+        icon: 'pi pi-circle',
1286
+        to: '/reports/mutations',
1287
+        component: 'mutation/Report'
1288
+      }]
1291 1289
     }]
1292 1290
   }, {
1293 1291
     label: 'Master',

+ 9
- 0
public/js/resources_js_pages_user_Show_vue.js View File

@@ -1372,6 +1372,15 @@ __webpack_require__.r(__webpack_exports__);
1372 1372
       icon: 'pi pi-wallet',
1373 1373
       to: '/expenses',
1374 1374
       component: 'expense/Index'
1375
+    }, {
1376
+      label: 'Laporan',
1377
+      icon: 'pi pi-book',
1378
+      items: [{
1379
+        label: 'Mutasi',
1380
+        icon: 'pi pi-circle',
1381
+        to: '/reports/mutations',
1382
+        component: 'mutation/Report'
1383
+      }]
1375 1384
     }]
1376 1385
   }, {
1377 1386
     label: 'Master',

+ 17
- 1
public/js/vue.js View File

@@ -58119,6 +58119,22 @@ var map = {
58119 58119
 		"./resources/js/pages/member/TableHeader.js",
58120 58120
 		"resources_js_pages_member_TableHeader_js"
58121 58121
 	],
58122
+	"./mutation/Report": [
58123
+		"./resources/js/pages/mutation/Report.vue",
58124
+		"resources_js_pages_mutation_Report_vue"
58125
+	],
58126
+	"./mutation/Report.vue": [
58127
+		"./resources/js/pages/mutation/Report.vue",
58128
+		"resources_js_pages_mutation_Report_vue"
58129
+	],
58130
+	"./mutation/TableHeader": [
58131
+		"./resources/js/pages/mutation/TableHeader.js",
58132
+		"resources_js_pages_mutation_TableHeader_js"
58133
+	],
58134
+	"./mutation/TableHeader.js": [
58135
+		"./resources/js/pages/mutation/TableHeader.js",
58136
+		"resources_js_pages_mutation_TableHeader_js"
58137
+	],
58122 58138
 	"./topup/Create": [
58123 58139
 		"./resources/js/pages/topup/Create.vue",
58124 58140
 		"resources_js_pages_topup_Create_vue"
@@ -58372,7 +58388,7 @@ module.exports = JSON.parse('{"name":"axios","version":"0.21.4","description":"P
58372 58388
 /******/ 		// This function allow to reference async chunks
58373 58389
 /******/ 		__webpack_require__.u = (chunkId) => {
58374 58390
 /******/ 			// return url for filenames based on template
58375
-/******/ 			return "js/" + chunkId + ".js?id=" + {"node_modules_chart_js_auto_auto_esm_js":"10c6b388645ceb22","resources_js_pages_auth_ForgotPassword_vue":"5b9f0529bda25a9b","resources_js_pages_auth_Login_vue":"61b9c9ae1ae9da32","resources_js_pages_auth_ResetPassword_vue":"b091193a1e114ce8","resources_js_pages_auth_VerifyEmail_vue":"a7b9a99e5a331088","resources_js_pages_expense_Create_vue":"66e7c99b236f0deb","resources_js_pages_expense_Index_vue":"f85b8a458475c32f","resources_js_pages_expense_Show_vue":"c6be13ef48f14ee2","resources_js_pages_expense_TableHeader_js":"eed3f0613f167cfd","resources_js_pages_home_Index_vue":"77d2cc7e0ffbf90e","resources_js_pages_member_Create_vue":"00e438eb5da902ce","resources_js_pages_member_Edit_vue":"48baae4f4480f54d","resources_js_pages_member_Index_vue":"220ea5d5cd363228","resources_js_pages_member_TableHeader_js":"51dbf053f7ddd45c","resources_js_pages_topup_Create_vue":"d9727aeb522f7d0e","resources_js_pages_topup_Index_vue":"4213bf188c295a33","resources_js_pages_topup_Show_vue":"a8c55ac0b35fc72b","resources_js_pages_topup_TableHeader_js":"601b7c0a855ce64e","resources_js_pages_typemember_Create_vue":"a79f5122dd4d955c","resources_js_pages_typemember_Edit_vue":"339a293819be91a7","resources_js_pages_typemember_Index_vue":"b6d16dc9b5f2b3b6","resources_js_pages_typemember_TableHeader_js":"ac1d31a59f8d464e","resources_js_pages_typevehicle_Create_vue":"913e399451308fbb","resources_js_pages_typevehicle_Edit_vue":"659302538c3304bb","resources_js_pages_typevehicle_Index_vue":"a5da2be987ea0ce5","resources_js_pages_typevehicle_TableHeader_js":"a40378918fbe74e1","resources_js_pages_user_Create_vue":"9407a7ca1e9268c7","resources_js_pages_user_Edit_vue":"68b60f3e274f7cd8","resources_js_pages_user_Index_vue":"f3269e9d78d4fe78","resources_js_pages_user_Show_vue":"e1c2622b8345f329","resources_js_pages_user_TableHeader_js":"0d87fd422fe40491"}[chunkId] + "";
58391
+/******/ 			return "js/" + chunkId + ".js?id=" + {"node_modules_chart_js_auto_auto_esm_js":"10c6b388645ceb22","resources_js_pages_auth_ForgotPassword_vue":"5b9f0529bda25a9b","resources_js_pages_auth_Login_vue":"61b9c9ae1ae9da32","resources_js_pages_auth_ResetPassword_vue":"b091193a1e114ce8","resources_js_pages_auth_VerifyEmail_vue":"d9853eae0a0235f2","resources_js_pages_expense_Create_vue":"310e7d98ea6b356a","resources_js_pages_expense_Index_vue":"bc7ec2fb070cf568","resources_js_pages_expense_Show_vue":"877a19596ee241b4","resources_js_pages_expense_TableHeader_js":"eed3f0613f167cfd","resources_js_pages_home_Index_vue":"4c4f4fe595ce63c4","resources_js_pages_member_Create_vue":"838296974c6b4913","resources_js_pages_member_Edit_vue":"bc2c701451f6a653","resources_js_pages_member_Index_vue":"caaaba41d56c9f67","resources_js_pages_member_TableHeader_js":"51dbf053f7ddd45c","resources_js_pages_mutation_Report_vue":"6e9122d512297940","resources_js_pages_mutation_TableHeader_js":"7822e888aa3c52fc","resources_js_pages_topup_Create_vue":"958203b0038681b5","resources_js_pages_topup_Index_vue":"ccfe12c579a19810","resources_js_pages_topup_Show_vue":"4d5dea1719d4048e","resources_js_pages_topup_TableHeader_js":"601b7c0a855ce64e","resources_js_pages_typemember_Create_vue":"5bba3a97069a1889","resources_js_pages_typemember_Edit_vue":"8ab79ae9735ce84f","resources_js_pages_typemember_Index_vue":"1310a39e399f214c","resources_js_pages_typemember_TableHeader_js":"ac1d31a59f8d464e","resources_js_pages_typevehicle_Create_vue":"4799ba8b5384d9a3","resources_js_pages_typevehicle_Edit_vue":"1ec4ba3e7994e2bc","resources_js_pages_typevehicle_Index_vue":"69ab68f9968f9aff","resources_js_pages_typevehicle_TableHeader_js":"a40378918fbe74e1","resources_js_pages_user_Create_vue":"ed7565eb901e854c","resources_js_pages_user_Edit_vue":"4948ac292320388a","resources_js_pages_user_Index_vue":"552950b60f6dbb1b","resources_js_pages_user_Show_vue":"1d1d7702785d1470","resources_js_pages_user_TableHeader_js":"0d87fd422fe40491"}[chunkId] + "";
58376 58392
 /******/ 		};
58377 58393
 /******/ 	})();
58378 58394
 /******/ 	

+ 4
- 4
resources/js/components/AppButton.vue View File

@@ -17,10 +17,10 @@ defineProps({
17 17
     <span v-if="icon" class="p-button-icon p-button-icon-left" :class="icon"></span>
18 18
     <span v-if="label" class="p-button-label">{{ label }}</span>
19 19
   </Link>
20
-  <a v-else>
21
-    <Button :class="classButton">
20
+  <template v-else>
21
+    <a :class="classButton" class="p-button p-component">
22 22
       <span v-if="icon" class="p-button-icon p-button-icon-left" :class="icon"></span>
23 23
       <span v-if="label" class="p-button-label">{{ label }}</span>
24
-    </Button>
25
-  </a>
24
+    </a>
25
+  </template>
26 26
 </template>

+ 182
- 0
resources/js/pages/mutation/Report.vue View File

@@ -0,0 +1,182 @@
1
+<script setup>
2
+import { watch, onMounted, ref } from 'vue'
3
+import { Inertia } from '@inertiajs/inertia'
4
+import { Head, useForm } from '@inertiajs/inertia-vue3'
5
+import dayjs from 'dayjs'
6
+import { pickBy } from 'lodash'
7
+import AppLayout from '@/layouts/AppLayout.vue'
8
+import AppPagination from '@/components/AppPagination.vue'
9
+import AppButton from '@/components/AppButton.vue'
10
+
11
+import TableHeader from './TableHeader'
12
+
13
+const props = defineProps({
14
+  mutations: {
15
+    type: Object,
16
+    default: {
17
+      details: {
18
+        data: [],
19
+        links: [],
20
+        total: 0,
21
+      },
22
+    },
23
+  },
24
+  filters: Object,
25
+})
26
+
27
+const filterForm = useForm({
28
+  dates: null,
29
+  startDate: props.filters.startDate,
30
+  endDate: props.filters.endDate,
31
+})
32
+
33
+onMounted(() => {
34
+  if (props.filters.startDate || props.filters.endDate) {
35
+    if (props.filters.endDate) {
36
+      filterForm.dates = [new Date(props.filters.startDate), new Date(props.filters.endDate)]
37
+    } else {
38
+      filterForm.dates = [new Date(props.filters.startDate), null]
39
+    }
40
+  }
41
+})
42
+
43
+watch(filterForm, () => {
44
+  if (filterForm.dates) {
45
+    if (filterForm.dates[1]) {
46
+      filterForm.startDate = dayjs(filterForm.dates[0]).format('YYYY-MM-DD')
47
+      filterForm.endDate = dayjs(filterForm.dates[1]).format('YYYY-MM-DD')
48
+    } else {
49
+      filterForm.startDate = dayjs(filterForm.dates[0]).format('YYYY-MM-DD')
50
+      filterForm.endDate = null
51
+    }
52
+  } else {
53
+    filterForm.endDate = null
54
+    filterForm.startDate = null
55
+  }
56
+
57
+  Inertia.reload({
58
+    data: pickBy({
59
+      startDate: filterForm.startDate,
60
+      endDate: filterForm.endDate,
61
+    }),
62
+    only: ['mutations'],
63
+  })
64
+
65
+  const params = window.location.search
66
+  exportExcelLink.value = `/reports/mutations/export/excel${params}`
67
+})
68
+
69
+const filterReset = () => {
70
+  Inertia.get('/reports/mutations')
71
+}
72
+
73
+const linkReference = (data) => {
74
+  if (data.topupId) {
75
+    return route('top-ups.show', data.topupId)
76
+  } else if (data.expenseId) {
77
+    return route('expenses.show', data.expenseId)
78
+  } else {
79
+    console.info('under construction')
80
+    // return route('expenses.show', data.expenseId)
81
+  }
82
+}
83
+
84
+const exportExcelLink = ref('/reports/mutations/export/excel')
85
+</script>
86
+
87
+<template>
88
+  <AppLayout>
89
+    <Head title="Laporan Mutasi" />
90
+
91
+    <DataTable
92
+      responsive-layout="scroll"
93
+      column-resize-mode="expand"
94
+      :value="mutations.details.data"
95
+      :row-hover="true"
96
+      :striped-rows="true"
97
+    >
98
+      <template #header>
99
+        <h1>Laporan Mutasi</h1>
100
+
101
+        <div class="grid">
102
+          <div class="col-12 md:col-8">
103
+            <div class="grid">
104
+              <div class="col-12 md:col-4">
105
+                <Calendar
106
+                  class="w-full"
107
+                  v-model="filterForm.dates"
108
+                  selection-mode="range"
109
+                  placeholder="filter waktu..."
110
+                  date-format="dd/mm/yy"
111
+                  :manual-input="false"
112
+                />
113
+              </div>
114
+              <div class="col-auto mt-2 ml-2">
115
+                <Button label="reset" class="p-button-link" @click="filterReset" />
116
+              </div>
117
+            </div>
118
+          </div>
119
+          <div class="col-12 md:col-4 flex flex-column md:flex-row justify-content-end">
120
+            <AppButton
121
+              v-if="mutations.details.total"
122
+              label="Export excel"
123
+              class-button="p-button-outlined md:w-16rem"
124
+              icon="pi pi-file-excel"
125
+              :inertia-link="false"
126
+              :href="exportExcelLink"
127
+            />
128
+          </div>
129
+        </div>
130
+
131
+        <div v-if="mutations.totalAmount" class="grid mt-5 ml-1">
132
+          <div class="col-auto mr-7">
133
+            <h2>
134
+              <span class="text-base"> <i class="pi pi-wallet" /> Pendapatan</span>
135
+
136
+              <br />
137
+
138
+              <span class="text-xl font-bold">{{ mutations.totalIncome }}</span>
139
+            </h2>
140
+          </div>
141
+          <div class="col-auto mr-7">
142
+            <h2>
143
+              <span class="text-base"> <i class="pi pi-wallet" /> Pengeluaran</span>
144
+
145
+              <br />
146
+
147
+              <span class="text-xl font-bold">{{ mutations.totalExpense }}</span>
148
+            </h2>
149
+          </div>
150
+          <div class="col-auto">
151
+            <h2>
152
+              <span class="text-base"> <i class="pi pi-wallet" /> Total Pendapatan </span>
153
+
154
+              <br />
155
+
156
+              <span class="text-xl font-bold">{{ mutations.totalAmount }}</span>
157
+            </h2>
158
+          </div>
159
+        </div>
160
+      </template>
161
+
162
+      <Column
163
+        v-for="tableHeader in TableHeader"
164
+        :field="tableHeader.field"
165
+        :header="tableHeader.header"
166
+        :key="tableHeader.field"
167
+      />
168
+
169
+      <Column>
170
+        <template #body="{ data }">
171
+          <AppButton
172
+            icon="pi pi-link"
173
+            class="p-button-text p-button-icon-only p-button-rounded p-button-text"
174
+            :href="linkReference(data)"
175
+          />
176
+        </template>
177
+      </Column>
178
+    </DataTable>
179
+
180
+    <AppPagination :links="mutations.details.links" />
181
+  </AppLayout>
182
+</template>

+ 5
- 0
resources/js/pages/mutation/TableHeader.js View File

@@ -0,0 +1,5 @@
1
+export default [
2
+  { field: 'createdAt', header: 'Tanggal' },
3
+  { field: 'type', header: 'Tipe' },
4
+  { field: 'amount', header: 'Nilai' },
5
+]

+ 1
- 7
resources/js/pages/topup/Show.vue View File

@@ -1,20 +1,14 @@
1 1
 <script setup>
2
-import { onMounted } from 'vue'
3 2
 import { Head } from '@inertiajs/inertia-vue3'
4 3
 import AppPagination from '@/components/AppPagination.vue'
5 4
 import AppLayout from '@/layouts/AppLayout.vue'
6 5
 
7 6
 import { TopUpsTable } from './TableHeader'
8 7
 
9
-const props = defineProps({
8
+defineProps({
10 9
   member: Object,
11 10
   topUp: Object,
12 11
 })
13
-
14
-onMounted(() => {
15
-  console.info(props.member)
16
-  console.table(props.topUp)
17
-})
18 12
 </script>
19 13
 
20 14
 <template>

+ 8
- 1
resources/js/utils/menu.js View File

@@ -19,7 +19,14 @@ export default {
19 19
     },
20 20
     {
21 21
       label: 'Menu',
22
-      items: [{ label: 'Pengeluaran', icon: 'pi pi-wallet', to: '/expenses', component: 'expense/Index' }],
22
+      items: [
23
+        { label: 'Pengeluaran', icon: 'pi pi-wallet', to: '/expenses', component: 'expense/Index' },
24
+        {
25
+          label: 'Laporan',
26
+          icon: 'pi pi-book',
27
+          items: [{ label: 'Mutasi', icon: 'pi pi-circle', to: '/reports/mutations', component: 'mutation/Report' }],
28
+        },
29
+      ],
23 30
     },
24 31
     {
25 32
       label: 'Master',

+ 45
- 0
resources/views/excel/mutation-report.blade.php View File

@@ -0,0 +1,45 @@
1
+<table>
2
+    <thead>
3
+        <tr>
4
+            <th colspan="5">Laporan Mutasi</th>
5
+        </tr>
6
+        <tr>
7
+            <th colspan="5" rowspan="2">Periode {{ $mutations->first()->created_at }} -
8
+                {{ $mutations->last()->created_at }} </th>
9
+        </tr>
10
+        <tr></tr>
11
+        <tr>
12
+            <th>#</th>
13
+            <th>Tanggal</th>
14
+            <th>Tipe</th>
15
+            <th>Nilai</th>
16
+        </tr>
17
+    </thead>
18
+    <tbody>
19
+        @foreach ($mutations->chunk(100) as $chunk)
20
+            @foreach ($chunk as $index => $mutation)
21
+                <tr>
22
+                    <td>{{ ++$index }}</td>
23
+                    <td>{{ $mutation->created_at }}</td>
24
+                    <td>{{ $mutation->type }}</td>
25
+                    <td>{{ $mutation->amount }}</td>
26
+                </tr>
27
+            @endforeach
28
+        @endforeach
29
+        <tr>
30
+            <td colspan="3">Total</td>
31
+        </tr>
32
+        <tr>
33
+            <td colspan="3">Pendapatan</td>
34
+            <td>{{ (new App\Services\MutationService())->totalIncomeAsString($mutations) }}</td>
35
+        </tr>
36
+        <tr>
37
+            <td colspan="3">Pengeluran</td>
38
+            <td>{{ (new App\Services\MutationService())->totalExpenseAsString($mutations) }}</td>
39
+        </tr>
40
+        <tr>
41
+            <td colspan="3">Jumlah Pendapatan</td>
42
+            <td>{{ (new App\Services\MutationService())->totalAmountAsString($mutations) }}</td>
43
+        </tr>
44
+    </tbody>
45
+</table>

+ 4
- 0
routes/web.php View File

@@ -3,6 +3,7 @@
3 3
 use App\Http\Controllers\DashboardController;
4 4
 use App\Http\Controllers\ExpenseController;
5 5
 use App\Http\Controllers\MemberController;
6
+use App\Http\Controllers\ReportMutationController;
6 7
 use App\Http\Controllers\TopUpController;
7 8
 use App\Http\Controllers\TypeMemberController;
8 9
 use App\Http\Controllers\TypeVehicleController;
@@ -27,6 +28,9 @@ Route::middleware(['auth', 'verified'])->group(function () {
27 28
 
28 29
     Route::resource('/expenses', ExpenseController::class);
29 30
 
31
+    Route::get('/reports/mutations', [ReportMutationController::class, 'index']);
32
+    Route::get('/reports/mutations/export/excel', [ReportMutationController::class, 'exportExcel'])->name('mutations.excel');
33
+
30 34
     Route::resource('/members', MemberController::class);
31 35
 
32 36
     Route::resource('/top-ups', TopUpController::class);