浏览代码

feat: outlet statistics outlet

父节点
当前提交
2517ef5eb9

+ 11
- 1
app/Http/Controllers/DashboardController.php 查看文件

23
     public function __invoke(Request $request)
23
     public function __invoke(Request $request)
24
     {
24
     {
25
         $transactions = Transaction::filter(['startDate' => today()])->get();
25
         $transactions = Transaction::filter(['startDate' => today()])->get();
26
+
26
         $expenses = Expense::filter(['startDate' => today()])->get();
27
         $expenses = Expense::filter(['startDate' => today()])->get();
28
+
27
         $laundries = Laundry::get();
29
         $laundries = Laundry::get();
30
+
28
         $products = Product::get();
31
         $products = Product::get();
29
 
32
 
30
         $transactionChartStatistic = Transaction::get()->groupBy([
33
         $transactionChartStatistic = Transaction::get()->groupBy([
31
             fn($transaction) => Carbon::parse($transaction->getRawOriginal('created_at'))->format('Y'),
34
             fn($transaction) => Carbon::parse($transaction->getRawOriginal('created_at'))->format('Y'),
32
             fn($transaction) => Carbon::parse($transaction->getRawOriginal('created_at'))->format('M'),
35
             fn($transaction) => Carbon::parse($transaction->getRawOriginal('created_at'))->format('M'),
33
         ]);
36
         ]);
37
+
34
         $expenseChartStatistic = Expense::get()->groupBy([
38
         $expenseChartStatistic = Expense::get()->groupBy([
35
             fn($expense) => Carbon::parse($expense->getRawOriginal('created_at'))->format('Y'),
39
             fn($expense) => Carbon::parse($expense->getRawOriginal('created_at'))->format('Y'),
36
             fn($expense) => Carbon::parse($expense->getRawOriginal('created_at'))->format('M'),
40
             fn($expense) => Carbon::parse($expense->getRawOriginal('created_at'))->format('M'),
37
         ]);
41
         ]);
38
 
42
 
43
+        $transactionOutletChartStatistic = Transaction::get()->groupBy('outlet.name');
44
+
39
         return inertia('home/Index', [
45
         return inertia('home/Index', [
40
             'cardStatistics' => [
46
             'cardStatistics' => [
41
                 [
47
                 [
65
                     'amount' => $products->count(),
71
                     'amount' => $products->count(),
66
                 ],
72
                 ],
67
             ],
73
             ],
68
-            'chartStatistics' => [
74
+            'transactionStatistics' => [
69
                 [
75
                 [
70
                     'title' => __('words.transaction_statistic'),
76
                     'title' => __('words.transaction_statistic'),
71
                     'data' => (new TransactionService)->statisticData($transactionChartStatistic),
77
                     'data' => (new TransactionService)->statisticData($transactionChartStatistic),
75
                     'data' => (new ExpenseService)->statisticData($expenseChartStatistic),
81
                     'data' => (new ExpenseService)->statisticData($expenseChartStatistic),
76
                 ],
82
                 ],
77
             ],
83
             ],
84
+            'transactionOutletStatistics' => [
85
+                'title' => __('words.transaction_outlet_statistic'),
86
+                'data' => (new TransactionService)->totalPerMonth($transactionOutletChartStatistic),
87
+            ],
78
         ]);
88
         ]);
79
     }
89
     }
80
 }
90
 }

+ 1
- 0
lang/en/words.php 查看文件

25
     'product_type' => 'Product Type',
25
     'product_type' => 'Product Type',
26
     'transaction_statistic' => 'Transaction Statistic',
26
     'transaction_statistic' => 'Transaction Statistic',
27
     'expense_statistic' => 'Expense Statistic',
27
     'expense_statistic' => 'Expense Statistic',
28
+    'transaction_outlet_statistic' => 'Transaction Statistic/Outlet',
28
 
29
 
29
 ];
30
 ];

+ 1
- 0
lang/id/words.php 查看文件

25
     'product_type' => 'Jenis Product',
25
     'product_type' => 'Jenis Product',
26
     'transaction_statistic' => 'Statistik Transaksi',
26
     'transaction_statistic' => 'Statistik Transaksi',
27
     'expense_statistic' => 'Statistik Pengeluaran',
27
     'expense_statistic' => 'Statistik Pengeluaran',
28
+    'transaction_outlet_statistic' => 'Statistik Transaksi/Outlet',
28
 
