diff --git a/.gitignore b/.gitignore index f0f1dea..d293627 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /public/node_modules /public/storage /public/js/helpers/* +/public/js/page/* /public/js/stisla/* /public/webfonts /storage/*.key diff --git a/app/Enum/Periodicity.php b/app/Enum/Periodicity.php new file mode 100644 index 0000000..ab482ee --- /dev/null +++ b/app/Enum/Periodicity.php @@ -0,0 +1,27 @@ + trans('Yearly'), + 'monthly' => trans('Monthly'), + 'weekly' => trans('Weekly'), + 'daily' => trans('Daily'), + ]; + } +} diff --git a/app/Http/Controllers/AchievementController.php b/app/Http/Controllers/AchievementController.php index c933357..2cd192d 100644 --- a/app/Http/Controllers/AchievementController.php +++ b/app/Http/Controllers/AchievementController.php @@ -2,11 +2,24 @@ namespace App\Http\Controllers; -use App\Models\Achievement; +use App\Http\Requests\Achievement\LaporanPencapaianNewCinChartRequest; +use App\Repositories\AchievementRepository; use Illuminate\Http\Request; class AchievementController extends Controller { + /** + * Create a new instance class. + * + * @param \App\Repositories\AchievementRepository $achievementRepository + * @return void + */ + public function __construct( + protected AchievementRepository $achievementRepository + ) { + // + } + /** * Display index page. * @@ -30,41 +43,18 @@ public function laporanPencapaianNewCin() /** * Return laporan pencapaian new cin chart data as json response. * + * @param \App\Http\Requests\Achievement\LaporanPencapaianNewCinChartRequest $request * @return \Illuminate\Http\JsonResponse */ - public function laporanPencapaianNewCinChart() + public function laporanPencapaianNewCinChart(LaporanPencapaianNewCinChartRequest $request) { - return response()->json([ - 'labels' => [ - 'Sunday', - 'Monday', - 'Tuesday', - 'Wednesday', - 'Thursday', - 'Friday', - 'Saturday', - ], - 'datasets' => [ - [ - 'label' => 'Jumlah New CiN', - 'data' => [460, 458, 330, 502, 430, 610, 488], - 'backgroundColor' => 'rgba(254,86,83,.7)', - 'borderColor' => 'rgba(254,86,83,.7)', - 'borderWidth' => 2.5, - 'pointBackgroundColor' => '#ffffff', - 'pointRadius' => 4, - ], - [ - 'label' => 'Target Bulanan', - 'data' => [550, 558, 390, 562, 490, 670, 538], - 'backgroundColor' => 'rgba(63,82,227,.8)', - 'borderColor' => 'transparent', - 'borderWidth' => 0, - 'pointBackgroundColor' => '#999999', - 'pointRadius' => 4, - ], - ], - ]); + $data = $this->achievementRepository->chartLaporanPencapaianNewCin( + $request->date('start_date'), + $request->date('end_date'), + $request->periodicity + ); + + return response()->json($data); } /** diff --git a/app/Http/Requests/Achievement/LaporanPencapaianNewCinChartRequest.php b/app/Http/Requests/Achievement/LaporanPencapaianNewCinChartRequest.php new file mode 100644 index 0000000..2748df3 --- /dev/null +++ b/app/Http/Requests/Achievement/LaporanPencapaianNewCinChartRequest.php @@ -0,0 +1,48 @@ +user()); + } + + /** + * {@inheritDoc} + */ + public function rules() + { + return [ + 'start_date' => ['required', 'date_format:Y-m-d H:i:s'], + 'end_date' => ['required', 'date_format:Y-m-d H:i:s'], + 'periodicity' => ['sometimes', 'nullable', new EnumRule(Periodicity::class)], + ]; + } + + /** + * List of transformed enum from request. + * + * @return array + */ + public function enums(): array + { + return [ + 'periodicity' => Periodicity::class, + ]; + } +} diff --git a/app/Repositories/AchievementRepository.php b/app/Repositories/AchievementRepository.php new file mode 100644 index 0000000..f569414 --- /dev/null +++ b/app/Repositories/AchievementRepository.php @@ -0,0 +1,47 @@ + $branches->pluck('name'), + 'datasets' => [ + [ + 'label' => trans('Number of New CiN'), + 'data' => $branches->map(fn (Branch $branch) => rand(1, 100)), + 'backgroundColor' => 'rgba(254,86,83,.7)', + 'borderColor' => 'rgba(254,86,83,.7)', + 'borderWidth' => 2.5, + 'pointBackgroundColor' => '#ffffff', + 'pointRadius' => 4, + ], + [ + 'label' => trans(':periodicity target', ['periodicity' => $periodicity->label]), + 'data' => $branches->map(fn (Branch $branch) => rand(1, 100)), + 'backgroundColor' => 'rgba(63,82,227,.8)', + 'borderColor' => 'transparent', + 'borderWidth' => 0, + 'pointBackgroundColor' => '#999999', + 'pointRadius' => 4, + ], + ], + ]; + } +} diff --git a/composer.json b/composer.json index 0183778..91c2621 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "laravel/framework": "^8.65", "laravel/sanctum": "^2.11", "laravel/tinker": "^2.5", + "spatie/laravel-enum": "^3.0", "spatie/laravel-permission": "^5.5", "yajra/laravel-datatables-fractal": "^1.6", "yajra/laravel-datatables-oracle": "~9.0" diff --git a/composer.lock b/composer.lock index c168942..d7c77e9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "15b0703cb2fc4607b2eda0deb8aea0dd", + "content-hash": "5d99c657c76e974d00ae99858587469a", "packages": [ { "name": "asm89/stack-cors", @@ -2916,6 +2916,174 @@ ], "time": "2021-09-25T23:10:38+00:00" }, + { + "name": "spatie/enum", + "version": "3.12.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/enum.git", + "reference": "c0180f1de7c5d06e4b84efbc751ea19167140173" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/enum/zipball/c0180f1de7c5d06e4b84efbc751ea19167140173", + "reference": "c0180f1de7c5d06e4b84efbc751ea19167140173", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "fakerphp/faker": "^1.9.1", + "larapack/dd": "^1.1", + "phpunit/phpunit": "^9.0", + "vimeo/psalm": "^4.3" + }, + "suggest": { + "fakerphp/faker": "To use the enum faker provider", + "phpunit/phpunit": "To use the enum assertions" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\Enum\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brent Roose", + "email": "brent@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Tom Witkowski", + "email": "dev@gummibeer.de", + "homepage": "https://gummibeer.de", + "role": "Developer" + } + ], + "description": "PHP Enums", + "homepage": "https://github.com/spatie/enum", + "keywords": [ + "enum", + "enumerable", + "spatie" + ], + "support": { + "docs": "https://docs.spatie.be/enum", + "issues": "https://github.com/spatie/enum/issues", + "source": "https://github.com/spatie/enum" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2022-02-05T09:44:52+00:00" + }, + { + "name": "spatie/laravel-enum", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-enum.git", + "reference": "b1bd1c1be50dfdccdefdd5a988d95b292d031d48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-enum/zipball/b1bd1c1be50dfdccdefdd5a988d95b292d031d48", + "reference": "b1bd1c1be50dfdccdefdd5a988d95b292d031d48", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^8.0 || ^9.0", + "illuminate/contracts": "^8.0 || ^9.0", + "illuminate/database": "^8.0 || ^9.0", + "illuminate/http": "^8.0 || ^9.0", + "illuminate/support": "^8.0 || ^9.0", + "php": "^7.4 || ^8.0", + "spatie/enum": "^3.9" + }, + "conflict": { + "bensampo/laravel-enum": "*" + }, + "require-dev": { + "fakerphp/faker": "^1.16", + "mockery/mockery": "^1.4.0", + "orchestra/testbench": "^6.0 || ^7.0", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.0" + }, + "suggest": { + "fzaninotto/faker": "^1.9.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Enum\\Laravel\\EnumServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Spatie\\Enum\\Laravel\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brent Roose", + "email": "brent@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + }, + { + "name": "Tom Witkowski", + "email": "dev@gummibeer.de", + "homepage": "https://gummibeer.de", + "role": "Developer" + } + ], + "description": "Laravel Enum support", + "homepage": "https://github.com/spatie/laravel-enum", + "keywords": [ + "enum", + "laravel", + "laravel-enum", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-enum/issues", + "source": "https://github.com/spatie/laravel-enum/tree/3.0.1" + }, + "funding": [ + { + "url": "https://spatie.be/open-source/support-us", + "type": "custom" + }, + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2022-02-05T09:53:41+00:00" + }, { "name": "spatie/laravel-permission", "version": "5.5.0", diff --git a/public/mix-manifest.json b/public/mix-manifest.json index e3fa1bd..a440e84 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -25,6 +25,7 @@ "/js/helpers/datatable-row-child.js": "/js/helpers/datatable-row-child.js", "/js/helpers/datatable.js": "/js/helpers/datatable.js", "/js/helpers/geolocation.js": "/js/helpers/geolocation.js", + "/js/page/achievement-laporan-pencapaian-new-cin.js": "/js/page/achievement-laporan-pencapaian-new-cin.js", "/node_modules/select2/dist/css/select2.min.css": "/node_modules/select2/dist/css/select2.min.css", "/node_modules/datatables.net-bs4/css/dataTables.bootstrap4.min.css": "/node_modules/datatables.net-bs4/css/dataTables.bootstrap4.min.css", "/node_modules/datatables.net-select-bs4/css/select.bootstrap4.min.css": "/node_modules/datatables.net-select-bs4/css/select.bootstrap4.min.css", diff --git a/resources/js/page/achievement-laporan-pencapaian-new-cin.js b/resources/js/page/achievement-laporan-pencapaian-new-cin.js new file mode 100644 index 0000000..084e3af --- /dev/null +++ b/resources/js/page/achievement-laporan-pencapaian-new-cin.js @@ -0,0 +1,133 @@ +let startDate = initialStartDate.clone().subtract(29, "days"); +let endDate = initialEndDate.clone(); +let periodicity = initialPeriodicity; + +function daterangeHandler(start, end) { + startDate = start; + endDate = end; + + const text = endDate.diff(startDate, "days") > 0 + ? `${start.format("DD MMMM YYYY")} - ${end.format("DD MMMM YYYY")}` + : start.format("DD MMMM YYYY"); + + $(".btn-daterange span").html(text); +} + +async function getChartLabelsAndDatasets(url) { + const response = await fetch(url, { + method: "POST", + headers: { + Accept: "application/json", + "Content-Type": "application/json", + "X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"), + }, + body: JSON.stringify({ + start_date: startDate.format("YYYY-MM-DD HH:mm:ss"), + end_date: endDate.format("YYYY-MM-DD HH:mm:ss"), + periodicity, + }), + }); + + if (!response.ok) { + const json = await response.json(); + + throw new Error(`[HTTP ${response.status}] ${json.message}`); + } + + return await response.json(); +} + +$(function() { + $(".btn-daterange").daterangepicker({ + ranges: daterangepickerRanges, + startDate, + endDate, + maxDate: moment(), + locale: { + applyLabel, + cancelLabel, + customRangeLabel, + }, + }, daterangeHandler); + + daterangeHandler(startDate, endDate); + + $(".btn-daterange").on("cancel.daterangepicker", function (ev, picker) { + startDate = null; + endDate = null; + + $(".btn-daterange span").html(customRangeLabel); + }); + + $(".periodicity-dropdown-item").on("click", function() { + const value = $(this).attr("data-value"); + const label = $(this).html(); + + periodicity = value !== '__reset' ? value : null; + + $(".periodicity-dropdown-item").removeClass("active"); + $(this).addClass("active"); + + $("#periodicity-dropdown-toggle").html(value !== '__reset' ? label : periodicityLabel); + }); + + const chartElement = document.getElementById("chart").getContext("2d"); + + let chart = new Chart(chartElement, { + type: "bar", + options: { + legend: { + display: false, + }, + scales: { + yAxes: [ + { + gridLines: { + drawBorder: false, + color: "#f2f2f2", + }, + ticks: { + beginAtZero: true, + stepSize: 150, + }, + }, + ], + xAxes: [ + { + gridLines: { + display: false, + }, + }, + ], + }, + elements: { + pointRadius: 4, + }, + }, + }); + + $("button#download-chart").on("click", function () { + const a = document.createElement("a"); + + a.href = chart.toBase64Image(); + a.download = `${moment().format("YYYY-MM-DD")}.png`; + + a.click(); + }); + + $("button#load-chart-data").on("click", async function () { + $(this).attr("disabled", "disabled").addClass("btn-progress"); + + try { + chart.data = await getChartLabelsAndDatasets($(this).attr("data-url")); + + chart.update(); + } catch (error) { + console.error(error); + + alert(error.message); + } + + $(this).removeAttr("disabled").removeClass("btn-progress"); + }); +}); diff --git a/resources/lang/id.json b/resources/lang/id.json index 015de9d..80d8fbb 100644 --- a/resources/lang/id.json +++ b/resources/lang/id.json @@ -802,5 +802,8 @@ "Last 30 Days": "30 Hari Terakhir", "This Month": "Bulan Ini", "Last Month": "Bulan Lalu", - "This Year": "Tahun Ini" + "This Year": "Tahun Ini", + "Periodicity": "Jangka Waktu", + ":periodicity target": "Target :periodicity", + "Number of New CiN": "Jumlah New CiN" } diff --git a/resources/views/achievement/laporan-pencapaian-new-cin.blade.php b/resources/views/achievement/laporan-pencapaian-new-cin.blade.php index 6b0c543..22962ab 100644 --- a/resources/views/achievement/laporan-pencapaian-new-cin.blade.php +++ b/resources/views/achievement/laporan-pencapaian-new-cin.blade.php @@ -8,128 +8,29 @@ + + @endsection @@ -168,46 +69,42 @@ function daterangeHandler(start, end) {
-
+
- -
-
-
- +
+ +
diff --git a/resources/views/auth/register.blade.php b/resources/views/auth/register.blade.php index 5293ec7..9e07595 100755 --- a/resources/views/auth/register.blade.php +++ b/resources/views/auth/register.blade.php @@ -10,7 +10,7 @@ - + - + @endsection @section('content') diff --git a/resources/views/master/user/form.blade.php b/resources/views/master/user/form.blade.php index b9879f2..aa53357 100644 --- a/resources/views/master/user/form.blade.php +++ b/resources/views/master/user/form.blade.php @@ -7,7 +7,7 @@ @section('script')