From 1973ab6b7ff16c393c75a593fa7ebf3433e8ef0e Mon Sep 17 00:00:00 2001 From: dkecskes Date: Mon, 3 Nov 2025 19:37:04 +0100 Subject: [PATCH] feat: implement company deletion functionality with confirmation dialog --- .../Http/Controllers/CompanyController.php | 66 ++++++++++++ backend/app/Models/Company.php | 16 +++ backend/routes/api.php | 1 + .../dashboard/admin/companies/edit/[id].vue | 93 ++++++++++++++++ .../pages/dashboard/admin/companies/index.vue | 100 +++++++++++++++++- 5 files changed, 274 insertions(+), 2 deletions(-) diff --git a/backend/app/Http/Controllers/CompanyController.php b/backend/app/Http/Controllers/CompanyController.php index f8499d6..ac3ce8e 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 { @@ -152,4 +155,67 @@ 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); + + if (!$company) { + return response()->json([ + 'message' => 'No such company exists.' + ], 400); + } + + try { + DB::beginTransaction(); + + // 1. Získaj všetky internship IDs firmy + $internshipIds = Internship::where('company_id', $company->id) + ->pluck('id') + ->toArray(); + + // 2. Vymaž všetky internship statuses + if (!empty($internshipIds)) { + InternshipStatus::whereIn('internship_id', $internshipIds)->delete(); + } + + // 3. Vymaž všetky internships firmy + Internship::where('company_id', $company->id)->delete(); + + // 4. Získaj contact usera + $contactUser = User::find($company->contact); + + // 5. Vymaž company + $company->delete(); + + // 6. Vymaž contact usera (EMPLOYER) + if ($contactUser && $contactUser->role === 'EMPLOYER') { + $contactUser->delete(); + } + + DB::commit(); + + return response()->json([ + 'message' => 'Company successfully deleted.' + ], 200); + + } catch (\Exception $e) { + DB::rollBack(); + + return response()->json([ + 'message' => 'Error deleting company.', + 'error' => $e->getMessage() + ], 500); + } + } } 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/routes/api.php b/backend/routes/api.php index 6af5e6e..4e4e11c 100644 --- a/backend/routes/api.php +++ b/backend/routes/api.php @@ -54,4 +54,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 f0cca5c..c4c6c25 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: '', @@ -30,6 +37,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; @@ -65,6 +73,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..43622e1 100644 --- a/frontend/app/pages/dashboard/admin/companies/index.vue +++ b/frontend/app/pages/dashboard/admin/companies/index.vue @@ -22,7 +22,65 @@ const headers = [ { title: 'Operácie', key: 'ops', align: 'middle' }, ]; +const client = useSanctumClient(); + const { data, error } = await useSanctumFetch('/api/companies/simple'); + +// State pre delete dialog +const deleteDialog = ref(false); +const companyToDelete = ref(null); +const deleteLoading = ref(false); +const deleteError = ref(null); +const deleteSuccess = ref(false); + +// Funkcia na otvorenie delete dialogu +const openDeleteDialog = (company: CompanyData) => { + companyToDelete.value = company; + deleteDialog.value = true; + deleteError.value = null; +}; + +// Funkcia na zatvorenie dialogu +const closeDeleteDialog = () => { + deleteDialog.value = false; + companyToDelete.value = null; + deleteError.value = null; + deleteSuccess.value = false; +}; + +// Funkcia na vymazanie firmy +const deleteCompany = async () => { + if (!companyToDelete.value) return; + + deleteLoading.value = true; + deleteError.value = null; + + try { + await client(`/api/companies/${companyToDelete.value.id}`, { + method: 'DELETE' + }); + + // Odstránime firmu zo zoznamu + if (data.value) { + const index = data.value.findIndex(c => c.id === companyToDelete.value!.id); + if (index > -1) { + data.value.splice(index, 1); + } + } + + deleteSuccess.value = true; + + setTimeout(() => { + closeDeleteDialog(); + }, 1500); + + } catch (err: any) { + deleteError.value = err.data?.message || 'Chyba pri mazaní firmy.'; + } finally { + deleteLoading.value = false; + } +}; +