diff --git a/app/Http/Controllers/Api/ApplianceController.php b/app/Http/Controllers/Api/ApplianceController.php index a5d8d5f..9720e04 100644 --- a/app/Http/Controllers/Api/ApplianceController.php +++ b/app/Http/Controllers/Api/ApplianceController.php @@ -77,6 +77,12 @@ public function editDate(Request $request, $id) $startDate = Carbon::parse($request->start_date); $endDate = Carbon::parse($request->end_date); + if ($startDate->greaterThanOrEqualTo($endDate)) { + return response()->json([ + 'message' => 'The start date cannot be later than or equal to the end date.', + ], 400); + } + // Check if the start and end dates overlap with any other company's internship dates $overlapCheck = $user->internDates()->where('company_id', '!=', $id) ->where(function ($query) use ($startDate, $endDate) { diff --git a/app/Http/Controllers/Api/ExportController.php b/app/Http/Controllers/Api/ExportController.php index c644b12..c9b3464 100644 --- a/app/Http/Controllers/Api/ExportController.php +++ b/app/Http/Controllers/Api/ExportController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers\Api; // use ZipArchive; +use Barryvdh\DomPDF\Facade\Pdf as DomPdfFacade; use mikehaertl\pdftk\Pdf; use Carbon\Carbon; @@ -29,7 +30,7 @@ public function pdfSingleCompany(Request $request, $id) $companyId = $id; $company = $user->companies()->find($companyId); if (!$company) { - return response()->json(['error' => 'Company not found!'], 404); + return response()->json(['message' => 'Company not found!'], 404); } $internDate = $user->internDates()->where('company_id', $companyId)->first(); @@ -46,7 +47,7 @@ public function pdfSingleCompany(Request $request, $id) ->values(); if ($presences->isEmpty()) { - return response()->json(['error' => 'No presences found!'], 404); + return response()->json(['message' => 'No presences found!'], 404); } $journals = $user->journals() @@ -58,7 +59,7 @@ public function pdfSingleCompany(Request $request, $id) ->values(); if ($journals->isEmpty()) { - return response()->json(['error' => 'No journals found!'], 404); + return response()->json(['message' => 'No journals found!'], 404); } $parentAddress = $request->input('parent_address') ?? $user->address; @@ -70,8 +71,8 @@ public function pdfSingleCompany(Request $request, $id) $formFields = [ 'namasiswa' => $user->name, 'kelas' => $courseLevel, - 'nis' => $request->input('nis'), - 'nis_nisn' => $request->input('nis') . '/' . $request->input('nisn'), + 'nis' => $user->nis, + 'nis_nisn' => $user->nis . '/' . $request->input('nisn'), 'gol_darah' => $request->input('blood_type'), 'alamat_siswa' => $user->address, 'jurusan' => $user->departments->first()?->description, @@ -115,7 +116,7 @@ public function pdfSingleCompany(Request $request, $id) } if (!file_exists($templatePath)) { - return response()->json(['error' => 'PDF template not found!'], 404); + return response()->json(['message' => 'PDF template not found!'], 404); } $fileName = $user->id . time() . '.pdf'; @@ -125,7 +126,7 @@ public function pdfSingleCompany(Request $request, $id) $result = $pdf->fillForm($formFields)->flatten()->saveAs($outputPath); if (!$result) { $error = $pdf->getError(); - return response()->json(['error' => 'Failed to generate PDF: ' . $error], 500); + return response()->json(['message' => 'Failed to generate PDF: ' . $error], 500); } return response()->download($outputPath, $fileName)->deleteFileAfterSend(true); @@ -151,14 +152,14 @@ public function pdfMultipleCompany(Request $request) $companies = $user->companies; if ($companies->isEmpty()) { - return response()->json(['error' => 'No companies associated with the user!'], 404); + return response()->json(['message' => 'No companies associated with the user!'], 404); } $formFields = [ 'namasiswa' => $user->name, 'kelas' => $courseLevel, - 'nis' => $request->input('nis'), - 'nis_nisn' => $request->input('nis') . '/' . $request->input('nisn'), + 'nis' => $user->nis, + 'nis_nisn' => $user->nis . '/' . $request->input('nisn'), 'gol_darah' => $request->input('blood_type'), 'alamat_siswa' => $user->address, 'jurusan' => $user->departments->first()?->description, @@ -221,7 +222,7 @@ public function pdfMultipleCompany(Request $request) $templatePath = public_path('template-pdf/template_2-company.pdf'); if (!file_exists($templatePath)) { - return response()->json(['error' => 'PDF template not found!'], 404); + return response()->json(['message' => 'PDF template not found!'], 404); } $fileName = $user->id . time() . '.pdf'; @@ -231,10 +232,108 @@ public function pdfMultipleCompany(Request $request) $result = $pdf->fillForm($formFields)->flatten()->saveAs($outputPath); if (!$result) { $error = $pdf->getError(); - return response()->json(['error' => 'Failed to generate PDF: ' . $error], 500); + return response()->json(['message' => 'Failed to generate PDF: ' . $error], 500); } return response()->download($outputPath, $fileName)->deleteFileAfterSend(true); } - + public function exportCertificate(Request $request, $id) + { + $user = auth()->user(); + $company = $user->companies()->find($id); + + if (!$company) { + return response()->json(['message' => 'Company not found!'], 404); + } + + $internDate = $user->internDates()->where('company_id', $id)->first(); + $scores = $user->scores()->where('company_id', $id)->get(); + + if ($scores->isEmpty()) { + return response()->json(['message' => 'Scores not found! Call the mentor to add scores first!'], 400); + } + + $averageScore = $scores->avg('score') ?? 0; + // $technicalScore = $scores->where('type', 'teknis')->avg('score') ?? 0; + // $nonTechnicalScore = $scores->where('type', 'non-teknis')->avg('score') ?? 0; + + $formattedDateOfBirth = $user->date_of_birth + ? Carbon::parse($user->date_of_birth)->translatedFormat('j F Y') + : 'N/A'; + + $formFields = [ + 'nama_siswa' => $user->name, + 'ttl' => $formattedDateOfBirth, + 'nis' => $user->nis, + 'program_studi' => $user->departments->first()?->study_program, + 'jurusan' => $user->departments->first()?->description, + 'instansi_nama' => $company->name, + 'tgl_mulai' => $internDate ? Carbon::parse($internDate->start_date)->translatedFormat('j F Y') : 'N/A', + 'tgl_selesai' => $internDate ? Carbon::parse($internDate->end_date)->translatedFormat('j F Y') : 'N/A', + 'tgl_export' => Carbon::now()->translatedFormat('j F Y'), + 'instansi_direktur' => $company->contact_person, + 'nilai_all' => number_format($averageScore, 2), + ]; + + $templatePath = public_path('template-pdf/template_certificate_infront.pdf'); + + if (!file_exists($templatePath)) { + return response()->json(['message' => 'PDF template not found!'], 404); + } + + $fileName = $user->id . '_certificate_' . time() . '.pdf'; + $outputPathFront = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'front_' . $fileName; + $pdfFront = new Pdf($templatePath); + $resultFront = $pdfFront->fillForm($formFields)->flatten()->saveAs($outputPathFront); + + if (!$resultFront) { + return response()->json(['message' => 'Failed to generate front page PDF: ' . $pdfFront->getError()], 500); + } + + // Generate halaman belakang (back) dengan DomPDF + $technicalScores = $scores->where('type', 'teknis'); + $nonTechnicalScores = $scores->where('type', 'non-teknis'); + + foreach ($technicalScores as $score) { + $score->letter = $this->convertScoreToLetter($score->score); + } + foreach ($nonTechnicalScores as $score) { + $score->letter = $this->convertScoreToLetter($score->score); + } + + $pdfBack = DomPdfFacade::loadView('pdf.certificate_back', [ + 'technicalScores' => $technicalScores, + 'nonTechnicalScores' => $nonTechnicalScores, + 'avgScore' => number_format($averageScore, 2), + ])->setPaper('a4', 'landscape'); + + $outputPathBack = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'back_' . $fileName; + $pdfBack->save($outputPathBack); + + // Gabungkan PDF depan & belakang + $mergedPdfPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $fileName; + $pdf = new Pdf(); + $mergeResult = $pdf->addFile($outputPathFront) + ->addFile($outputPathBack) + ->saveAs($mergedPdfPath); + + if (!$mergeResult) { + return response()->json(['message' => 'Failed to merge PDF files: ' . $pdf->getError()], 500); + } + + return response()->download($mergedPdfPath, $fileName)->deleteFileAfterSend(true); + } + + private function convertScoreToLetter($score) + { + if ($score >= 90) { + return 'Sangat Baik'; + } elseif ($score >= 75) { + return 'Baik'; + } elseif ($score >= 60) { + return 'Cukup'; + } else { + return 'Kurang'; + } + } } diff --git a/app/Http/Controllers/Api/UserController.php b/app/Http/Controllers/Api/UserController.php index 1be8eda..3f5468d 100644 --- a/app/Http/Controllers/Api/UserController.php +++ b/app/Http/Controllers/Api/UserController.php @@ -81,6 +81,7 @@ public function update(Request $request) 'date_of_birth' => 'date', 'bio' => 'max:255', 'skills' => 'nullable', + 'nis' => 'required|string|unique:users,nis,' . $user->id, ]); $user->update($request->all()); diff --git a/app/Http/Controllers/DepartmentController.php b/app/Http/Controllers/DepartmentController.php index 44d1d1a..1272584 100644 --- a/app/Http/Controllers/DepartmentController.php +++ b/app/Http/Controllers/DepartmentController.php @@ -138,7 +138,8 @@ public function store(Request $request) 'name' => 'required|max:255', 'description' => 'nullable|max:255', 'logo' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048', - 'school_id' => 'required|exists:schools,id' + 'school_id' => 'required|exists:schools,id', + 'study_program' => 'nullable|string|max:255', ]); try { @@ -146,6 +147,7 @@ public function store(Request $request) 'name' => $request->name, 'description' => $request->description, 'school_id' => $request->school_id, + 'study_program' => $request->study_program ]); if ($request->hasFile('logo')) { @@ -213,6 +215,7 @@ public function update(Request $request, $id) 'name' => 'required|max:255', 'description' => 'nullable|max:255', 'logo' => 'nullable|image|mimes:jpeg,png,jpg,gif,svg|max:2048', + 'study_program' => 'nullable|string|max:255', ]); try { @@ -220,6 +223,7 @@ public function update(Request $request, $id) $department->update([ 'name' => $request->name, 'description' => $request->description, + 'study_program' => $request->study_program ]); if ($request->hasFile('logo')) { diff --git a/app/Http/Controllers/StudentController.php b/app/Http/Controllers/StudentController.php index dd84c27..9b55741 100644 --- a/app/Http/Controllers/StudentController.php +++ b/app/Http/Controllers/StudentController.php @@ -216,6 +216,7 @@ public function update(Request $request, $id) $request->validate([ 'name' => 'required|string|max:255', + 'nis' => 'required|string|unique:users,nis,' . $id, 'skills' => 'nullable|string', 'course_id' => 'required|exists:courses,id', 'companies.*.start_date' => 'nullable|date', @@ -232,6 +233,7 @@ public function update(Request $request, $id) $user->update([ 'name' => $request->name, 'skills' => $request->skills, + 'nis' => $request->nis ]); $user->courses()->sync($request->course_id); diff --git a/app/Models/Department.php b/app/Models/Department.php index 62e3911..ae27c6d 100644 --- a/app/Models/Department.php +++ b/app/Models/Department.php @@ -15,6 +15,7 @@ class Department extends Model 'logo', 'status', 'school_id', + 'study_program', ]; public function school() diff --git a/app/Models/User.php b/app/Models/User.php index f66719d..a779881 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -32,6 +32,7 @@ class User extends Authenticatable implements MustVerifyEmail 'date_of_birth', 'status', 'skills', + 'nis', 'resume', 'password_by_admin', 'last_login', diff --git a/composer.json b/composer.json index d20322f..65bd550 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,7 @@ "license": "MIT", "require": { "php": "^8.0.2", + "barryvdh/laravel-dompdf": "^3.1", "cviebrock/eloquent-sluggable": "^10.0", "guzzlehttp/guzzle": "^7.2", "laravel/fortify": "^1.14", diff --git a/composer.lock b/composer.lock index 9d04daa..9b288c9 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": "20003ba38720bb0f0b87ef46cf44787c", + "content-hash": "f0ae84b346491b6bf6b17ae98d5db35e", "packages": [ { "name": "bacon/bacon-qr-code", @@ -60,6 +60,83 @@ }, "time": "2024-04-18T11:16:25+00:00" }, + { + "name": "barryvdh/laravel-dompdf", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/barryvdh/laravel-dompdf.git", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "reference": "8e71b99fc53bb8eb77f316c3c452dd74ab7cb25d", + "shasum": "" + }, + "require": { + "dompdf/dompdf": "^3.0", + "illuminate/support": "^9|^10|^11|^12", + "php": "^8.1" + }, + "require-dev": { + "larastan/larastan": "^2.7|^3.0", + "orchestra/testbench": "^7|^8|^9|^10", + "phpro/grumphp": "^2.5", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf", + "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf" + }, + "providers": [ + "Barryvdh\\DomPDF\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Barryvdh\\DomPDF\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "A DOMPDF Wrapper for Laravel", + "keywords": [ + "dompdf", + "laravel", + "pdf" + ], + "support": { + "issues": "https://github.com/barryvdh/laravel-dompdf/issues", + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.1" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2025-02-13T15:07:54+00:00" + }, { "name": "brick/math", "version": "0.12.1", @@ -709,6 +786,161 @@ ], "time": "2024-02-05T11:56:58+00:00" }, + { + "name": "dompdf/dompdf", + "version": "v3.1.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "a51bd7a063a65499446919286fb18b518177155a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/a51bd7a063a65499446919286fb18b518177155a", + "reference": "a51bd7a063a65499446919286fb18b518177155a", + "shasum": "" + }, + "require": { + "dompdf/php-font-lib": "^1.0.0", + "dompdf/php-svg-lib": "^1.0.0", + "ext-dom": "*", + "ext-mbstring": "*", + "masterminds/html5": "^2.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ext-gd": "*", + "ext-json": "*", + "ext-zip": "*", + "mockery/mockery": "^1.3", + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11", + "squizlabs/php_codesniffer": "^3.5", + "symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0" + }, + "suggest": { + "ext-gd": "Needed to process images", + "ext-gmagick": "Improves image processing performance", + "ext-imagick": "Improves image processing performance", + "ext-zlib": "Needed for pdf stream compression" + }, + "type": "library", + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "The Dompdf Community", + "homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "support": { + "issues": "https://github.com/dompdf/dompdf/issues", + "source": "https://github.com/dompdf/dompdf/tree/v3.1.0" + }, + "time": "2025-01-15T14:09:04+00:00" + }, + { + "name": "dompdf/php-font-lib", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-font-lib.git", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "reference": "6137b7d4232b7f16c882c75e4ca3991dbcf6fe2d", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "The FontLib Community", + "homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/dompdf/php-font-lib", + "support": { + "issues": "https://github.com/dompdf/php-font-lib/issues", + "source": "https://github.com/dompdf/php-font-lib/tree/1.0.1" + }, + "time": "2024-12-02T14:37:59+00:00" + }, + { + "name": "dompdf/php-svg-lib", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/dompdf/php-svg-lib.git", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "reference": "eb045e518185298eb6ff8d80d0d0c6b17aecd9af", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": "^7.1 || ^8.0", + "sabberworm/php-css-parser": "^8.4" + }, + "require-dev": { + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Svg\\": "src/Svg" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0-or-later" + ], + "authors": [ + { + "name": "The SvgLib Community", + "homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/dompdf/php-svg-lib", + "support": { + "issues": "https://github.com/dompdf/php-svg-lib/issues", + "source": "https://github.com/dompdf/php-svg-lib/tree/1.0.0" + }, + "time": "2024-04-29T13:26:35+00:00" + }, { "name": "dragonmantank/cron-expression", "version": "v3.3.3", @@ -2683,6 +2915,73 @@ }, "time": "2022-12-02T22:17:43+00:00" }, + { + "name": "masterminds/html5", + "version": "2.9.0", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" + }, + "time": "2024-03-31T07:05:07+00:00" + }, { "name": "meilisearch/meilisearch-php", "version": "v1.10.0", @@ -4571,6 +4870,71 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "sabberworm/php-css-parser", + "version": "v8.7.0", + "source": { + "type": "git", + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "f414ff953002a9b18e3a116f5e462c56f21237cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/f414ff953002a9b18e3a116f5e462c56f21237cf", + "reference": "f414ff953002a9b18e3a116f5e462c56f21237cf", + "shasum": "" + }, + "require": { + "ext-iconv": "*", + "php": "^5.6.20 || ^7.0.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" + }, + "require-dev": { + "phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.40" + }, + "suggest": { + "ext-mbstring": "for parsing UTF-8 CSS" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Sabberworm\\CSS\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "support": { + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.7.0" + }, + "time": "2024-10-27T17:38:32+00:00" + }, { "name": "spatie/laravel-permission", "version": "5.11.1", @@ -9822,12 +10186,12 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.0.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/database/migrations/2025_02_23_152615_add_study_program_to_departments_table.php b/database/migrations/2025_02_23_152615_add_study_program_to_departments_table.php new file mode 100644 index 0000000..1c4336a --- /dev/null +++ b/database/migrations/2025_02_23_152615_add_study_program_to_departments_table.php @@ -0,0 +1,28 @@ +string('study_program')->nullable(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('departments', function (Blueprint $table) { + $table->dropColumn('study_program'); + }); + } +}; diff --git a/database/migrations/2025_02_23_152744_add_nis_to_users_table.php b/database/migrations/2025_02_23_152744_add_nis_to_users_table.php new file mode 100644 index 0000000..de5ee66 --- /dev/null +++ b/database/migrations/2025_02_23_152744_add_nis_to_users_table.php @@ -0,0 +1,28 @@ +string('nis')->unique()->nullable()->after('skills'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('nis'); + }); + } +}; diff --git a/public/template-pdf/template_2-company.pdf b/public/template-pdf/template_2-company.pdf index b73ed10..a2b37ff 100644 Binary files a/public/template-pdf/template_2-company.pdf and b/public/template-pdf/template_2-company.pdf differ diff --git a/public/template-pdf/template_3_month.pdf b/public/template-pdf/template_3_month.pdf index fc6ed6e..bd6bdd0 100644 Binary files a/public/template-pdf/template_3_month.pdf and b/public/template-pdf/template_3_month.pdf differ diff --git a/public/template-pdf/template_6_month.pdf b/public/template-pdf/template_6_month.pdf index aca27eb..033cbb2 100644 Binary files a/public/template-pdf/template_6_month.pdf and b/public/template-pdf/template_6_month.pdf differ diff --git a/public/template-pdf/template_certificate_infront.pdf b/public/template-pdf/template_certificate_infront.pdf new file mode 100644 index 0000000..73c6998 Binary files /dev/null and b/public/template-pdf/template_certificate_infront.pdf differ diff --git a/resources/views/departments/create.blade.php b/resources/views/departments/create.blade.php index 7e0a90c..3f39c10 100644 --- a/resources/views/departments/create.blade.php +++ b/resources/views/departments/create.blade.php @@ -1,11 +1,12 @@ @extends('layouts.dashboard') @section('dashboard-content') - - - - - - - -@endsection + + + + + + + + +@endsection \ No newline at end of file diff --git a/resources/views/departments/edit.blade.php b/resources/views/departments/edit.blade.php index f59aff2..e9471ed 100644 --- a/resources/views/departments/edit.blade.php +++ b/resources/views/departments/edit.blade.php @@ -1,12 +1,13 @@ @extends('layouts.dashboard') @section('dashboard-content') - - - - - - - -@endsection + + + + + + + + +@endsection \ No newline at end of file diff --git a/resources/views/pdf/certificate_back.blade.php b/resources/views/pdf/certificate_back.blade.php new file mode 100644 index 0000000..78f1cf6 --- /dev/null +++ b/resources/views/pdf/certificate_back.blade.php @@ -0,0 +1,128 @@ + + + + + + + Daftar Nilai + + + + +

