From 44d0b455adfafafb732142b8cf738b7ff89c41f4 Mon Sep 17 00:00:00 2001 From: Johan Briger Date: Fri, 24 Apr 2026 11:31:26 +0200 Subject: [PATCH] feat: allow owners to delete pets --- frontend/src/App.jsx | 1 + frontend/src/pages/PetDetail.jsx | 118 +++++++++++++----- frontend/src/services/api.jsx | 2 + .../repository/MedicalRecordRepository.java | 1 + .../example/vet1177/services/PetService.java | 6 + 5 files changed, 96 insertions(+), 32 deletions(-) diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 0c635c31..b08337f1 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -198,6 +198,7 @@ function App() { onBack={goBackToDashboard} onRegisterCase={(pet) => { setSelectedPet(pet); setCurrentView('create-case'); }} onCaseClick={handleCaseClick} + onDelete={fetchData} /> ); diff --git a/frontend/src/pages/PetDetail.jsx b/frontend/src/pages/PetDetail.jsx index ee45885d..d337eff5 100644 --- a/frontend/src/pages/PetDetail.jsx +++ b/frontend/src/pages/PetDetail.jsx @@ -1,10 +1,12 @@ import React, { useState, useEffect } from 'react'; import { STATUS_MAP } from '../utils/statusHelper'; -import { medicalRecordService } from '../services/api'; +import { medicalRecordService, petService } from '../services/api'; +import { Trash2, Info, AlertCircle } from 'lucide-react'; -const PetDetail = ({ pet, onBack, onRegisterCase, onCaseClick }) => { +const PetDetail = ({ pet, onBack, onRegisterCase, onCaseClick, onDelete }) => { const [petRecords, setPetRecords] = useState([]); const [loading, setLoading] = useState(true); + const [isDeleting, setIsDeleting] = useState(false); useEffect(() => { if (!pet?.id) { @@ -20,6 +22,30 @@ const PetDetail = ({ pet, onBack, onRegisterCase, onCaseClick }) => { return () => { cancelled = true; }; }, [pet?.id]); + // Strikt kontroll: Vi tillåter bara borttagning om noll journaler finns (matchar backend) + const hasHistory = Array.isArray(petRecords) && petRecords.length > 0; + + const handleDeletePet = async () => { + if (hasHistory) return; + + const confirmMessage = `Är du helt säker på att du vill ta bort ${pet.name}? Detta går inte att ångra.`; + if (window.confirm(confirmMessage)) { + setIsDeleting(true); + try { + await petService.deletePet(pet.id); + if (onDelete) { + await onDelete(); + } + onBack(); // Navigera tillbaka till listan + } catch (err) { + console.error("Fel vid borttagning:", err); + alert(err.response?.data?.message || "Kunde inte ta bort djurprofilen."); + } finally { + setIsDeleting(false); + } + } + }; + if (!pet) { return
Ingen djurdata hittades.
; } @@ -29,64 +55,88 @@ const PetDetail = ({ pet, onBack, onRegisterCase, onCaseClick }) => { {/* Navigering tillbaka */} -
+
{/* VÄNSTERKOLUMN: DJURPROFIL */}
-
+
-
+
{pet?.name?.charAt(0) || '?'}
-

+

{pet?.name}

-

+

{pet?.species} • {pet?.breed || 'Okänd ras'}

- Född + Född {pet?.dateOfBirth || 'Ej angivet'}
- Vikt + Vikt {pet?.weightKg ? `${pet.weightKg} kg` : 'Ej angivet'}
- +
+ + + {/* TA BORT-KNAPP */} + + + {hasHistory && ( +
+ +

+ Profilen kan ej raderas då den är kopplad till medicinsk historik i systemet. +

+
+ )} +
{/* HÖGERKOLUMN: JOURNALHISTORIK */}
-

- +

+ Journalhistorik för {pet?.name}

{loading ? ( -
-
- Laddar... +
+
+ Hämtar journaler...
) : Array.isArray(petRecords) && petRecords.length > 0 ? ( petRecords.map(record => { @@ -101,31 +151,35 @@ const PetDetail = ({ pet, onBack, onRegisterCase, onCaseClick }) => { type="button" key={record.id} onClick={() => onCaseClick && onCaseClick(record)} - aria-label={`Visa detaljer för journal: ${record.title || 'Journalanteckning'}`} - className="w-full text-left p-5 bg-white border border-slate-200 rounded-xl hover:shadow-md transition group focus:ring-2 focus:ring-blue-500 outline-none" + className="w-full text-left p-6 bg-white border border-slate-200 rounded-[2rem] hover:shadow-xl hover:border-blue-100 transition-all group outline-none" >
-
- +
+ {statusConfig.label} -

+

{record.reasonForVisit || record.title || 'Journalanteckning'}

-

- {record.diagnosis || 'Ingen diagnos ställd än.'} +

+ {record.diagnosis || 'Väntar på medicinsk bedömning...'}

-
- {record.createdAt ? new Date(record.createdAt).toLocaleDateString('sv-SE') : ''} +
+
+ {record.createdAt ? new Date(record.createdAt).toLocaleDateString('sv-SE') : ''} +
); }) ) : ( -
-

Ingen historik hittades

+
+
+ +
+

Ingen historik hittades

)}
diff --git a/frontend/src/services/api.jsx b/frontend/src/services/api.jsx index 224c2275..e27cd8d3 100644 --- a/frontend/src/services/api.jsx +++ b/frontend/src/services/api.jsx @@ -69,6 +69,8 @@ export const petService = { getPetsByOwner: (ownerId) => api.get(`/pets/owner/${ownerId}`), getPetById: (id) => api.get(`/pets/${id}`), createPet: (data) => api.post('/pets', data), + updatePet: (id, data) => api.put(`/pets/${id}`, data), + deletePet: (id) => api.delete(`/pets/${id}`), }; export const medicalRecordService = { diff --git a/src/main/java/org/example/vet1177/repository/MedicalRecordRepository.java b/src/main/java/org/example/vet1177/repository/MedicalRecordRepository.java index db8f424f..c0b2f617 100644 --- a/src/main/java/org/example/vet1177/repository/MedicalRecordRepository.java +++ b/src/main/java/org/example/vet1177/repository/MedicalRecordRepository.java @@ -37,4 +37,5 @@ public interface MedicalRecordRepository extends JpaRepository