29
 
29
 ];
30
 ];

+ 69
- 13
public/js/resources_js_pages_home_Index_vue.js 查看文件

318
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
318
 /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
319
   props: {
319
   props: {
320
     cardStatistics: Object,
320
     cardStatistics: Object,
321
-    chartStatistics: Object
321
+    transactionStatistics: Object,
322
+    transactionOutletStatistics: Object
322
   },
323
   },
323
   setup: function setup(__props, _ref) {
324
   setup: function setup(__props, _ref) {
324
     var expose = _ref.expose;
325
     var expose = _ref.expose;
325
     expose();
326
     expose();
326
 
327
 
327
-    var chartData = function chartData(_chartData) {
328
-      var colors = ['#42A5F5', '#FFA726'];
328
+    var transactionBarData = function transactionBarData(chartData) {
329
+      var colors = ['#17b6ff', '#ffb51c'];
329
       var data = {
330
       var data = {
330
         datasets: []
331
         datasets: []
331
       };
332
       };
332
       var id = 0;
333
       var id = 0;
333
 
334
 
334
-      for (var key in _chartData) {
335
+      for (var key in chartData) {
335
         data.datasets.push({
336
         data.datasets.push({
336
           label: key,
337
           label: key,
337
           backgroundColor: colors[id],
338
           backgroundColor: colors[id],
338
-          data: _chartData[key]
339
+          data: chartData[key]
339
         });
340
         });
340
         id++;
341
         id++;
341
       }
342
       }
343
       return data;
344
       return data;
344
     };
345
     };
345
 
346
 
346
-    var chartOptions = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)({
347
+    var transactionBarOption = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)({
347
       responsive: true,
348
       responsive: true,
348
       maintainAspectRatio: false,
349
       maintainAspectRatio: false,
349
       datasetFill: false,
350
       datasetFill: false,
360
         }
361
         }
361
       }
362
       }
362
     });
363
     });
364
+
365
+    var transactionOutletPieData = function transactionOutletPieData(chartData) {
366
+      var labels = [];
367
+      var data = [];
368
+
369
+      for (var key in chartData) {
370
+        labels.push(key);
371
+        data.push(chartData[key]);
372
+      }
373
+
374
+      return {
375
+        labels: labels,
376
+        datasets: [{
377
+          data: data,
378
+          backgroundColor: ['#17b6ff', '#00c3f7', '#00cbdc', '#00d1b2', '#2bd281', '#86cf50', '#c5c623', '#ffb51c']
379
+        }]
380
+      };
381
+    };
382
+
383
+    var transactionOutletPieOption = (0,vue__WEBPACK_IMPORTED_MODULE_0__.ref)({
384
+      maintainAspectRatio: false,
385
+      datasetFill: false,
386
+      plugins: {
387
+        legend: {
388
+          labels: {
389
+            color: '#495057'
390
+          }
391
+        }
392
+      }
393
+    });
363
     var __returned__ = {
394
     var __returned__ = {
364
-      chartData: chartData,
365
-      chartOptions: chartOptions,
395
+      transactionBarData: transactionBarData,
396
+      transactionBarOption: transactionBarOption,
397
+      transactionOutletPieData: transactionOutletPieData,
398
+      transactionOutletPieOption: transactionOutletPieOption,
366
       ref: vue__WEBPACK_IMPORTED_MODULE_0__.ref,
399
       ref: vue__WEBPACK_IMPORTED_MODULE_0__.ref,
367
       Head: _inertiajs_inertia_vue3__WEBPACK_IMPORTED_MODULE_1__.Head,
400
       Head: _inertiajs_inertia_vue3__WEBPACK_IMPORTED_MODULE_1__.Head,
368
       AppLayout: _layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_2__["default"]
401
       AppLayout: _layouts_AppLayout_vue__WEBPACK_IMPORTED_MODULE_2__["default"]
902
 var _hoisted_9 = {
935
 var _hoisted_9 = {
903
   "class": "col-12 md:col-6"
936
   "class": "col-12 md:col-6"
904
 };
937
 };
938
+var _hoisted_10 = {
939
+  "class": "col-12 md:col-6"
940
+};
905
 function render(_ctx, _cache, $props, $setup, $data, $options) {
941
 function render(_ctx, _cache, $props, $setup, $data, $options) {
906
   var _component_Card = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Card");
942
   var _component_Card = (0,vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Card");
907
 
943
 
938
         )]);
974
         )]);