DAFTAR NILAI
PRAKTIK KERJA LAPANGAN (PKL) / MAGANG TAHUN PELAJARAN 2024/2025

+ +

A. ASPEK TEKNIS

+ + + + + + + + + + + @foreach ($technicalScores as $index => $score) + + + + + + + @endforeach +
No.KemampuanNilai
AngkaHuruf
{{ $loop->iteration }}{{ $score->name }}{{ $score->score }}{{ $score->letter }}
+ +

B. ASPEK NONTEKNIS

+ + + + + + + + + + + @foreach ($nonTechnicalScores as $index => $score) + + + + + + + @endforeach + + + + +
No.KemampuanNilai
AngkaHuruf
{{ $loop->iteration }}{{ $score->name }}{{ $score->score }}{{ $score->letter }}
Jumlah Nilai Rata-Rata{{ $avgScore }}
+ +

+ Keterangan:
+ Sangat Baik: 90 - 100
+ Baik: 75 - 89
+ Cukup: 60 - 74
+ Kurang: < 59 +

+ + + + \ No newline at end of file diff --git a/resources/views/students/edit.blade.php b/resources/views/students/edit.blade.php index cb948c8..75fe33d 100644 --- a/resources/views/students/edit.blade.php +++ b/resources/views/students/edit.blade.php @@ -1,46 +1,50 @@ @extends('layouts.dashboard') @section('dashboard-content') - - @error(['name', 'course_id', 'skills', 'company', 'start_date', 'end_date', 'extend']) -
{{ $message }}
- @enderror - - @if (auth()->user()->can('user-edit')) - - - - - @foreach ($courses as $key => $value) - - @endforeach - - - - @else - - - - - @foreach ($courses as $key => $value) - - @endforeach - - - - @endif -
+ + @error(['name', 'course_id', 'skills', 'company', 'start_date', 'end_date', 'extend']) +
{{ $message }}
+ @enderror + + @if (auth()->user()->can('user-edit')) + + + + + + @foreach ($courses as $key => $value) + + @endforeach + + + + @else + + + + + @foreach ($courses as $key => $value) + + @endforeach + + + + @endif +
@foreach ($companiesData as $company)
@@ -66,6 +70,6 @@
@endforeach
-
-
-@endsection + + +@endsection \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index 3f05d43..c5e2d29 100644 --- a/routes/api.php +++ b/routes/api.php @@ -66,6 +66,7 @@ Route::post('export-journal/{id}', [ExportController::class, 'pdfSingleCompany']); Route::post('export-journals', [ExportController::class, 'pdfMultipleCompany']); + Route::post('export-certificate/{id}', [ExportController::class, 'exportCertificate']); Route::get('/today-activities', [PresenceController::class, 'todayActivity']); Route::resource('presences', PresenceController::class)->except(['create', 'edit']);