123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <script setup>
  2. import { Head } from '@inertiajs/inertia-vue3'
  3. import orderBy from 'lodash/orderBy'
  4. import AppLayout from '@/layouts/AppLayout.vue'
  5. defineProps({
  6. cardStatistics: Object,
  7. chartTransactionStatistics: Object,
  8. chartOutletStatistic: Object,
  9. chartTopTransactionStatistic: Object,
  10. })
  11. const colors = [
  12. '#349dcf',
  13. '#00b2da',
  14. '#00c7dd',
  15. '#1fdbdb',
  16. '#57eed3',
  17. '#88ffc9',
  18. '#96ed9a',
  19. '#a8d96c',
  20. '#bbc242',
  21. '#cda91d',
  22. ]
  23. const transactionBarData = (chartData) => {
  24. const colors = ['#349dcf', '#a8d96c']
  25. const data = {
  26. datasets: [],
  27. }
  28. let id = 0
  29. for (const key in chartData) {
  30. data.datasets.push({
  31. label: key,
  32. backgroundColor: colors[id],
  33. data: chartData[key],
  34. })
  35. id++
  36. }
  37. return data
  38. }
  39. const transactionBarOption = {
  40. maintainAspectRatio: false,
  41. datasetFill: false,
  42. }
  43. const transactionOutletPieData = (chartData) => {
  44. const labels = []
  45. const data = []
  46. for (const key in chartData) {
  47. labels.push(key)
  48. data.push(chartData[key])
  49. }
  50. return {
  51. labels: labels,
  52. datasets: [
  53. {
  54. data: data,
  55. backgroundColor: colors,
  56. },
  57. ],
  58. }
  59. }
  60. const transactionOutletPieOption = {
  61. maintainAspectRatio: false,
  62. datasetFill: false,
  63. }
  64. const topTransactionData = (chartData) => {
  65. const labels = []
  66. const data = []
  67. for (const chartData of orderBy(chartData, ['totalPrice'], ['desc'])) {
  68. labels.push([chartData.customerNumber, chartData.name])
  69. data.push(chartData.totalPrice)
  70. }
  71. return {
  72. labels: labels,
  73. datasets: [
  74. {
  75. data: data,
  76. backgroundColor: colors,
  77. },
  78. ],
  79. }
  80. }
  81. const topTransactionOption = {
  82. maintainAspectRatio: false,
  83. datasetFill: false,
  84. indexAxis: 'y',
  85. plugins: {
  86. legend: {
  87. display: false,
  88. },
  89. },
  90. }
  91. </script>
  92. <template>
  93. <AppLayout>
  94. <Head title="Dashboard" />
  95. <div class="grid">
  96. <div class="col-12 flex flex-wrap justify-content-between card-statistic">
  97. <div v-for="cardStatistic in cardStatistics" class="flex-grow-1">
  98. <Card class="h-full">
  99. <template #content>
  100. <div class="flex justify-content-between mb-3">
  101. <div>
  102. <span class="block text-500 font-medium mb-3">{{ cardStatistic.title }}</span>
  103. <div v-if="cardStatistic.value" class="text-900 font-medium text-xl">{{ cardStatistic.value }}</div>
  104. </div>
  105. <div
  106. class="flex align-items-center justify-content-center bg-orange-100 border-round"
  107. style="width: 2.5rem; height: 2.5rem"
  108. >
  109. <i class="text-orange-500 text-xl" :class="cardStatistic.icon"></i>
  110. </div>
  111. </div>
  112. <span class="text-green-500 font-medium">{{ cardStatistic.amount }} </span>
  113. <span class="text-500"> {{ ' ' + cardStatistic.amountLabel }}</span>
  114. </template>
  115. </Card>
  116. </div>
  117. </div>
  118. <div v-for="statistic in chartTransactionStatistics" class="col-12 md:col-6">
  119. <Card>
  120. <template #title>
  121. <div class="flex flex-column">
  122. <span>{{ statistic.title }}</span>
  123. <span class="text-base font-normal">{{ statistic.description }}</span>
  124. </div>
  125. </template>
  126. <template #content>
  127. <Chart type="bar" :data="transactionBarData(statistic.data)" :options="transactionBarOption" />
  128. </template>
  129. </Card>
  130. </div>
  131. <div class="col-12 md:col-6">
  132. <Card>
  133. <template #title>
  134. <div class="flex flex-column">
  135. <span>{{ chartOutletStatistic.title }}</span>
  136. <span class="text-base font-normal">{{ chartOutletStatistic.description }}</span>
  137. </div>
  138. </template>
  139. <template #content>
  140. <Chart
  141. type="pie"
  142. :width="600"
  143. :height="300"
  144. :data="transactionOutletPieData(chartOutletStatistic.data)"
  145. :options="transactionOutletPieOption"
  146. />
  147. </template>
  148. </Card>
  149. </div>
  150. <div class="col-12 md:col-6">
  151. <Card>
  152. <template #title>
  153. <div class="flex flex-column">
  154. <span>{{ chartTopTransactionStatistic.title }}</span>
  155. <span class="text-base font-normal">{{ chartTopTransactionStatistic.description }}</span>
  156. </div>
  157. </template>
  158. <template #content>
  159. <Chart
  160. type="bar"
  161. :width="600"
  162. :height="300"
  163. :data="topTransactionData(chartTopTransactionStatistic.data)"
  164. :options="topTransactionOption"
  165. />
  166. </template>
  167. </Card>
  168. </div>
  169. </div>
  170. </AppLayout>
  171. </template>
  172. <style scoped>
  173. .card-statistic {
  174. gap: 1rem;
  175. }
  176. </style>