diff --git a/backend/app/Http/Controllers/Auth/RegisteredUserController.php b/backend/app/Http/Controllers/Auth/RegisteredUserController.php index 98509eb..ba2d421 100644 --- a/backend/app/Http/Controllers/Auth/RegisteredUserController.php +++ b/backend/app/Http/Controllers/Auth/RegisteredUserController.php @@ -26,7 +26,7 @@ class RegisteredUserController extends Controller $password = bin2hex(random_bytes(16)); $request->validate([ - 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class], + 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:' . User::class], 'first_name' => ['required', 'string', 'max:64'], 'last_name' => ['required', 'string', 'max:64'], 'phone' => ['required', 'string', 'max:13'], @@ -56,14 +56,14 @@ class RegisteredUserController extends Controller 'password' => Hash::make($password), ]); - if($user->role === "STUDENT") { + if ($user->role === "STUDENT") { StudentData::create([ 'user_id' => $user->id, 'address' => $request->student_data['address'], 'personal_email' => $request->student_data['personal_email'], 'study_field' => $request->student_data['study_field'], ]); - } else if($user->role === "EMPLOYER") { + } else if ($user->role === "EMPLOYER") { Company::create([ 'name' => $request->company_data['name'], 'address' => $request->company_data['address'], @@ -79,7 +79,8 @@ class RegisteredUserController extends Controller return response()->noContent(); } - public function reset_password(Request $request): Response { + public function reset_password(Request $request): Response + { $request->validate([ 'email' => ['required', 'string', 'lowercase', 'email', 'max:255'], ]); @@ -97,4 +98,22 @@ class RegisteredUserController extends Controller return response()->noContent(); } + + public function reset_password_2(Request $request): Response + { + $request->validate([ + 'id' => ['required', 'string', 'lowercase', 'email', 'max:255'], + 'password' => ['required', 'string', 'lowercase', 'email', 'max:255'], + ]); + + $user = User::whereEmail($request->email)->first(); + if (!$user) { + return response(status: 400); + } + + $user->password = Hash::make($request->password); + $user->save(); + + return response()->noContent(); + } } \ No newline at end of file diff --git a/backend/app/Http/Controllers/CompanyController.php b/backend/app/Http/Controllers/CompanyController.php index 7b0222c..7afc3d4 100644 --- a/backend/app/Http/Controllers/CompanyController.php +++ b/backend/app/Http/Controllers/CompanyController.php @@ -4,7 +4,10 @@ namespace App\Http\Controllers; use App\Models\Company; use App\Models\User; +use App\Models\Internship; +use App\Models\InternshipStatus; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; class CompanyController extends Controller { @@ -155,4 +158,48 @@ class CompanyController extends Controller { // } + + /** + * Delete a company, its contact person and all related data. + */ + public function delete(int $id) + { + $user = auth()->user(); + + // Admin kontrola + if ($user->role !== 'ADMIN') { + abort(403, 'Unauthorized'); + } + + $company = Company::find($id); + $company_contact = User::find($company->contact); + + if (!$company) { + return response()->json([ + 'message' => 'No such company exists.' + ], 400); + } + + DB::beginTransaction(); + + $internships = Internship::whereCompanyId($company->id); + + // mazanie statusov + $internships->each(function ($internship) { + InternshipStatus::whereInternshipId($internship->id)->delete(); + }); + + // mazanie praxov + $internships->delete(); + + // mazanie firmy + Company::whereContact($company_contact->id); + + // mazanie účtu firmy + $company_contact->delete(); + + DB::commit(); + + return response()->noContent(); + } } diff --git a/backend/app/Http/Controllers/StudentDataController.php b/backend/app/Http/Controllers/StudentDataController.php index 0de7529..1d24a25 100644 --- a/backend/app/Http/Controllers/StudentDataController.php +++ b/backend/app/Http/Controllers/StudentDataController.php @@ -2,9 +2,12 @@ namespace App\Http\Controllers; +use App\Models\Internship; use App\Models\StudentData; use App\Models\User; +use App\Models\InternshipStatus; use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; class StudentDataController extends Controller { @@ -171,4 +174,54 @@ class StudentDataController extends Controller { // } + + /** + * Delete a student and all related data. + */ + public function delete(int $id) + { + $user = auth()->user(); + + // Admin kontrola + if ($user->role !== 'ADMIN') { + abort(403, 'Unauthorized'); + } + + $student = User::find($id); + + if (!$student) { + return response()->json([ + 'message' => 'No such student exists.' + ], 400); + } + + if ($student->role !== 'STUDENT') { + return response()->json([ + 'message' => 'User is not a student.' + ], 400); + } + + DB::beginTransaction(); + + // mazanie praxov + $internships = Internship::whereUserId($student->id); + + // mazanie statusov + $internships->each(function ($internship) { + InternshipStatus::whereInternshipId($internship->id)->delete(); + }); + + // mazanie praxov + $internships->delete(); + + // mazanie firmy + StudentData::whereUserId($student->id); + + // mazanie účtu firmy + $student->delete(); + + DB::commit(); + + return response()->noContent(); + } } diff --git a/backend/app/Models/Company.php b/backend/app/Models/Company.php index ea19407..6320e72 100644 --- a/backend/app/Models/Company.php +++ b/backend/app/Models/Company.php @@ -22,4 +22,20 @@ class Company extends Model 'contact', 'hiring' ]; + + /** + * Get the internships for the company. + */ + public function internships() + { + return $this->hasMany(Internship::class, 'company_id'); + } + + /** + * Get the contact person (user) for the company. + */ + public function contactPerson() + { + return $this->belongsTo(User::class, 'contact'); + } } diff --git a/backend/app/Models/User.php b/backend/app/Models/User.php index a052880..de3bb49 100644 --- a/backend/app/Models/User.php +++ b/backend/app/Models/User.php @@ -57,4 +57,12 @@ class User extends Authenticatable { return $this->hasOne(StudentData::class, 'user_id'); } + + /** + * Get the internships for the user. + */ + public function internships() + { + return $this->hasMany(Internship::class, 'user_id'); + } } diff --git a/backend/routes/api.php b/backend/routes/api.php index 35bae9d..3190b4d 100644 --- a/backend/routes/api.php +++ b/backend/routes/api.php @@ -26,6 +26,7 @@ Route::middleware(['auth:sanctum'])->prefix('/students')->group(function () { Route::get('/', [StudentDataController::class, 'all']); Route::get('/{id}', [StudentDataController::class, 'get']); Route::post('/{id}', [StudentDataController::class, 'update_all']); + Route::delete('/{id}', [StudentDataController::class, 'delete']); }); Route::post('/password-reset', [RegisteredUserController::class, 'reset_password']) @@ -56,4 +57,5 @@ Route::prefix('/companies')->middleware("auth:sanctum")->group(function () { Route::get("/simple", [CompanyController::class, 'all_simple']); Route::get("/{id}", [CompanyController::class, 'get']); Route::post("/{id}", [CompanyController::class, 'update_all']); + Route::delete("/{id}", [CompanyController::class, 'delete']); }); \ No newline at end of file diff --git a/frontend/app/pages/dashboard/admin/companies/edit/[id].vue b/frontend/app/pages/dashboard/admin/companies/edit/[id].vue index 95462a3..5885350 100644 --- a/frontend/app/pages/dashboard/admin/companies/edit/[id].vue +++ b/frontend/app/pages/dashboard/admin/companies/edit/[id].vue @@ -13,6 +13,13 @@ const companyId = route.params.id; const loading = ref(true); const saving = ref(false); +// Delete state +const deleteDialog = ref(false); +const deleteLoading = ref(false); +const deleteError = ref(null); +const deleteSuccess = ref(false); +const company = ref(null); + const form = ref({ name: '', address: '', @@ -31,6 +38,7 @@ const { data } = await useSanctumFetch(`/api/companies/${companyId} watch(data, (newData) => { if (newData) { + company.value = newData; form.value.name = newData.name; form.value.address = newData.address; form.value.ico = newData.ico; @@ -67,6 +75,49 @@ async function saveChanges() { function cancel() { navigateTo('/dashboard/admin/companies'); } + +// Funkcia na otvorenie delete dialogu +const openDeleteDialog = () => { + deleteDialog.value = true; + deleteError.value = null; +}; + +// Funkcia na zatvorenie dialogu +const closeDeleteDialog = () => { + deleteDialog.value = false; + deleteError.value = null; + deleteSuccess.value = false; +}; + +// Funkcia na vymazanie firmy +const deleteCompany = async () => { + if (!companyId) return; + + deleteLoading.value = true; + deleteError.value = null; + + try { + await client(`/api/companies/${companyId}`, { + method: 'DELETE' + }); + + deleteSuccess.value = true; + + // Presmeruj na zoznam po 1.5 sekundách + setTimeout(() => { + navigateTo('/dashboard/admin/companies'); + }, 1500); + + } catch (e) { + if (e instanceof FetchError) { + deleteError.value = e.response?._data?.message || 'Chyba pri mazaní firmy.'; + } else { + deleteError.value = 'Neznáma chyba pri mazaní firmy.'; + } + } finally { + deleteLoading.value = false; + } +}; diff --git a/frontend/app/pages/dashboard/admin/companies/index.vue b/frontend/app/pages/dashboard/admin/companies/index.vue index 6bd4cac..13c3dc8 100644 --- a/frontend/app/pages/dashboard/admin/companies/index.vue +++ b/frontend/app/pages/dashboard/admin/companies/index.vue @@ -1,5 +1,6 @@ diff --git a/frontend/app/pages/dashboard/admin/students/edit/[id].vue b/frontend/app/pages/dashboard/admin/students/edit/[id].vue index 4d41eb8..a78d4fb 100644 --- a/frontend/app/pages/dashboard/admin/students/edit/[id].vue +++ b/frontend/app/pages/dashboard/admin/students/edit/[id].vue @@ -14,6 +14,12 @@ const student = ref(null); const loading = ref(true); const saving = ref(false); +// Delete state +const deleteDialog = ref(false); +const deleteLoading = ref(false); +const deleteError = ref(null); +const deleteSuccess = ref(false); + const form = ref({ first_name: '', last_name: '', @@ -69,6 +75,49 @@ async function saveChanges() { function cancel() { navigateTo('/dashboard/admin/students'); } + +// Funkcia na otvorenie delete dialogu +const openDeleteDialog = () => { + deleteDialog.value = true; + deleteError.value = null; +}; + +// Funkcia na zatvorenie dialogu +const closeDeleteDialog = () => { + deleteDialog.value = false; + deleteError.value = null; + deleteSuccess.value = false; +}; + +// Funkcia na vymazanie študenta +const deleteStudent = async () => { + if (!studentId) return; + + deleteLoading.value = true; + deleteError.value = null; + + try { + await client(`/api/students/${studentId}`, { + method: 'DELETE' + }); + + deleteSuccess.value = true; + + // Presmeruj na zoznam po 1.5 sekundách + setTimeout(() => { + navigateTo('/dashboard/admin/students'); + }, 1500); + + } catch (e) { + if (e instanceof FetchError) { + deleteError.value = e.response?._data?.message || 'Chyba pri mazaní študenta.'; + } else { + deleteError.value = 'Neznáma chyba pri mazaní študenta.'; + } + } finally { + deleteLoading.value = false; + } +}; diff --git a/frontend/app/pages/dashboard/admin/students/index.vue b/frontend/app/pages/dashboard/admin/students/index.vue index d3eb4c7..9f706e7 100644 --- a/frontend/app/pages/dashboard/admin/students/index.vue +++ b/frontend/app/pages/dashboard/admin/students/index.vue @@ -1,5 +1,6 @@