939
       }), 256
975
       }), 256
940
       /* UNKEYED_FRAGMENT */
976
       /* UNKEYED_FRAGMENT */
941
-      )), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.chartStatistics, function (chartStatistic) {
977
+      )), ((0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(true), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)(vue__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, (0,vue__WEBPACK_IMPORTED_MODULE_0__.renderList)($props.transactionStatistics, function (transactionStatistic) {
942
         return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Card, null, {
978
         return (0,vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_9, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Card, null, {
943
           title: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
979
           title: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
944
-            return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(chartStatistic.title), 1
980
+            return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)(transactionStatistic.title), 1
945
             /* TEXT */
981
             /* TEXT */
946
             )];
982
             )];
947
           }),
983
           }),
948
           content: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
984
           content: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
949
             return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Chart, {
985
             return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Chart, {
950
               type: "bar",
986
               type: "bar",
951
-              data: $setup.chartData(chartStatistic.data),
952
-              options: $setup.chartOptions
987
+              data: $setup.transactionBarData(transactionStatistic.data),
988
+              options: $setup.transactionBarOption
953
             }, null, 8
989
             }, null, 8
954
             /* PROPS */
990
             /* PROPS */
955
             , ["data", "options"])];
991
             , ["data", "options"])];
962
         )]);
998
         )]);
963
       }), 256
999
       }), 256
964
       /* UNKEYED_FRAGMENT */
1000
       /* UNKEYED_FRAGMENT */
965
-      ))])];
1001
+      )), (0,vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("div", _hoisted_10, [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Card, null, {
1002
+        title: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
1003
+          return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createTextVNode)((0,vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($props.transactionOutletStatistics.title), 1
1004
+          /* TEXT */
1005
+          )];
1006
+        }),
1007
+        content: (0,vue__WEBPACK_IMPORTED_MODULE_0__.withCtx)(function () {
1008
+          return [(0,vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Chart, {
1009
+            type: "pie",
1010
+            width: 600,
1011
+            height: 300,
1012
+            data: $setup.transactionOutletPieData($props.transactionOutletStatistics.data),
1013
+            options: $setup.transactionOutletPieOption
1014
+          }, null, 8
1015
+          /* PROPS */
1016
+          , ["data", "options"])];
1017
+        }),
1018
+        _: 1
1019
+        /* STABLE */
1020
+
1021
+      })])])];
966
     }),
1022
     }),
967
     _: 1
1023
     _: 1
968
     /* STABLE */
1024
     /* STABLE */

+ 1
- 1
public/js/vue.js 查看文件

58088
 /******/ 		// This function allow to reference async chunks
58088
 /******/ 		// This function allow to reference async chunks
