You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CumulativeCompanyData.php 6.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. <?php
  2. namespace App\Filament\Pages\Widgets\Companies\Charts;
  3. use App\Models\Company;
  4. use Leandrocfe\FilamentApexCharts\Widgets\ApexChartWidget;
  5. class CumulativeCompanyData extends ApexChartWidget
  6. {
  7. protected int|string|array $columnSpan = [
  8. 'md' => 2,
  9. 'xl' => 3,
  10. ];
  11. /**
  12. * Chart Id
  13. *
  14. * @var string
  15. */
  16. protected static string $chartId = 'cumulative-company-data';
  17. /**
  18. * Widget Title
  19. *
  20. * @var string|null
  21. */
  22. protected static ?string $heading = 'Cumulative Company Data';
  23. protected function getOptions(): array
  24. {
  25. $startOfYear = today()->startOfYear();
  26. $today = today();
  27. // Company data
  28. $companyData = Company::selectRaw("COUNT(*) as aggregate, YEARWEEK(created_at, 3) as week")
  29. ->whereBetween('created_at', [$startOfYear, $today])
  30. ->groupByRaw('week')
  31. ->get();
  32. $weeks = [];
  33. for ($week = $startOfYear->copy(); $week->lte($today); $week->addWeek()) {
  34. $weeks[$week->format('oW')] = 0;
  35. }
  36. $weeklyData = collect($weeks)->mapWithKeys(static function ($value, $week) use ($companyData) {
  37. $matchingData = $companyData->firstWhere('week', $week);
  38. return [$week => $matchingData ? $matchingData->aggregate : 0];
  39. });
  40. $totalCompanies = $weeklyData->reduce(static function ($carry, $value) {
  41. $carry[] = ($carry ? end($carry) : 0) + $value;
  42. return $carry;
  43. }, []);
  44. // Calculate percentage increase and increase in companies per week
  45. $newCompanies = [0];
  46. $weeklyPercentageChange = [0];
  47. for ($i = 1; $i < count($totalCompanies); $i++) {
  48. $newCompanies[] = $totalCompanies[$i] - $totalCompanies[$i - 1];
  49. $weeklyPercentageChange[] = ($newCompanies[$i] / $totalCompanies[$i - 1]) * 100;
  50. }
  51. // Calculate exponential smoothing for total companies
  52. $alpha = 0.3; // Smoothing factor, between 0 and 1
  53. $smoothedTotalCompanies = [];
  54. $smoothedTotalCompanies[0] = $totalCompanies[0]; // Initialize the first smoothed value
  55. for ($i = 1; $i < count($totalCompanies); $i++) {
  56. $smoothedTotalCompanies[$i] = $alpha * $totalCompanies[$i] + (1 - $alpha) * $smoothedTotalCompanies[$i - 1];
  57. }
  58. $labels = collect($weeks)->keys()->map(static function ($week) {
  59. $year = substr($week, 0, 4);
  60. $weekNumber = substr($week, 4);
  61. return today()->setISODate($year, $weekNumber)->format('M d');
  62. });
  63. return [
  64. 'chart' => [
  65. 'type' => 'line',
  66. 'height' => 350,
  67. 'stacked' => false,
  68. 'toolbar' => [
  69. 'show' => false,
  70. ],
  71. ],
  72. 'series' => [
  73. [
  74. 'name' => 'Weekly Growth Rate',
  75. 'type' => 'area',
  76. 'data' => $weeklyPercentageChange,
  77. ],
  78. [
  79. 'name' => 'New Companies',
  80. 'type' => 'line',
  81. 'data' => $newCompanies,
  82. ],
  83. [
  84. 'name' => 'Smoothed Total Companies',
  85. 'type' => 'line',
  86. 'data' => $smoothedTotalCompanies,
  87. ],
  88. [
  89. 'name' => 'Total Companies',
  90. 'type' => 'column',
  91. 'data' => $totalCompanies,
  92. ],
  93. ],
  94. 'xaxis' => [
  95. 'categories' => $labels,
  96. 'position' => 'bottom',
  97. 'labels' => [
  98. 'style' => [
  99. 'colors' => '#9ca3af',
  100. 'fontWeight' => 600,
  101. ],
  102. ],
  103. ],
  104. 'yaxis' => [
  105. [
  106. 'seriesName' => 'Weekly Growth Rate',
  107. 'decimalsInFloat' => 2,
  108. 'labels' => [
  109. 'style' => [
  110. 'colors' => '#9ca3af',
  111. 'fontWeight' => 600,
  112. ],
  113. ],
  114. ],
  115. [
  116. 'seriesName' => 'New Companies',
  117. 'decimalsInFloat' => 0,
  118. 'opposite' => true,
  119. 'labels' => [
  120. 'style' => [
  121. 'colors' => '#9ca3af',
  122. 'fontWeight' => 600,
  123. ],
  124. ],
  125. ],
  126. [
  127. 'seriesName' => 'Smoothed Total Companies',
  128. 'decimalsInFloat' => 0,
  129. 'opposite' => true,
  130. 'labels' => [
  131. 'style' => [
  132. 'colors' => '#9ca3af',
  133. 'fontWeight' => 600,
  134. ],
  135. ],
  136. ],
  137. [
  138. 'seriesName' => 'Total Companies',
  139. 'decimalsInFloat' => 0,
  140. 'opposite' => true,
  141. 'labels' => [
  142. 'style' => [
  143. 'colors' => '#9ca3af',
  144. 'fontWeight' => 600,
  145. ],
  146. ],
  147. ],
  148. ],
  149. 'legend' => [
  150. 'position' => 'top',
  151. 'horizontalAlign' => 'center',
  152. 'labels' => [
  153. 'colors' => '#9ca3af',
  154. 'fontWeight' => 600,
  155. ],
  156. ],
  157. 'markers' => [
  158. 'size' => 0,
  159. ],
  160. 'colors' => ['#d946ef', '#6d28d9', '#14b8a6', '#3b82f6'],
  161. 'fill' => [
  162. 'type' => 'gradient',
  163. 'gradient' => [
  164. 'shade' => 'dark',
  165. 'type' => 'vertical',
  166. 'shadeIntensity' => 0.5,
  167. 'gradientToColors' => ['#d946ef', '#6d28d9', '#14b8a6', '#0ea5e9'],
  168. 'inverseColors' => false,
  169. 'opacityFrom' => [0.85, 1, 1, 0.75],
  170. 'opacityTo' => [0.4, 0.85, 0.85, 1],
  171. 'stops' => [0, 20, 80, 100],
  172. ],
  173. ],
  174. 'stroke' => [
  175. 'width' => [2, 5, 5, 0],
  176. 'curve' => 'smooth',
  177. ],
  178. 'plotOptions' => [
  179. 'bar' => [
  180. 'borderRadius' => 5,
  181. 'borderRadiusApplication' => 'end',
  182. 'columnWidth' => '60%',
  183. ],
  184. ],
  185. ];
  186. }
  187. }