ソースを参照

add user and employee charts

3.x
Andrew Wallo 2年前
コミット
345752c9d8

+ 1
- 0
app/Filament/Pages/Employees.php ファイルの表示

@@ -25,6 +25,7 @@ class Employees extends Page
25 25
     protected function getHeaderWidgets(): array
26 26
     {
27 27
         return [
28
+            Widgets\CumulativeEmployeeData::class,
28 29
             Widgets\Employees::class,
29 30
         ];
30 31
     }

+ 1
- 0
app/Filament/Pages/Users.php ファイルの表示

@@ -25,6 +25,7 @@ class Users extends Page
25 25
     protected function getHeaderWidgets(): array
26 26
     {
27 27
         return [
28
+            Widgets\CumulativeUserData::class,
28 29
             Widgets\Users::class,
29 30
         ];
30 31
     }

+ 6
- 2
app/Filament/Pages/Widgets/CumulativeCompanyData.php ファイルの表示

@@ -68,7 +68,7 @@ class CumulativeCompanyData extends ApexChartWidget
68 68
             $year = substr($week, 0, 4);
69 69
             $weekNumber = substr($week, 4);
70 70
 
71
-            return now()->setISODate($year, $weekNumber)->format('Y-m-d');
71
+            return today()->setISODate($year, $weekNumber)->format('M d');
72 72
         });
73 73
 
74 74
         return [
@@ -98,8 +98,8 @@ class CumulativeCompanyData extends ApexChartWidget
98 98
                 ],
99 99
             ],
