Implement health check service and global exception handling
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import { useState, useTransition } from 'react';
|
||||
import { parseErrorResponse } from '../../lib/error-handler';
|
||||
import type { InventoryConsumption } from '../../features/inventory/types';
|
||||
|
||||
type Props = {
|
||||
@@ -28,15 +29,16 @@ export default function InventoryConsumptionHistory({ id }: Props) {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(text || 'Kunde inte hämta historik.');
|
||||
const errorMessage = await parseErrorResponse(res);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
const data: InventoryConsumption[] = await res.json();
|
||||
setHistory(data);
|
||||
setIsOpen(true);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Okänt fel');
|
||||
const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade.';
|
||||
setError(message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useState, useTransition } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { parseErrorResponse } from '../../lib/error-handler';
|
||||
import type {
|
||||
Recipe,
|
||||
RecipeInventoryPreview,
|
||||
@@ -74,14 +75,15 @@ export default function RecipePreview({ recipes }: Props) {
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const text = await res.text();
|
||||
throw new Error(text || 'Kunde inte hämta recept-preview.');
|
||||
const errorMessage = await parseErrorResponse(res);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
const data: RecipeInventoryPreview = await res.json();
|
||||
setPreview(data);
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Okänt fel');
|
||||
const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade.';
|
||||
setError(message);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useRouter, useParams } from 'next/navigation';
|
||||
import { fetchJson } from '../../../../lib/api';
|
||||
import { parseErrorResponse } from '../../../../lib/error-handler';
|
||||
import type { Product, Recipe } from '../../../../features/inventory/types';
|
||||
|
||||
export default function EditRecipePage() {
|
||||
@@ -99,12 +100,14 @@ export default function EditRecipePage() {
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Kunde inte uppdatera receptet');
|
||||
const errorMessage = await parseErrorResponse(response);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
router.push('/recipes');
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade. Försök igen.';
|
||||
setError(message);
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { fetchJson } from '../../../lib/api';
|
||||
import { parseErrorResponse } from '../../../lib/error-handler';
|
||||
import type { Product } from '../../../features/inventory/types';
|
||||
|
||||
export default function CreateRecipePage() {
|
||||
@@ -64,12 +65,14 @@ export default function CreateRecipePage() {
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Kunde inte spara receptet');
|
||||
const errorMessage = await parseErrorResponse(response);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
router.push('/recipes');
|
||||
} catch (err) {
|
||||
setError((err as Error).message);
|
||||
const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade. Försök igen.';
|
||||
setError(message);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* Utility för att parse HTTP-responses och extrahera tydliga felmeddelanden
|
||||
*/
|
||||
export async function parseErrorResponse(response: Response): Promise<string> {
|
||||
const status = response.status;
|
||||
|
||||
try {
|
||||
const data = await response.json();
|
||||
|
||||
// Om backend skickade ett felmeddelande
|
||||
if (data.message) {
|
||||
return data.message;
|
||||
}
|
||||
if (data.error) {
|
||||
return data.error;
|
||||
}
|
||||
if (data.details) {
|
||||
return data.details;
|
||||
}
|
||||
} catch {
|
||||
// Inte JSON, försök text
|
||||
try {
|
||||
const text = await response.text();
|
||||
if (text && text.length < 200) {
|
||||
return text;
|
||||
}
|
||||
} catch {
|
||||
// Inget text-innehål
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback baserat på HTTP-status
|
||||
const defaultMessages: Record<number, string> = {
|
||||
400: 'Ogiltiga data. Kontrollera dina inmatningar.',
|
||||
401: 'Du är inte autentiserad. Logga in.',
|
||||
403: 'Du har inte behörighet till detta.',
|
||||
404: 'Resursen hittades inte.',
|
||||
409: 'Konflikten med befintlig data.',
|
||||
422: 'Valideringen misslyckades. Kontrollera dina inmatningar.',
|
||||
500: 'Serverfel. Försök igen senare.',
|
||||
503: 'Tjänsten är inte tillgänglig.',
|
||||
};
|
||||
|
||||
return defaultMessages[status] || `Fel (${status}). Försök igen senare.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hämta data från API med bra felhantering
|
||||
*/
|
||||
export async function fetchWithErrorHandling(
|
||||
url: string,
|
||||
options?: RequestInit,
|
||||
): Promise<any> {
|
||||
try {
|
||||
const response = await fetch(url, options);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorMessage = await parseErrorResponse(response);
|
||||
throw new Error(errorMessage);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
throw err;
|
||||
}
|
||||
throw new Error('Ett okänt fel inträffade.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user