From f467550d8deb5a1987988a05c464082abb62c9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Reh=C3=A1kov=C3=A1?= <125893846+sofiarehakova@users.noreply.github.com> Date: Mon, 3 Nov 2025 16:01:18 +0100 Subject: [PATCH 01/19] dokumenty admin --- .../dashboard/admin/internships/edit/[id].vue | 119 +++++++++++++++++- 1 file changed, 117 insertions(+), 2 deletions(-) diff --git a/frontend/app/pages/dashboard/admin/internships/edit/[id].vue b/frontend/app/pages/dashboard/admin/internships/edit/[id].vue index 11a5f93..0c15a7d 100644 --- a/frontend/app/pages/dashboard/admin/internships/edit/[id].vue +++ b/frontend/app/pages/dashboard/admin/internships/edit/[id].vue @@ -42,6 +42,36 @@ async function handleUpdateOfBasicInfo(internship: NewInternship) { } const { data, error, refresh } = await useSanctumFetch(`/api/internships/${route.params.id}`); + +// ---- helpery pre sekciu Dokumenty ---- +const docs = computed(() => { + const d: any = data.value ?? {} + return { + contract: d.documents?.contract ?? d.contract ?? null, + report: d.documents?.report ?? d.report ?? null, + } +}) + +function docUrl(doc: any) { + return doc?.url ?? doc?.download_url ?? doc?.link ?? null +} +function docName(doc: any) { + return doc?.fileName ?? doc?.filename ?? doc?.name ?? 'dokument.pdf' +} +function docSize(doc: any) { + const bytes = doc?.size ?? doc?.filesize ?? null + if (!bytes && bytes !== 0) return null + if (bytes < 1024) return `${bytes} B` + if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB` + return `${(bytes / (1024 * 1024)).toFixed(1)} MB` +} +function docDate(doc: any) { + const dt = doc?.uploadedAt ?? doc?.created_at ?? doc?.uploaded_at ?? null + return dt ? new Date(dt).toLocaleString() : null +} +function docBy(doc: any) { + return doc?.uploadedBy?.name ?? doc?.uploaded_by?.name ?? doc?.uploaded_by ?? null +} + + \ No newline at end of file From 797915d597a09aa9815f0b4f07a1ed899c413911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Reh=C3=A1kov=C3=A1?= <125893846+sofiarehakova@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:22:49 +0100 Subject: [PATCH 04/19] =?UTF-8?q?edit=20company=20str=C3=A1nky?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/app/pages/dashboard/company.vue | 367 ------------------ .../app/pages/dashboard/company/index.vue | 43 ++ 2 files changed, 43 insertions(+), 367 deletions(-) delete mode 100644 frontend/app/pages/dashboard/company.vue create mode 100644 frontend/app/pages/dashboard/company/index.vue diff --git a/frontend/app/pages/dashboard/company.vue b/frontend/app/pages/dashboard/company.vue deleted file mode 100644 index 5811343..0000000 --- a/frontend/app/pages/dashboard/company.vue +++ /dev/null @@ -1,367 +0,0 @@ - - - - - \ No newline at end of file diff --git a/frontend/app/pages/dashboard/company/index.vue b/frontend/app/pages/dashboard/company/index.vue new file mode 100644 index 0000000..6f2d8e2 --- /dev/null +++ b/frontend/app/pages/dashboard/company/index.vue @@ -0,0 +1,43 @@ + + + + + \ No newline at end of file From 3e1783f7333206476848739e68ef333c4b9e123e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Reh=C3=A1kov=C3=A1?= <125893846+sofiarehakova@users.noreply.github.com> Date: Mon, 3 Nov 2025 17:23:08 +0100 Subject: [PATCH 05/19] =?UTF-8?q?vytvorenie=20internship=20podstr=C3=A1nky?= =?UTF-8?q?=20pre=20company=20na=20editovanie=20vykazov=20praxe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pages/dashboard/company/internship.vue | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 frontend/app/pages/dashboard/company/internship.vue diff --git a/frontend/app/pages/dashboard/company/internship.vue b/frontend/app/pages/dashboard/company/internship.vue new file mode 100644 index 0000000..83903a9 --- /dev/null +++ b/frontend/app/pages/dashboard/company/internship.vue @@ -0,0 +1,358 @@ + + + + + \ No newline at end of file From f32ce9fc99fe4e4f5e535d8bcd88292bc2c892cb Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 18:23:13 +0100 Subject: [PATCH 06/19] feat: simplify internship document viewer and add support for reports --- .../components/InternshipDocumentViewer.vue | 61 +++++++++ .../dashboard/admin/internships/edit/[id].vue | 118 +----------------- frontend/app/types/internships.ts | 2 + 3 files changed, 64 insertions(+), 117 deletions(-) create mode 100644 frontend/app/components/InternshipDocumentViewer.vue diff --git a/frontend/app/components/InternshipDocumentViewer.vue b/frontend/app/components/InternshipDocumentViewer.vue new file mode 100644 index 0000000..5e96484 --- /dev/null +++ b/frontend/app/components/InternshipDocumentViewer.vue @@ -0,0 +1,61 @@ + + + diff --git a/frontend/app/pages/dashboard/admin/internships/edit/[id].vue b/frontend/app/pages/dashboard/admin/internships/edit/[id].vue index 0c15a7d..df93096 100644 --- a/frontend/app/pages/dashboard/admin/internships/edit/[id].vue +++ b/frontend/app/pages/dashboard/admin/internships/edit/[id].vue @@ -42,36 +42,6 @@ async function handleUpdateOfBasicInfo(internship: NewInternship) { } const { data, error, refresh } = await useSanctumFetch(`/api/internships/${route.params.id}`); - -// ---- helpery pre sekciu Dokumenty ---- -const docs = computed(() => { - const d: any = data.value ?? {} - return { - contract: d.documents?.contract ?? d.contract ?? null, - report: d.documents?.report ?? d.report ?? null, - } -}) - -function docUrl(doc: any) { - return doc?.url ?? doc?.download_url ?? doc?.link ?? null -} -function docName(doc: any) { - return doc?.fileName ?? doc?.filename ?? doc?.name ?? 'dokument.pdf' -} -function docSize(doc: any) { - const bytes = doc?.size ?? doc?.filesize ?? null - if (!bytes && bytes !== 0) return null - if (bytes < 1024) return `${bytes} B` - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB` - return `${(bytes / (1024 * 1024)).toFixed(1)} MB` -} -function docDate(doc: any) { - const dt = doc?.uploadedAt ?? doc?.created_at ?? doc?.uploaded_at ?? null - return dt ? new Date(dt).toLocaleString() : null -} -function docBy(doc: any) { - return doc?.uploadedBy?.name ?? doc?.uploaded_by?.name ?? doc?.uploaded_by ?? null -} From 28a79cf7c60cb5d5d0e264e889e6cbcf078e9f2e Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 19:54:22 +0100 Subject: [PATCH 10/19] fix: correct internship retrieval method in `get` function of `InternshipStatusController` --- backend/app/Http/Controllers/InternshipStatusController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/app/Http/Controllers/InternshipStatusController.php b/backend/app/Http/Controllers/InternshipStatusController.php index 3cee9dc..a25e20d 100644 --- a/backend/app/Http/Controllers/InternshipStatusController.php +++ b/backend/app/Http/Controllers/InternshipStatusController.php @@ -19,7 +19,7 @@ class InternshipStatusController extends Controller ], 400); } - $internship = Internship::where($id); + $internship = Internship::find($id); if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id) { abort(403, 'Unauthorized'); } From 04acbf1b58b98b46cddcdd9d806b1c4a54f7c839 Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 19:55:00 +0100 Subject: [PATCH 11/19] feat: enhance internship edit page with status display and document upload functionality for students --- .../student/internship/edit/[id].vue | 83 +++++++++++++++++-- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/frontend/app/pages/dashboard/student/internship/edit/[id].vue b/frontend/app/pages/dashboard/student/internship/edit/[id].vue index 81ac5a2..f330165 100644 --- a/frontend/app/pages/dashboard/student/internship/edit/[id].vue +++ b/frontend/app/pages/dashboard/student/internship/edit/[id].vue @@ -1,6 +1,7 @@ @@ -36,4 +102,9 @@ const { data, refresh } = await useSanctumFetch(`/api/internships/${ padding-right: 10px; padding-bottom: 10px; } + +hr { + margin-top: 20px; + margin-bottom: 20px; +} \ No newline at end of file From 6d2f57393db7fa1772c19704be56c7ebc92f5bb9 Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:00:58 +0100 Subject: [PATCH 12/19] refactor: update layout and styling of company dashboard page --- .../app/pages/dashboard/company/index.vue | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/frontend/app/pages/dashboard/company/index.vue b/frontend/app/pages/dashboard/company/index.vue index 6f2d8e2..085f377 100644 --- a/frontend/app/pages/dashboard/company/index.vue +++ b/frontend/app/pages/dashboard/company/index.vue @@ -18,26 +18,28 @@ const user = useSanctumUser(); \ No newline at end of file From cb5540ec8d4fca4372b1c1b0c05ab07a991a6819 Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:02:17 +0100 Subject: [PATCH 13/19] feat: rename internship route and replace `internship` page with `internships` page --- .../app/pages/dashboard/company/index.vue | 2 +- .../{internship.vue => internships/index.vue} | 200 ++++++++---------- 2 files changed, 85 insertions(+), 117 deletions(-) rename frontend/app/pages/dashboard/company/{internship.vue => internships/index.vue} (69%) diff --git a/frontend/app/pages/dashboard/company/index.vue b/frontend/app/pages/dashboard/company/index.vue index 085f377..ee77806 100644 --- a/frontend/app/pages/dashboard/company/index.vue +++ b/frontend/app/pages/dashboard/company/index.vue @@ -27,7 +27,7 @@ const user = useSanctumUser(); Môj profil - + Praxe diff --git a/frontend/app/pages/dashboard/company/internship.vue b/frontend/app/pages/dashboard/company/internships/index.vue similarity index 69% rename from frontend/app/pages/dashboard/company/internship.vue rename to frontend/app/pages/dashboard/company/internships/index.vue index 83903a9..c1fadb3 100644 --- a/frontend/app/pages/dashboard/company/internship.vue +++ b/frontend/app/pages/dashboard/company/internships/index.vue @@ -66,7 +66,7 @@ const students = ref([ { id: 2, name: 'Petra Kováčová', - existingReport: null, + existingReport: null, reportFile: null, localPreviewUrl: null, decision: null, @@ -181,26 +181,13 @@ async function submitFor(s: Student) {
- + Otvoriť - + Stiahnuť
@@ -210,43 +197,33 @@ async function submitFor(s: Student) { - -
Súbor: {{ s.existingReport.fileName }} ({{ formatSize(s.existingReport.size) }})
-
Nahraté: {{ new Date(s.existingReport.uploadedAt).toLocaleString() }}
+ +
Súbor: {{ s.existingReport.fileName }} ({{ + formatSize(s.existingReport.size) }})
+
Nahraté: {{ new + Date(s.existingReport.uploadedAt).toLocaleString() }}

Výkaz

- + accept=".pdf,application/pdf" prepend-icon="" label="Nahrať PDF výkaz" + variant="outlined" show-size clearable :disabled="s.loading" + hint="Povolené: PDF, max 10 MB" persistent-hint />
- + Otvoriť náhľad - + Stiahnuť vybraný súbor
@@ -254,20 +231,15 @@ async function submitFor(s: Student) {

Rozhodnutie

- + - +
@@ -277,20 +249,9 @@ async function submitFor(s: Student) {
- - + + @@ -302,57 +263,64 @@ async function submitFor(s: Student) { \ No newline at end of file From ec463c98b0d9a06e647668892dbee2bcd3a93a02 Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:38:44 +0100 Subject: [PATCH 14/19] fix: update semester handling in internship submission --- frontend/app/components/InternshipEditor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/InternshipEditor.vue b/frontend/app/components/InternshipEditor.vue index add890c..2cdccbb 100644 --- a/frontend/app/components/InternshipEditor.vue +++ b/frontend/app/components/InternshipEditor.vue @@ -77,7 +77,7 @@ function triggerSubmit() { start: dateTimeFixup(form.value.start as any), end: dateTimeFixup(form.value.end as any), year_of_study: form.value.year_of_study, - semester: form.value.semester === "Zimný" ? "WINTER" : "SUMMER", + semester: form.value.semester, position_description: form.value.description }; From ee3418e6582f670e9f4477c24d6a6513a11f714e Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:44:46 +0100 Subject: [PATCH 15/19] feat: add company relationship to `Internship` model --- backend/app/Models/Internship.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/app/Models/Internship.php b/backend/app/Models/Internship.php index 7161233..4974156 100644 --- a/backend/app/Models/Internship.php +++ b/backend/app/Models/Internship.php @@ -39,4 +39,9 @@ class Internship extends Model 'report_confirmed' => 'boolean', ]; } + + public function company() + { + return $this->belongsTo(Company::class, 'company_id'); + } } From 30973b2cedb39d3b7c4f46caae8bcf55e81ed738 Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:45:45 +0100 Subject: [PATCH 16/19] feat: update internship data retrieval permission checks --- .../Http/Controllers/InternshipController.php | 35 ++++++++++++++----- .../InternshipStatusController.php | 13 +++---- backend/routes/api.php | 2 +- 3 files changed, 33 insertions(+), 17 deletions(-) diff --git a/backend/app/Http/Controllers/InternshipController.php b/backend/app/Http/Controllers/InternshipController.php index 62b7bea..ee474f5 100644 --- a/backend/app/Http/Controllers/InternshipController.php +++ b/backend/app/Http/Controllers/InternshipController.php @@ -54,9 +54,28 @@ class InternshipController extends Controller return response()->json($internships); } - public function all_student() + public function all_my() { - $internships = Internship::where('user_id', auth()->id())->get()->makeHidden(['created_at', 'updated_at']); + $user = auth()->user(); + + if ($user->role === 'STUDENT') { + $internships = Internship::whereUserId($user->id)->get()->makeHidden(['created_at', 'updated_at']); + } elseif ($user->role === 'EMPLOYER') { + $company = Company::whereContact($user->id)->first(); + if (!$company) { + return response()->json(['message' => 'No company associated with this user.'], 404); + } + $internships = Internship::whereCompanyId($company->id)->get()->makeHidden(['created_at', 'updated_at']); + } else { + abort(403, 'Unauthorized'); + } + + if($user->role === "EMPLOYER") { + $internships->each(function ($internship) { + $internship->user = User::find($internship->user_id)->makeHidden(['created_at', 'updated_at', 'email_verified_at']); + unset($internship->user_id); + }); + } $internships->each(function ($internship) { $internship->company = Company::find($internship->company_id)->makeHidden(['created_at', 'updated_at']); @@ -97,16 +116,16 @@ class InternshipController extends Controller ], 400); } - if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id) { - abort(403, 'Unauthorized'); - } - $internship->company = Company::find($internship->company_id)->makeHidden(['created_at', 'updated_at']); unset($internship->company_id); + if($user->role !== 'ADMIN' && $internship->user_id !== $user->id && $user->id !== $internship->company->contact) { + abort(403, 'Unauthorized'); + } + $internship->contact = User::find($internship->company->contact)->makeHidden(['created_at', 'updated_at', 'email_verified_at']); unset($internship->company->contact); - + $internship->status = InternshipStatus::whereColumn('internship_id', '=', $internship->id)->orderByDesc('changed')->get()->first()->makeHidden(['created_at', 'updated_at', 'id']); $internship->status->modified_by = User::find($internship->status->modified_by)->makeHidden(['created_at', 'updated_at', 'email_verified_at']); @@ -191,7 +210,7 @@ class InternshipController extends Controller ], 400); } - if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id) { + if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id && $user->id !== $internship->company->contact) { abort(403, 'Unauthorized'); } diff --git a/backend/app/Http/Controllers/InternshipStatusController.php b/backend/app/Http/Controllers/InternshipStatusController.php index a25e20d..2621faa 100644 --- a/backend/app/Http/Controllers/InternshipStatusController.php +++ b/backend/app/Http/Controllers/InternshipStatusController.php @@ -20,7 +20,7 @@ class InternshipStatusController extends Controller } $internship = Internship::find($id); - if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id) { + if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id && $user->id !== $internship->company->contact) { abort(403, 'Unauthorized'); } @@ -41,7 +41,7 @@ class InternshipStatusController extends Controller ], 400); } - if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id && $user->id !== $internship->contact) { + if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id && $user->id !== $internship->company->contact) { abort(403, 'Unauthorized'); } @@ -105,9 +105,7 @@ class InternshipStatusController extends Controller ], 400); } - $company_contact = User::find($internship->contact); - - if ($user->role !== 'ADMIN' && $user->id !== $company_contact->id) { + if ($user->role !== 'ADMIN' && $user->id !== $internship->company->contact) { abort(403, 'Unauthorized'); } @@ -139,11 +137,10 @@ class InternshipStatusController extends Controller } private function possibleNewStatuses(string $current_status, string $userRole) { + if($userRole === "STUDENT") return []; + switch ($current_status) { case 'SUBMITTED': - if ($userRole === 'EMPLOYER') { - return []; - } return ['CONFIRMED', 'DENIED']; case 'CONFIRMED': if ($userRole === 'EMPLOYER') { diff --git a/backend/routes/api.php b/backend/routes/api.php index 367f259..a25dc1f 100644 --- a/backend/routes/api.php +++ b/backend/routes/api.php @@ -34,7 +34,7 @@ Route::post('/password-reset', [RegisteredUserController::class, 'reset_password Route::prefix('/internships')->group(function () { Route::get("/", [InternshipController::class, 'all'])->name("api.internships"); - Route::get("/my", [InternshipController::class, 'all_student'])->name("api.internships.student"); + Route::get("/my", [InternshipController::class, 'all_my'])->name("api.internships.my"); Route::middleware("auth:sanctum")->group(function () { Route::prefix('/{id}')->group(function () { From 8915a7cec81b605e0001a6ac8dfb1d65feb45878 Mon Sep 17 00:00:00 2001 From: br0kenpixel <23280129+br0kenpixel@users.noreply.github.com> Date: Mon, 3 Nov 2025 20:46:04 +0100 Subject: [PATCH 17/19] feat: implement internship editing functionality for companies --- .../company/internships/edit/[id].vue | 116 ++++++ .../dashboard/company/internships/index.vue | 357 +++--------------- 2 files changed, 175 insertions(+), 298 deletions(-) create mode 100644 frontend/app/pages/dashboard/company/internships/edit/[id].vue diff --git a/frontend/app/pages/dashboard/company/internships/edit/[id].vue b/frontend/app/pages/dashboard/company/internships/edit/[id].vue new file mode 100644 index 0000000..74cac5d --- /dev/null +++ b/frontend/app/pages/dashboard/company/internships/edit/[id].vue @@ -0,0 +1,116 @@ + + + + + \ No newline at end of file diff --git a/frontend/app/pages/dashboard/company/internships/index.vue b/frontend/app/pages/dashboard/company/internships/index.vue index c1fadb3..7ff86fd 100644 --- a/frontend/app/pages/dashboard/company/internships/index.vue +++ b/frontend/app/pages/dashboard/company/internships/index.vue @@ -1,326 +1,87 @@ \ No newline at end of file From 69df349d3fbcddaf2ef31d431fafeee77fb0696e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Reh=C3=A1kov=C3=A1?= <125893846+sofiarehakova@users.noreply.github.com> Date: Mon, 3 Nov 2025 22:56:35 +0100 Subject: [PATCH 18/19] potvrdenie vykazu a oprava databazy --- .../Http/Controllers/InternshipController.php | 25 +++++++++++-------- .../components/InternshipDocumentEditor.vue | 9 ++++++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/backend/app/Http/Controllers/InternshipController.php b/backend/app/Http/Controllers/InternshipController.php index ee474f5..0be763f 100644 --- a/backend/app/Http/Controllers/InternshipController.php +++ b/backend/app/Http/Controllers/InternshipController.php @@ -37,7 +37,7 @@ class InternshipController extends Controller }); $internships->each(function ($internship) { - $internship->status = InternshipStatus::whereColumn('internship_id', '=', $internship->id)->orderByDesc('changed')->get()->first()->makeHidden(['created_at', 'updated_at', 'id']); + $internship->status = InternshipStatus::whereInternshipId($internship->id)->orderByDesc('changed')->get()->first()->makeHidden(['created_at', 'updated_at', 'id']); $internship->status->modified_by = User::find($internship->status->modified_by)->makeHidden(['created_at', 'updated_at', 'email_verified_at']); }); @@ -126,7 +126,7 @@ class InternshipController extends Controller $internship->contact = User::find($internship->company->contact)->makeHidden(['created_at', 'updated_at', 'email_verified_at']); unset($internship->company->contact); - $internship->status = InternshipStatus::whereColumn('internship_id', '=', $internship->id)->orderByDesc('changed')->get()->first()->makeHidden(['created_at', 'updated_at', 'id']); + $internship->status = InternshipStatus::whereInternshipId($internship->id)->orderByDesc('changed')->get()->first()->makeHidden(['created_at', 'updated_at', 'id']); $internship->status->modified_by = User::find($internship->status->modified_by)->makeHidden(['created_at', 'updated_at', 'email_verified_at']); $internship->agreement = $internship->agreement !== null; @@ -231,21 +231,16 @@ class InternshipController extends Controller ], 400); } - if ($user->role !== 'ADMIN' && $internship->user_id !== $user->id && $user->id !== $internship->contact) { + if ($internship->user_id !== $user->id && $user->id !== $internship->company->contact) { abort(403, 'Unauthorized'); } $request->validate([ 'agreement' => ['nullable', 'file', 'mimes:pdf', 'max:10240'], - 'report' => ['nullable', 'file', 'mimes:pdf', 'max:10240'] + 'report' => ['nullable', 'file', 'mimes:pdf', 'max:10240'], + 'report_confirmed' => ['required', 'boolean'], ]); - if (!$request->hasFile('agreement') && !$request->hasFile('report')) { - return response()->json([ - 'message' => 'At least one document (agreement or report) must be provided.' - ], 400); - } - if ($request->hasFile('agreement')) { $internship->agreement = file_get_contents($request->file('agreement')->getRealPath()); } @@ -254,6 +249,16 @@ class InternshipController extends Controller $internship->report = file_get_contents($request->file('report')->getRealPath()); } + if($user->role === 'EMPLOYER') { + if($request->report_confirmed && (!$internship->agreement || !$internship->report)) { + return response()->json([ + 'message' => 'Report cannot be confirmed without an agreement and report.' + ], 400); + } + + $internship->report_confirmed = $request->report_confirmed; + } + $internship->save(); return response()->noContent(); } diff --git a/frontend/app/components/InternshipDocumentEditor.vue b/frontend/app/components/InternshipDocumentEditor.vue index deaa7c0..965c699 100644 --- a/frontend/app/components/InternshipDocumentEditor.vue +++ b/frontend/app/components/InternshipDocumentEditor.vue @@ -1,6 +1,8 @@