diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx
index 39b9cd6..633862c 100644
--- a/frontend/src/App.jsx
+++ b/frontend/src/App.jsx
@@ -1,4 +1,4 @@
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
import { jwtDecode } from 'jwt-decode';
import Layout from './components/Layout';
import OwnerDashboard from './pages/OwnerDashboard';
@@ -21,6 +21,7 @@ function App() {
const [myRecords, setMyRecords] = useState([]);
const [loading, setLoading] = useState(true);
const [currentUser, setCurrentUser] = useState(null);
+ const caseDetailDirtyRef = useRef(false);
// 1. Initialisering: Hämta användare från token vid start
useEffect(() => {
@@ -109,6 +110,7 @@ function App() {
};
const goBackToDashboard = () => {
+ caseDetailDirtyRef.current = false;
setSelectedPet(null);
setSelectedRecord(null);
if (currentUser?.role === 'ROLE_VET') {
@@ -209,6 +211,7 @@ function App() {
caseData={selectedRecord}
currentUserId={currentUser?.id}
userRole={currentUser?.role} // VIKTIGT: Skickar med rollen för veterinär-panelen
+ onDirtyChange={(dirty) => { caseDetailDirtyRef.current = dirty; }}
onBack={goBackToDashboard}
onGoToPet={async (petId) => {
try {
@@ -270,7 +273,13 @@ function App() {
userName={currentUser?.name || currentUser?.email || "Användare"}
userRole={currentUser?.role}
onLogout={handleLogout}
- onNavigate={(view) => setCurrentView(view)}
+ onNavigate={(view) => {
+ if (currentView === 'case-detail' && caseDetailDirtyRef.current) {
+ if (!window.confirm('Du har osparade ändringar. Vill du lämna sidan?')) return;
+ }
+ caseDetailDirtyRef.current = false;
+ setCurrentView(view);
+ }}
currentView={currentView}
>
diff --git a/frontend/src/pages/CaseDetail.jsx b/frontend/src/pages/CaseDetail.jsx
index 339f8c3..a3e67cb 100644
--- a/frontend/src/pages/CaseDetail.jsx
+++ b/frontend/src/pages/CaseDetail.jsx
@@ -3,7 +3,7 @@ import { commentService, activityService, attachmentService, medicalRecordServic
import { STATUS_MAP } from '../utils/statusHelper';
import { Stethoscope, Lock, FileText, CheckCircle, Upload, Trash2, ExternalLink } from 'lucide-react';
-const CaseDetail = ({ caseData, onBack, onGoToPet, currentUserId, userRole }) => {
+const CaseDetail = ({ caseData, onBack, onGoToPet, currentUserId, userRole, onDirtyChange }) => {
const [newMessage, setNewMessage] = useState('');
const [timeline, setTimeline] = useState([]);
const [attachments, setAttachments] = useState([]);
@@ -22,6 +22,41 @@ const CaseDetail = ({ caseData, onBack, onGoToPet, currentUserId, userRole }) =>
const isClosed = localStatus === 'CLOSED'; // Helper för att förenkla checkar
+ // Refs för att komma åt senaste state i cleanup-funktioner
+ const newMessageRef = useRef(newMessage);
+ const isEditingRef = useRef(isEditing);
+ const editedTitleRef = useRef(editedTitle);
+ const editedDescriptionRef = useRef(editedDescription);
+
+ useEffect(() => { newMessageRef.current = newMessage; }, [newMessage]);
+ useEffect(() => { isEditingRef.current = isEditing; }, [isEditing]);
+ useEffect(() => { editedTitleRef.current = editedTitle; }, [editedTitle]);
+ useEffect(() => { editedDescriptionRef.current = editedDescription; }, [editedDescription]);
+
+ // Rapportera dirty-state uppåt till App för in-app navigeringsskydd
+ useEffect(() => {
+ const journalChanged = isEditing && (editedTitle !== caseData?.title || editedDescription !== caseData?.description);
+ onDirtyChange?.(newMessage.trim().length > 0 || journalChanged);
+ }, [newMessage, isEditing, editedTitle, editedDescription]);
+
+ // Varna vid stängning av fliken om det finns osparad text
+ useEffect(() => {
+ const handleBeforeUnload = (e) => {
+ const journalChanged = isEditingRef.current && (editedTitleRef.current !== caseData?.title || editedDescriptionRef.current !== caseData?.description);
+ const hasUnsaved = newMessageRef.current.trim() || journalChanged;
+ if (hasUnsaved) {
+ e.preventDefault();
+ e.returnValue = '';
+ }
+ };
+ window.addEventListener('beforeunload', handleBeforeUnload);
+ return () => window.removeEventListener('beforeunload', handleBeforeUnload);
+ }, []);
+
+ useEffect(() => {
+ return () => { onDirtyChange?.(false); };
+ }, []);
+
useEffect(() => {
if (caseData) {
setLocalStatus(caseData.status);