refactor: useAuthFetch-hook för automatisk JWT-header i klientanrop

This commit is contained in:
Nils-Johan Gynther
2026-04-19 21:48:13 +02:00
parent 92d0b066f1
commit b4d9e3dd5f
4 changed files with 40 additions and 17 deletions
@@ -2,7 +2,7 @@
import { useState, useEffect, useTransition } from 'react';
import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
import { useAuthFetch } from '../../../lib/use-auth-fetch';
import type {
Recipe,
Product,
@@ -65,7 +65,7 @@ function StatusBadge({ status }: { status: 'enough' | 'missing' | 'unit_mismatch
export default function RecipeDetailClient({ recipe: initialRecipe }: { recipe: Recipe }) {
const router = useRouter();
const { data: session } = useSession();
const authFetch = useAuthFetch();
const [recipe, setRecipe] = useState(initialRecipe);
const [isEditing, setIsEditing] = useState(false);
const [isLiked, setIsLiked] = useState(false);
@@ -142,9 +142,7 @@ export default function RecipeDetailClient({ recipe: initialRecipe }: { recipe:
if (!confirm(`Ta bort receptet "${recipe.name}"? Det går inte att ångra.`)) return;
setIsDeleting(true);
try {
const res = await fetch(`/api/recipes/${recipe.id}`, { method: 'DELETE',
headers: { Authorization: `Bearer ${session?.accessToken}` },
});
const res = await authFetch(`/api/recipes/${recipe.id}`, { method: 'DELETE' });
if (!res.ok) throw new Error(await parseErrorResponse(res));
router.push('/recipes');
} catch (err) {
@@ -166,9 +164,8 @@ export default function RecipeDetailClient({ recipe: initialRecipe }: { recipe:
quantity: Number(ing.quantity),
})),
};
const res = await fetch(`/api/recipes/${recipe.id}`, {
const res = await authFetch(`/api/recipes/${recipe.id}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${session?.accessToken}` },
body: JSON.stringify(body),
});
if (!res.ok) throw new Error(await parseErrorResponse(res));
@@ -188,9 +185,8 @@ export default function RecipeDetailClient({ recipe: initialRecipe }: { recipe:
setIsUploadingImage(true);
setImageError(null);
try {
const res = await fetch(`/api/recipes/${recipe.id}/image`, {
const res = await authFetch(`/api/recipes/${recipe.id}/image`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${session?.accessToken}` },
body: JSON.stringify({ sourceUrl: imageUrlInput.trim() }),
});
if (!res.ok) throw new Error(await parseErrorResponse(res));
@@ -2,7 +2,7 @@
import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
import { useAuthFetch } from '../../../lib/use-auth-fetch';
import { fetchJson } from '../../../lib/api';
import { parseErrorResponse } from '../../../lib/error-handler';
import type { Product } from '../../../features/inventory/types';
@@ -38,7 +38,7 @@ type Step = 'input' | 'review' | 'saving';
export default function ImportRecipePage() {
const router = useRouter();
const { data: session } = useSession();
const authFetch = useAuthFetch();
const [step, setStep] = useState<Step>('input');
const [markdown, setMarkdown] = useState('');
const [parsed, setParsed] = useState<ParseResult | null>(null);
@@ -136,9 +136,8 @@ export default function ImportRecipePage() {
};
try {
const res = await fetch('/api/recipes', {
const res = await authFetch('/api/recipes', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${session?.accessToken}` },
body: JSON.stringify(body),
});
@@ -2,7 +2,7 @@
import { useState, useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
import { useAuthFetch } from '../../../lib/use-auth-fetch';
import { fetchJson } from '../../../lib/api';
import { parseErrorResponse } from '../../../lib/error-handler';
import type { Product } from '../../../features/inventory/types';
@@ -37,7 +37,7 @@ type Step = 'input' | 'review' | 'saving' | 'saved';
export default function WriteRecipePage() {
const router = useRouter();
const { data: session } = useSession();
const authFetch = useAuthFetch();
const [step, setStep] = useState<Step>('input');
const [markdown, setMarkdown] = useState('');
const [parsed, setParsed] = useState<ParseResult | null>(null);
@@ -193,9 +193,8 @@ export default function WriteRecipePage() {
};
try {
const res = await fetch('/api/recipes', {
const res = await authFetch('/api/recipes', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${session?.accessToken}` },
body: JSON.stringify(body),
});