diff --git a/.env.example b/.env.example index 9f27c8b..0418d68 100644 --- a/.env.example +++ b/.env.example @@ -2,18 +2,18 @@ APP_NAME="Help Desk" APP_ENV=local APP_KEY=base64:l6QSYbX2+PeHu73W376Ijo2QbyeMIIOa6/vg60A7uGY= APP_DEBUG=true -APP_URL=http://localhost +APP_URL=172.0.0.1 LOG_CHANNEL=stack LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=mysql -DB_HOST=mysql +DB_HOST=localhost DB_PORT=3306 DB_DATABASE=help_desk -DB_USERNAME=sail -DB_PASSWORD=password +DB_USERNAME=root +DB_PASSWORD= BROADCAST_DRIVER=log CACHE_DRIVER=file @@ -29,13 +29,13 @@ REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=smtp -MAIL_HOST=mailhog -MAIL_PORT=1025 -MAIL_USERNAME=null -MAIL_PASSWORD=null -MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="hello@example.com" -MAIL_FROM_NAME="${APP_NAME}" +MAIL_HOST=mail.myipo.gov.my +MAIL_PORT=587 +MAIL_USERNAME=ict@myipo.gov.my +MAIL_PASSWORD=MyIPO@@2024 +MAIL_ENCRYPTION=tls +MAIL_FROM_ADDRESS="ict@myipo.gov.my" +MAIL_FROM_NAME="Helpdesk MyIPO" AWS_ACCESS_KEY_ID= AWS_SECRET_ACCESS_KEY= diff --git a/app/Class/SendDigestNotifications.php b/app/Class/SendDigestNotifications.php new file mode 100644 index 0000000..bacccb3 --- /dev/null +++ b/app/Class/SendDigestNotifications.php @@ -0,0 +1,56 @@ +unreadNotifications; // Get unread notifications + $temp = $notifications; + // Aggregate notifications based on your criteria + $groupedNotifications = $notifications->groupBy(function ($notification) { + return $notification->type; + }); + + foreach ($groupedNotifications as $type => $temp) { + if($temp->first()->type == "App\\Notifications\\SummaryNotification"){ + continue; + } + // // Create a summary notification for each group + $summary = $this->createSummary($temp); + + // // // Send the summary notification + $user->notify(new SummaryNotification($summary)); + + // // // Mark the individual notifications as read + } + foreach ($user->unreadNotifications as $notification) { + if($notification->type != "App\\Notifications\\SummaryNotification"){ + $notification->delete(); + } + } + } + + } + + protected function createSummary($notifications) + { + // Logic to create a summary from a group of notifications + $summary = [ + 'count' => $notifications->count(), + 'type' => $notifications->first()->type, + 'messages' => $notifications->pluck('data')->toArray(), // Assuming 'message' is an attribute in notification data + ]; + + return $summary; + } +} \ No newline at end of file diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d8bc1d2..b8359ed 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -4,6 +4,7 @@ use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; +use App\Class\SendDigestNotifications; class Kernel extends ConsoleKernel { @@ -15,7 +16,7 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - // $schedule->command('inspire')->hourly(); + $schedule->call(new SendDigestNotifications)->everyFiveMinute(); } /** @@ -29,4 +30,14 @@ protected function commands() require base_path('routes/console.php'); } + + /** + * Get the timezone that should be used by default for scheduled events. + * + * @return \DateTimeZone|string|null + */ + protected function scheduleTimezone() + { + return 'Asia/Kuala_Lumpur'; + } } diff --git a/app/Core/LogsActivity.php b/app/Core/LogsActivity.php index 09a2af1..44df36e 100644 --- a/app/Core/LogsActivity.php +++ b/app/Core/LogsActivity.php @@ -5,6 +5,7 @@ use Illuminate\Support\HtmlString; use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\Traits\LogsActivity as BaseLogsActivity; +use App\Models\User; trait LogsActivity { @@ -20,7 +21,45 @@ public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() ->logOnly($this->getFillable()) - ->setDescriptionForEvent(fn(string $eventName) => new HtmlString( + ->setDescriptionForEvent(function(string $eventName) { + + + // Define attributes to exclude from the change log + $excludedAttributes = ['updated_at', 'created_at', 'deleted_at']; + + + // Get changes and original values + $changes = array_diff_key($this->getDirty(), array_flip($excludedAttributes)); + $originals = array_diff_key($this->getOriginal(), array_flip($excludedAttributes)); + + + // Generate changes description + $changesDescription = ''; + foreach ($changes as $key => $value) { + $originalValue = $originals[$key] ?? 'null'; + if($key=="responsible_id") + { + // Fetch the responsible user based on the current responsible_id + $responsibleUserOld = User::withTrashed()->find($originalValue); + + // Get the responsible user's name if available + $responsibleUserNameOld = $responsibleUserOld ? $responsibleUserOld->name : 'None'; + + // Fetch the responsible user based on the current responsible_id + $responsibleUserNew = User::withTrashed()->find($value); + + // Get the responsible user's name if available + $responsibleUserNameNew = $responsibleUserNew ? $responsibleUserNew->name : 'Unknown User'; + $changesDescription .= "Responsible: {$responsibleUserNameOld} to {$responsibleUserNameNew} "; + continue; + } + $changesDescription .= "{$key}: '{$originalValue}' => '{$value}' "; + } + if($eventName == "created"){ + $changesDescription = "" ; + } + // Generate the description + return new HtmlString( '
'.$faker->paragraph(2).'
', + 'status' => $randomStatus, + 'priority' => $randompriority, + 'owner_id' => $randomOwner_id, + 'responsible_id' => $randomResponsible_id, + 'type' => $randomType, + 'number' => $number_strings[$i], + 'category' => $randomCategoryKey, + 'subcategory' => $randomSubcategoryKey, + 'issue' => $randomIssue, + 'created_at' => $formattedCreatedDate, + 'inprogress_at' => $formattedUpdatedDate, + 'closed_at' => $formattedClosedDate, + 'updated_at' => new \DateTime, + ) + ); + } + + + // Select a random string value + + + // DB::table('tickets')->insert( + // array( + // 'title' => 'Mouse rosak', + // 'content' => 'Tikus ni asyik lari je
', + // 'status' => 'resolved', + // 'priority' => 'low', + // 'owner_id' => 4, + // 'responsible_id' => 2, + // 'type' => 'Service Request', + // 'number' => '0000', + // 'category' => 'hardware', + // 'subcategory' => 'pc', + // 'created_at' => $formattedDate1, + // 'updated_at' => new \DateTime, + // ) + // ); + + } +} diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php new file mode 100644 index 0000000..5daf522 --- /dev/null +++ b/database/seeders/UserSeeder.php @@ -0,0 +1,109 @@ +insert( + array( + 'name' => 'administrator', + 'email' => 'admin@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'Head of Department', + 'email' => 'hod@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'technician', + 'email' => 'tech@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'technician 2', + 'email' => 'tech2@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'Asraf', + 'email' => 'asraf.educ.it@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'Syariff Ghani', + 'email' => 'syariffghani@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'Nurul Khaliesah', + 'email' => 'khaliesah@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'Haikal Handali', + 'email' => 'haikal@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + + DB::table('users')->insert( + array( + 'name' => 'Hazmie Khalid', + 'email' => 'hazmie@gmail.com', + 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', + 'created_at' => new \DateTime, + 'updated_at' => new \DateTime, + ) + ); + } +} diff --git a/docs/_media/favicon.ico b/docs/_media/favicon.ico index 87f78d0..014d296 100644 Binary files a/docs/_media/favicon.ico and b/docs/_media/favicon.ico differ diff --git a/package-lock.json b/package-lock.json index 2bf6f1b..1166f1f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,8 +4,10 @@ "requires": true, "packages": { "": { + "name": "help-desk", "dependencies": { "@fortawesome/fontawesome-free": "^6.2.0", + "chart.js": "^4.4.3", "flowbite": "^1.5.3", "jquery": "^3.6.1", "magnific-popup": "^1.1.0", @@ -87,6 +89,11 @@ "node": ">=6" } }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -290,11 +297,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -353,6 +360,17 @@ } ] }, + "node_modules/chart.js": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", + "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "dependencies": { + "@kurkle/color": "^0.3.0" + }, + "engines": { + "pnpm": ">=8" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -851,9 +869,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -880,9 +898,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true, "funding": [ { @@ -1142,10 +1160,16 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1192,9 +1216,9 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "node_modules/picomatch": { @@ -1218,9 +1242,9 @@ } }, "node_modules/postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", "dev": true, "funding": [ { @@ -1230,12 +1254,16 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -1424,9 +1452,9 @@ } }, "node_modules/rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -1478,9 +1506,9 @@ } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "engines": { "node": ">=0.10.0" } @@ -1607,15 +1635,15 @@ "dev": true }, "node_modules/vite": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.3.tgz", - "integrity": "sha512-/3XWiktaopByM5bd8dqvHxRt5EEgRikevnnrpND0gRfNkrMrPaGGexhtLCzv15RcCMtV2CLw+BPas8YFeSG0KA==", + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.10.tgz", + "integrity": "sha512-Dx3olBo/ODNiMVk/cA5Yft9Ws+snLOXrhLtrI3F4XLt4syz2Yg8fayZMWScPKoz12v5BUv7VEmQHnsfpY80fYw==", "dev": true, "dependencies": { - "esbuild": "^0.15.6", - "postcss": "^8.4.16", + "esbuild": "^0.15.9", + "postcss": "^8.4.18", "resolve": "^1.22.1", - "rollup": "~2.78.0" + "rollup": "^2.79.1" }, "bin": { "vite": "bin/vite.js" @@ -1627,12 +1655,17 @@ "fsevents": "~2.3.2" }, "peerDependencies": { + "@types/node": ">= 14", "less": "*", "sass": "*", "stylus": "*", + "sugarss": "*", "terser": "^5.4.0" }, "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, "less": { "optional": true }, @@ -1642,6 +1675,9 @@ "stylus": { "optional": true }, + "sugarss": { + "optional": true + }, "terser": { "optional": true } @@ -1714,6 +1750,11 @@ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz", "integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ==" }, + "@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1864,11 +1905,11 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "requires": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" } }, "browserslist": { @@ -1895,6 +1936,14 @@ "integrity": "sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ==", "dev": true }, + "chart.js": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.3.tgz", + "integrity": "sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==", + "requires": { + "@kurkle/color": "^0.3.0" + } + }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2171,9 +2220,9 @@ } }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "requires": { "to-regex-range": "^5.0.1" } @@ -2197,9 +2246,9 @@ } }, "follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", "dev": true }, "form-data": { @@ -2380,9 +2429,9 @@ "dev": true }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true }, "node-releases": { @@ -2415,9 +2464,9 @@ "dev": true }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", "dev": true }, "picomatch": { @@ -2432,14 +2481,14 @@ "dev": true }, "postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz", + "integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==", "dev": true, "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.7", + "picocolors": "^1.0.1", + "source-map-js": "^1.2.0" } }, "postcss-import": { @@ -2544,9 +2593,9 @@ "dev": true }, "rollup": { - "version": "2.78.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.78.1.tgz", - "integrity": "sha512-VeeCgtGi4P+o9hIg+xz4qQpRl6R401LWEXBmxYKOV4zlF82lyhgh2hTZnheFUbANE8l2A41F458iwj2vEYaXJg==", + "version": "2.79.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", + "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -2572,9 +2621,9 @@ } }, "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==" }, "supports-preserve-symlinks-flag": { "version": "1.0.0", @@ -2662,16 +2711,16 @@ "dev": true }, "vite": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.1.3.tgz", - "integrity": "sha512-/3XWiktaopByM5bd8dqvHxRt5EEgRikevnnrpND0gRfNkrMrPaGGexhtLCzv15RcCMtV2CLw+BPas8YFeSG0KA==", + "version": "3.2.10", + "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.10.tgz", + "integrity": "sha512-Dx3olBo/ODNiMVk/cA5Yft9Ws+snLOXrhLtrI3F4XLt4syz2Yg8fayZMWScPKoz12v5BUv7VEmQHnsfpY80fYw==", "dev": true, "requires": { - "esbuild": "^0.15.6", + "esbuild": "^0.15.9", "fsevents": "~2.3.2", - "postcss": "^8.4.16", + "postcss": "^8.4.18", "resolve": "^1.22.1", - "rollup": "~2.78.0" + "rollup": "^2.79.1" } }, "vite-plugin-full-reload": { diff --git a/package.json b/package.json index 8e28e30..9f9a790 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ }, "dependencies": { "@fortawesome/fontawesome-free": "^6.2.0", + "chart.js": "^4.4.3", "flowbite": "^1.5.3", "jquery": "^3.6.1", "magnific-popup": "^1.1.0", diff --git a/public/favicon.ico b/public/favicon.ico index 87f78d0..014d296 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/images/logo.png b/public/images/logo.png deleted file mode 100644 index dcd3117..0000000 Binary files a/public/images/logo.png and /dev/null differ diff --git a/public/images/logos.png b/public/images/logos.png new file mode 100644 index 0000000..9b7ae6b Binary files /dev/null and b/public/images/logos.png differ diff --git a/public/js/chart.min.js b/public/js/chart.min.js index 8f69759..707583f 100644 --- a/public/js/chart.min.js +++ b/public/js/chart.min.js @@ -1,13 +1,14 @@ +/** + * Minified by jsDelivr using Terser v5.19.2. + * Original file: /npm/chart.js@4.4.3/dist/chart.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ /*! - * Chart.js v3.9.1 + * Chart.js v4.4.3 * https://www.chartjs.org - * (c) 2022 Chart.js Contributors + * (c) 2024 Chart.js Contributors * Released under the MIT License */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";function t(){}const e=function(){let t=0;return function(){return t++}}();function i(t){return null==t}function s(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.slice(0,7)&&"Array]"===e.slice(-6)}function n(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const o=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function a(t,e){return o(t)?t:e}function r(t,e){return void 0===t?e:t}const l=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,h=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function c(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function d(t,e,i,o){let a,r,l;if(s(t))if(r=t.length,o)for(a=r-1;a>=0;a--)e.call(i,t[a],a);else for(a=0;a