58089
 /******/ 		__webpack_require__.u = (chunkId) => {
58089
 /******/ 		__webpack_require__.u = (chunkId) => {
58090
 /******/ 			// return url for filenames based on template
58090
 /******/ 			// return url for filenames based on template
58091
-/******/ 			return "js/" + chunkId + ".js?id=" + {"node_modules_chart_js_auto_auto_esm_js":"10c6b388645ceb22","resources_js_pages_auth_ForgotPassword_vue":"06e3fde2f6b5dfa3","resources_js_pages_auth_Login_vue":"0d70b4f828bb2ae3","resources_js_pages_auth_ResetPassword_vue":"2ba70d514b47ecff","resources_js_pages_auth_VerifyEmail_vue":"ebac28cf5fb51cfc","resources_js_pages_customer_Create_vue":"1220be5949d46569","resources_js_pages_customer_Edit_vue":"7571072c6961cb67","resources_js_pages_customer_Index_vue":"89aeb69bc7bf9125","resources_js_pages_customer_TableHeader_js":"71be5afdca048a9c","resources_js_pages_discount_Index_vue":"7a73e2119e6e6c6f","resources_js_pages_error_Error_vue":"39121f9961877130","resources_js_pages_expense_Create_vue":"8fa047c8fcff0fa3","resources_js_pages_expense_Index_vue":"b56d8a0027fef24c","resources_js_pages_expense_Show_vue":"e46cf4a28b9e732b","resources_js_pages_expense_TableHeader_js":"72e3dee74175b1c0","resources_js_pages_home_Index_vue":"8f0e1faaa7b884eb","resources_js_pages_laundry_Create_vue":"f5731b3f078c4bff","resources_js_pages_laundry_Edit_vue":"430f285b197d2fc1","resources_js_pages_laundry_Index_vue":"ee761f9e7d6e4502","resources_js_pages_laundry_TableHeader_js":"494e577855bbcaf6","resources_js_pages_mutation_Report_vue":"f53d6840d3891069","resources_js_pages_mutation_TableHeader_js":"82c2999bd7d098a1","resources_js_pages_outlet_Create_vue":"4958b1a88d1e03d1","resources_js_pages_outlet_Edit_vue":"3ce4dea5bd8e134a","resources_js_pages_outlet_Index_vue":"f58972cb6db52f4a","resources_js_pages_outlet_TableHeader_js":"498bf7e64bc0d0c4","resources_js_pages_product_Create_vue":"6f7ae2bf0addfd2c","resources_js_pages_product_Edit_vue":"aec56d000e33fbe6","resources_js_pages_product_Index_vue":"e73d3cd965bdbfb3","resources_js_pages_product_TableHeader_js":"b8eaaa9de25a2322","resources_js_pages_transaction_Create_vue":"04881653c83db0e8","resources_js_pages_transaction_Index_vue":"54a40dce85162abd","resources_js_pages_transaction_Report_vue":"8b3c37b617041b96","resources_js_pages_transaction_Show_vue":"bc1cb7b5161b5386","resources_js_pages_transaction_TableHeader_js":"be63e672e103818b","resources_js_pages_user_Create_vue":"9328027e33f14038","resources_js_pages_user_Edit_vue":"5e97bc1dbb553877","resources_js_pages_user_Index_vue":"bc60d10f530734f1","resources_js_pages_user_Show_vue":"0acbc3d158904cf1","resources_js_pages_user_TableHeader_js":"5653ecbcd70fd235"}[chunkId] + "";
58091
+/******/ 			return "js/" + chunkId + ".js?id=" + {"node_modules_chart_js_auto_auto_esm_js":"10c6b388645ceb22","resources_js_pages_auth_ForgotPassword_vue":"06e3fde2f6b5dfa3","resources_js_pages_auth_Login_vue":"0d70b4f828bb2ae3","resources_js_pages_auth_ResetPassword_vue":"2ba70d514b47ecff","resources_js_pages_auth_VerifyEmail_vue":"ebac28cf5fb51cfc","resources_js_pages_customer_Create_vue":"1220be5949d46569","resources_js_pages_customer_Edit_vue":"7571072c6961cb67","resources_js_pages_customer_Index_vue":"89aeb69bc7bf9125","resources_js_pages_customer_TableHeader_js":"71be5afdca048a9c","resources_js_pages_discount_Index_vue":"7a73e2119e6e6c6f","resources_js_pages_error_Error_vue":"39121f9961877130","resources_js_pages_expense_Create_vue":"8fa047c8fcff0fa3","resources_js_pages_expense_Index_vue":"b56d8a0027fef24c","resources_js_pages_expense_Show_vue":"e46cf4a28b9e732b","resources_js_pages_expense_TableHeader_js":"72e3dee74175b1c0","resources_js_pages_home_Index_vue":"ebcb4cef897548d8","resources_js_pages_laundry_Create_vue":"f5731b3f078c4bff","resources_js_pages_laundry_Edit_vue":"430f285b197d2fc1","resources_js_pages_laundry_Index_vue":"ee761f9e7d6e4502","resources_js_pages_laundry_TableHeader_js":"494e577855bbcaf6","resources_js_pages_mutation_Report_vue":"f53d6840d3891069","resources_js_pages_mutation_TableHeader_js":"82c2999bd7d098a1","resources_js_pages_outlet_Create_vue":"4958b1a88d1e03d1","resources_js_pages_outlet_Edit_vue":"3ce4dea5bd8e134a","resources_js_pages_outlet_Index_vue":"f58972cb6db52f4a","resources_js_pages_outlet_TableHeader_js":"498bf7e64bc0d0c4","resources_js_pages_product_Create_vue":"6f7ae2bf0addfd2c","resources_js_pages_product_Edit_vue":"aec56d000e33fbe6","resources_js_pages_product_Index_vue":"e73d3cd965bdbfb3","resources_js_pages_product_TableHeader_js":"b8eaaa9de25a2322","resources_js_pages_transaction_Create_vue":"04881653c83db0e8","resources_js_pages_transaction_Index_vue":"54a40dce85162abd","resources_js_pages_transaction_Report_vue":"8b3c37b617041b96","resources_js_pages_transaction_Show_vue":"bc1cb7b5161b5386","resources_js_pages_transaction_TableHeader_js":"be63e672e103818b","resources_js_pages_user_Create_vue":"9328027e33f14038","resources_js_pages_user_Edit_vue":"5e97bc1dbb553877","resources_js_pages_user_Index_vue":"bc60d10f530734f1","resources_js_pages_user_Show_vue":"0acbc3d158904cf1","resources_js_pages_user_TableHeader_js":"5653ecbcd70fd235"}[chunkId] + "";
58092
 /******/ 		};
58092
 /******/ 		};