100 100
             'xaxis' => [
101
-                'type' => 'datetime',
102 101
                 'categories' => $labels,
102
+                'position' => 'bottom',
103 103
                 'labels' => [
104 104
                     'style' => [
105 105
                         'colors' => '#9ca3af',
@@ -119,6 +119,7 @@ class CumulativeCompanyData extends ApexChartWidget
119 119
                 ],
120 120
                 [
121 121
                     'seriesName' => 'New Companies',
122
+                    'decimalsInFloat' => 0,
122 123
                     'opposite' => true,
123 124
                     'labels' => [
124 125
                         'style' => [
@@ -129,6 +130,7 @@ class CumulativeCompanyData extends ApexChartWidget
129 130
                 ],
130 131
                 [
131 132
                     'seriesName' => 'Total Companies',
133
+                    'decimalsInFloat' => 0,
132 134
                     'opposite' => true,
133 135
                     'labels' => [
134 136
                         'style' => [
@@ -139,6 +141,8 @@ class CumulativeCompanyData extends ApexChartWidget
139 141
                 ],
140 142
             ],
141 143
             'legend' => [
144
+                'position' => 'top',
145
+                'horizontalAlign' => 'center',
142 146
                 'labels' => [
143 147
                     'colors' => '#9ca3af',
144 148
                     'fontWeight' => 600,

+ 179
- 0
app/Filament/Pages/Widgets/CumulativeEmployeeData.php ファイルの表示

@@ -0,0 +1,179 @@
1
+<?php
2
+
3
+namespace App\Filament\Pages\Widgets;
4
+
5
+use App\Models\Company;
6
+use App\Models\Employeeship;
7
+use App\Models\User;
8
+use Leandrocfe\FilamentApexCharts\Widgets\ApexChartWidget;
9
+
10
+class CumulativeEmployeeData extends ApexChartWidget
11
+{
12
+    protected int|string|array $columnSpan = [
13
+        'md' => 2,
14
+        'xl' => 3,
15
+    ];
16
+
17
+    /**
18
+     * Chart Id
19
+     *
20
+     * @var string
21
+     */
22
+    protected static string $chartId = 'cumulative-employee-data';
23
+
24
+    /**
25
+     * Widget Title
26
+     *
27
+     * @var string|null
28
+     */
29
+    protected static ?string $heading = 'Cumulative Employee Data';
30
+
31
+    protected function getOptions(): array
32
+    {
33
+        $startOfYear = today()->startOfYear();
34
+        $today = today();
35
+
36
+        // Company data
37
+        $employeeData = Employeeship::selectRaw("COUNT(*) as aggregate, role, YEARWEEK(created_at, 3) as week")
38
+            ->whereBetween('created_at', [$startOfYear, $today])
39
+            ->groupByRaw('week, role')
40
+            ->get();
41
+
42
+        $weeks = [];
43
+        for ($week = $startOfYear->copy(); $week->lte($today); $week->addWeek()) {
44
+            $weeks[$week->format('oW')] = 0;
45
+        }
46
+
47
+        $weeklyRoleData = collect($weeks)->mapWithKeys(static function ($value, $week) use ($employeeData) {
48
+            $editors = $employeeData->where('role', 'editor')->where('week', $week)->first();
49
+            $admins = $employeeData->where('role', 'admin')->where('week', $week)->first();
50
+
51
+            return [
52
+                $week => [
53
+                    'editors' => $editors ? $editors->aggregate : 0,
54
+                    'admins' => $admins ? $admins->aggregate : 0,
55
+                ]
56
+            ];
57
+        });
58
+
59
+        $cumulativeEditors = $weeklyRoleData->reduce(function ($carry, $value) {
60
+            $carry[] = ($carry ? end($carry) : 0) + $value['editors'];
61
+            return $carry;
62
+        }, []);
63
+
64
+        $cumulativeAdmins = $weeklyRoleData->reduce(function ($carry, $value) {
65
+            $carry[] = ($carry ? end($carry) : 0) + $value['admins'];
66
+            return $carry;
67
+        }, []);
68
+
69
+        $totalEmployees = [];
70
+        for ($i = 0; $i < count($cumulativeEditors); $i++) {
71
+            $totalEmployees[] = $cumulativeEditors[$i] + $cumulativeAdmins[$i];
72
+        }
73
+
74
+        $weeklyGrowthRate = [0];
75
+        for ($i = 1; $i < count($totalEmployees); $i++) {
76
+            $growth = (($totalEmployees[$i] - $totalEmployees[$i - 1]) / $totalEmployees[$i - 1]) * 100;
77
+            $weeklyGrowthRate[] = round($growth, 2);
78
+        }
79
+
80
+        $labels = collect($weeks)->keys()->map(static function ($week) {
81
+            $year = substr($week, 0, 4);
82
+            $weekNumber = substr($week, 4);
83
+
84
+            return today()->setISODate($year, $weekNumber)->format('M d');
85
+        });
86
+
87
+
88
+        return [
89
+            'chart' => [
90
+                'type' => 'line',
91
+                'height' => 350,
92
+                'stacked' => true,
93
+                'toolbar' => [
94
+                    'show' => false,
95
+                ],
96
+            ],
97
+            'series' => [
98
+                [
99
+                    'name' => 'Editors',
100
+                    'type' => 'bar',
101
+                    'data' => $cumulativeEditors,
102
+                ],
103
+                [
104
+                    'name' => 'Admins',
105
+                    'type' => 'bar',
106
+                    'data' => $cumulativeAdmins,
107
+                ],
108
+                [
109
+                    'name' => 'Weekly Growth Rate',
110
+                    'type' => 'area',
111
+                    'data' => $weeklyGrowthRate,
112
+                ],
113
+            ],
114
+            'stroke' => [
115
+                'width' => [0, 0, 2],
116
+                'curve' => 'smooth',
117
+            ],
118
+            'xaxis' => [
119
+                'categories' => $labels,
120
+                'position' => 'bottom',
121
+                'labels' => [
122
+                    'style' => [
123
+                        'colors' => '#9ca3af',
124
+                        'fontWeight' => 600,
125
+                    ],
126
+                ],
127
+            ],
128
+            'yaxis' => [
129
+                'labels' => [
130
+                    'style' => [
131
+                        'colors' => '#9ca3af',
132
+                        'fontWeight' => 600,
133
+                    ],
134
+                ],
135
+            ],
136
+            'legend' => [
137
+                'labels' => [
138
+                    'colors' => '#9ca3af',
139
+                    'fontWeight' => 600,
140
+                ],
141
+            ],
142
+            'colors' => ['#d946ef', '#6d28d9', '#3b82f6'],
143
+            'fill' => [
144
+                'type' => 'gradient',
145
+                'gradient' => [
146
+                    'shade' => 'dark',
147
+                    'type' => 'vertical',
148
+                    'shadeIntensity' => 0.2,
149
+                    'gradientToColors' => ['#ec4899', '#8b5cf6', '#0ea5e9'],
150
+                    'inverseColors' => true,
151
+                    'opacityFrom' => [0.85, 0.85, 0.85],
152
+                    'opacityTo' => [0.85, 0.85, 0.4],
153
+                    'stops' => [0, 100, 100],
154
+                ],
155
+            ],
156
+            'plotOptions' => [
157
+                'bar' => [
158
+                    'horizontal' => false,
159
+                    'borderRadius' => 5,
160
+                    'borderRadiusApplication' => 'end',
161
+                    'columnWidth' => '60%',
162
+                    'dataLabels' => [
163
+                        'total' => [
164
+                            'enabled' => true,
165
+                            'style' => [
166
+                                'color' => '#9ca3af',
167
+                                'fontSize' => '14px',
168
+                                'fontWeight' => 600,
169
+                            ],
170
+                        ]
171
+                    ],
172
+                ],
173
+            ],
174
+            'dataLabels' => [
175
+                'enabled' => false,
176
+            ],
177
+        ];
178
+    }
179
+}

+ 182
- 0
app/Filament/Pages/Widgets/CumulativeUserData.php ファイルの表示

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

+ 7
- 6
composer.lock ファイルの表示

@@ -8379,16 +8379,16 @@
8379 8379
         },
8380 8380
         {
8381 8381
             "name": "phpunit/php-file-iterator",
8382
-            "version": "4.0.1",
8382
+            "version": "4.0.2",
8383 8383
             "source": {
8384 8384
                 "type": "git",
8385 8385
                 "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
8386
-                "reference": "fd9329ab3368f59fe1fe808a189c51086bd4b6bd"
8386
+                "reference": "5647d65443818959172645e7ed999217360654b6"
8387 8387
             },
8388 8388
             "dist": {
8389 8389
                 "type": "zip",
8390
-                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/fd9329ab3368f59fe1fe808a189c51086bd4b6bd",
8391
-                "reference": "fd9329ab3368f59fe1fe808a189c51086bd4b6bd",
8390
+                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6",
8391
+                "reference": "5647d65443818959172645e7ed999217360654b6",
8392 8392
                 "shasum": ""
8393 8393
             },
8394 8394
             "require": {
@@ -8427,7 +8427,8 @@
8427 8427
             ],
8428 8428
             "support": {
8429 8429
                 "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
8430
-                "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.1"
8430
+                "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
8431
+                "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2"
8431 8432
             },
8432 8433
             "funding": [
8433 8434
                 {
@@ -8435,7 +8436,7 @@
8435 8436
                     "type": "github"
8436 8437
                 }
8437 8438
             ],
8438
-            "time": "2023-02-10T16:53:14+00:00"
8439
+            "time": "2023-05-07T09:13:23+00:00"
8439 8440
         },
8440 8441
         {
8441 8442
             "name": "phpunit/php-invoker",

読み込み中…
キャンセル
保存