From a6efc67883cc9170fbb3854b7b6478210d8031ee Mon Sep 17 00:00:00 2001 From: baghizadizn Date: Sat, 29 Nov 2025 11:53:46 +0700 Subject: [PATCH] penambahan nidn pada user yang sudah login dan notifikasi --- .../Auth/RegisteredUserController.php | 6 +- .../student/BecomeInstructorController.php | 153 ++++++++++++++++-- app/Notifications/InstructorApplicant.php | 58 +++++++ .../student/become_instructor/index.blade.php | 62 ++++++- .../notifications/instructor_applicant.php | 125 ++++++++++++++ 5 files changed, 381 insertions(+), 23 deletions(-) create mode 100644 app/Notifications/InstructorApplicant.php create mode 100644 resources/views/vendor/notifications/instructor_applicant.php diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php index 97a0d61..a87e9e8 100644 --- a/app/Http/Controllers/Auth/RegisteredUserController.php +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -121,6 +121,10 @@ class RegisteredUserController extends Controller // Log the user in after successful registration Auth::login($user); + + //send notification to user + $application = Application::max('id') + 1; + $user->notify(new \App\Notifications\InstructorApplicant($application)); return redirect(RouteServiceProvider::HOME); } catch (\Exception $e) { @@ -181,7 +185,7 @@ class RegisteredUserController extends Controller 'id_sdm' => $matched_dosen['id'] ?? null, 'id_sms' => $matched_dosen['nama_prodi'] ?? null, 'id_pt' => $matched_dosen['nama_pt'] ?? null, - 'status' => 0 + 'status' => 0 ]; Log::info('Instructor data to be saved:', $instructor); diff --git a/app/Http/Controllers/student/BecomeInstructorController.php b/app/Http/Controllers/student/BecomeInstructorController.php index 672e7d9..de82b18 100644 --- a/app/Http/Controllers/student/BecomeInstructorController.php +++ b/app/Http/Controllers/student/BecomeInstructorController.php @@ -5,10 +5,17 @@ namespace App\Http\Controllers\student; use App\Http\Controllers\Controller; use App\Models\Application; use App\Models\FileUploader; +use App\Models\Instructors; +use App\Models\User; use Illuminate\Http\Request; +use Illuminate\Http\RedirectResponse; +use App\Providers\RouteServiceProvider; use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Validator; use Illuminate\Support\Str; +use Illuminate\Support\Facades\Http; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\DB; class BecomeInstructorController extends Controller { @@ -20,40 +27,154 @@ class BecomeInstructorController extends Controller public function store(Request $request) { - // check application exists or not + // Check if application already exists if (Application::where('user_id', auth()->user()->id)->exists()) { Session::flash('error', get_phrase('Your request is in process. Please wait for admin to response.')); return redirect()->route('become.instructor'); } $rules = [ + 'nidn' => ['required', 'string', 'max:11'], 'phone' => 'required', - 'document' => 'required|file|mimes:doc,docx,pdf,txt,png,jpg,jpeg|max:5120', + 'document' => ['required', 'file', 'mimes:pdf,doc,docx', 'max:2048'], 'description' => 'required', ]; - // validate data - $validator = Validator::make($request->all(), $rules); + // Validate data + $validator = Validator::make($request->all(), $rules, [ + 'nidn.required' => get_phrase('NIDN is required'), + 'nidn.string' => get_phrase('NIDN must be a valid number'), + 'nidn.max' => get_phrase('NIDN may not be greater than 11 characters'), + 'phone.required' => get_phrase('Phone number is required'), + 'document.required' => get_phrase('Document is required'), + 'document.file' => get_phrase('Document must be a valid file'), + 'document.mimes' => get_phrase('Document must be PDF, DOC, or DOCX'), + 'document.max' => get_phrase('Document size must be less than 2MB'), + 'description.required' => get_phrase('Description is required'), + ]); + if ($validator->fails()) { + $firstError = $validator->errors()->first(); + Session::flash('error', $firstError); return redirect()->back()->withErrors($validator)->withInput(); } + $user = auth()->user(); - // process data - $application['user_id'] = auth()->user()->id; - $application['phone'] = $request->phone; - $application['description'] = $request->description; + try { + DB::beginTransaction(); - $doc = $request->document; - $application['document'] = 'uploads/applications/' . auth()->user()->id . Str::random(20) .'.'. $doc->extension(); + $result = $this->processInstructorApplication($request, $user); - // upload document - FileUploader::upload($doc, $application['document'], null, null, 300); + if ($result instanceof RedirectResponse && $result->getSession()->get('error')) { + DB::rollBack(); + return $result; + } - // store application - Application::insert($application); + DB::commit(); - Session::flash('success', get_phrase('Your application has been submitted.')); - return redirect()->back(); + // Get the latest application and send notification + $application = Application::max('id') + 1; + if ($application) { + $user->notify(new \App\Notifications\InstructorApplicant($application)); + } + + Session::flash('success', get_phrase('Your application has been submitted successfully.')); + return redirect(RouteServiceProvider::HOME); + + } catch (\Exception $e) { + DB::rollBack(); + Log::error('Instructor application error:', ['error' => $e->getMessage()]); + Session::flash('error', get_phrase('Error during application submission. Please try again.')); + return redirect()->back()->withInput(); + } + } + + private function processInstructorApplication(Request $request, User $user): RedirectResponse + { + // Check if application already exists (redundant but safe) + if (Application::where('user_id', $user->id)->exists()) { + Session::flash('error', get_phrase('Your request is in process. Please wait for admin to respond.')); + return redirect()->route('become.instructor'); + } + + // Check if NIDN already exists in Instructors table with status = 1 (active) + $nidn = $request->nidn; + $existingInstructor = Instructors::where('nidn', $nidn) + ->where('status', 1) + ->first(); + + if ($existingInstructor) { + Session::flash('error', get_phrase('This NIDN is already registered as an active instructor.')); + return redirect()->back()->withInput(); + } + + // Check NIDN with the API + $api_url = "https://sindig.unesa.ac.id/apipddikti/api?nidn={$nidn}&auto=1"; + + $response = Http::timeout(30)->get($api_url); + $data = $response->json(); + + Log::info('API Response for NIDN: ' . $nidn, ['response' => $data]); + + // Extract matched dosen data + $matched_dosen = $data['matched_dosen'][0]; + Log::info('Instructor data to be saved:', $matched_dosen); + + if (!isset($data['ok']) || !isset($data['matched_dosen']) || count($data['matched_dosen']) == 0) { + Session::flash('error', get_phrase('NIDN not found in the system. Please check your NIDN.')); + return redirect()->back()->withInput(); + } else if (strtolower($matched_dosen['nama']) != strtolower($user->name)) { + Session::flash('error', get_phrase('Name does not match PDDikti records. Please check your name.')); + return redirect()->back()->withInput(); + } + + // Upload document + $fileName = null; + if ($request->hasFile('document') && $request->file('document')->isValid()) { + $doc = $request->file('document'); + $fileName = 'uploads/applications/' . $user->id . Str::random(20) . '.' . $doc->getClientOriginalExtension(); + + $uploadResult = FileUploader::upload($doc, $fileName, null, null, 300); + + if (!$uploadResult) { + Session::flash('error', get_phrase('Document upload failed. Please try again.')); + return redirect()->back()->withInput(); + } + } else { + Session::flash('error', get_phrase('Document upload failed or no document selected.')); + return redirect()->back()->withInput(); + } + + // Prepare instructor data + $instructorData = [ + 'user_id' => $user->id, + 'nidn' => $nidn, + 'name' => $matched_dosen['nama'] ?? $user->name, + 'id_sdm' => $matched_dosen['id'] ?? null, + 'id_sms' => $matched_dosen['nama_prodi'] ?? null, + 'id_pt' => $matched_dosen['nama_pt'] ?? null, + 'status' => 0 + ]; + + Log::info('Instructor data to be saved:', $instructorData); + + // Prepare application data - INCLUDING DOCUMENT PATH + $applicationData = [ + 'user_id' => $user->id, + 'nidn' => $nidn, + 'phone' => $request->phone, + 'description' => $request->description, + 'document' => $fileName, + 'status' => 0 + ]; + + Log::info('Application data to be saved:', $applicationData); + + // Create both application and instructor records + Application::create($applicationData); + Instructors::create($instructorData); + + return redirect()->back(); // This return won't be used due to the try-catch structure } } diff --git a/app/Notifications/InstructorApplicant.php b/app/Notifications/InstructorApplicant.php new file mode 100644 index 0000000..57490b8 --- /dev/null +++ b/app/Notifications/InstructorApplicant.php @@ -0,0 +1,58 @@ +application = $application; + } + + /** + * Get the notification's delivery channels. + * + * @return array + */ + public function via(object $notifiable): array + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + */ + public function toMail(object $notifiable): MailMessage + { + return (new MailMessage) + ->subject(get_phrase('Instructor Application Approved') . ' - ' . config('app.name')) + ->view('vendor.notifications.instructor_applicant', [ + 'user' => $notifiable, + 'application' => $this->application + ]); + } + + /** + * Get the array representation of the notification. + * + * @return array + */ + public function toArray(object $notifiable): array + { + return [ + // + ]; + } +} diff --git a/resources/views/frontend/default/student/become_instructor/index.blade.php b/resources/views/frontend/default/student/become_instructor/index.blade.php index 8011d7a..a7fea64 100644 --- a/resources/views/frontend/default/student/become_instructor/index.blade.php +++ b/resources/views/frontend/default/student/become_instructor/index.blade.php @@ -17,21 +17,39 @@
- - + + + @error('nidn') + {{ $message }} + @enderror
- - - {{ get_phrase('Documents of qualification. Max-size : 5MB (DOC, DOCX, PDF, TXT, PNG, JPG, JPEG)') }} + + + @error('phone') + {{ $message }} + @enderror +
+
+
+
+ + + @error('document') + {{ $message }} + @enderror + {{ get_phrase('Provide some documents about your qualifications') }}
- + + @error('description') + {{ $message }} + @enderror
@@ -45,5 +63,37 @@ @endsection @push('js') + @endpush + diff --git a/resources/views/vendor/notifications/instructor_applicant.php b/resources/views/vendor/notifications/instructor_applicant.php new file mode 100644 index 0000000..ea2871c --- /dev/null +++ b/resources/views/vendor/notifications/instructor_applicant.php @@ -0,0 +1,125 @@ + + + + + + {{ get_phrase('Instructor Application Submitted') }} + + + + + +