58093
 /******/ 	})();
58093
 /******/ 	})();
58094
 /******/ 	
58094
 /******/ 	

+ 55
- 7
resources/js/pages/home/Index.vue 查看文件

5
 
5
 
6
 defineProps({
6
 defineProps({
7
   cardStatistics: Object,
7
   cardStatistics: Object,
8
-  chartStatistics: Object,
8
+  transactionStatistics: Object,
9
+  transactionOutletStatistics: Object,
9
 })
10
 })
10
 
11
 
11
-const chartData = (chartData) => {
12
-  const colors = ['#42A5F5', '#FFA726']
12
+const transactionBarData = (chartData) => {
13
+  const colors = ['#17b6ff', '#ffb51c']
13
 
14
 
14
   const data = {
15
   const data = {
15
     datasets: [],
16
     datasets: [],
29
   return data
30
   return data
30
 }
31
 }
31
 
32
 
32
-const chartOptions = ref({
33
+const transactionBarOption = ref({
33
   responsive: true,
34
   responsive: true,
34
   maintainAspectRatio: false,
35
   maintainAspectRatio: false,
35
   datasetFill: false,
36
   datasetFill: false,
46
     },
47
     },
47
   },
48
   },
48
 })
49
 })
50
+
51
+const transactionOutletPieData = (chartData) => {
52
+  const labels = []
53
+  const data = []
54
+
55
+  for (const key in chartData) {
56
+    labels.push(key)
57
+    data.push(chartData[key])
58
+  }
59
+
60
+  return {
61
+    labels: labels,
62
+    datasets: [
63
+      {
64
+        data: data,
65
+        backgroundColor: ['#17b6ff', '#00c3f7', '#00cbdc', '#00d1b2', '#2bd281', '#86cf50', '#c5c623', '#ffb51c'],
66
+      },
67
+    ],
68
+  }
69
+}
70
+
71
+const transactionOutletPieOption = ref({
72
+  maintainAspectRatio: false,
73
+  datasetFill: false,
74
+  plugins: {
75
+    legend: {
76
+      labels: {
77
+        color: '#495057',
78
+      },
79
+    },
80
+  },
81
+})
49
 </script>
82
 </script>
50
 
83
 
51
 <template>
84
 <template>
74
         </Card>
107
         </Card>
75
       </div>
108
       </div>
76
 
109
 
77
-      <div v-for="chartStatistic in chartStatistics" class="col-12 md:col-6">
110
+      <div v-for="transactionStatistic in transactionStatistics" class="col-12 md:col-6">
111
+        <Card>
112
+          <template #title>{{ transactionStatistic.title }}</template>
113
+          <template #content>
114
+            <Chart type="bar" :data="transactionBarData(transactionStatistic.data)" :options="transactionBarOption" />
115
+          </template>
116
+        </Card>
117
+      </div>
118
+
119
+      <div class="col-12 md:col-6">
78
         <Card>
120
         <Card>
79
-          <template #title>{{ chartStatistic.title }}</template>
121
+          <template #title>{{ transactionOutletStatistics.title }}</template>
80
           <template #content>
122
           <template #content>
81
-            <Chart type="bar" :data="chartData(chartStatistic.data)" :options="chartOptions" />
123
+            <Chart
124
+              type="pie"
125
+              :width="600"
126
+              :height="300"
127
+              :data="transactionOutletPieData(transactionOutletStatistics.data)"
128
+              :options="transactionOutletPieOption"
129
+            />
82
           </template>
130
           </template>
83
         </Card>
131
         </Card>
84
       </div>
132
       </div>