Add recipe deletion functionality and enhance inventory consumption details

This commit is contained in:
Nils-Johan Gynther
2026-04-10 18:44:06 +02:00
parent a743f832a2
commit dd17656e4c
7 changed files with 174 additions and 49 deletions
+105 -37
View File
@@ -58,6 +58,32 @@ export default function RecipePreview({ recipes }: Props) {
const [error, setError] = useState<string | null>(null);
const [isPending, startTransition] = useTransition();
const selectAndLoad = (id: string) => {
setSelectedRecipeId(id);
setError(null);
setPreview(null);
startTransition(async () => {
try {
const res = await fetch(`/api/recipe-preview-proxy?id=${id}`, {
method: 'GET',
cache: 'no-store',
});
if (!res.ok) {
const errorMessage = await parseErrorResponse(res);
throw new Error(errorMessage);
}
const data: RecipeInventoryPreview = await res.json();
setPreview(data);
} catch (err) {
const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade.';
setError(message);
}
});
};
const loadPreview = () => {
setError(null);
setPreview(null);
@@ -88,46 +114,49 @@ export default function RecipePreview({ recipes }: Props) {
});
};
const listedRecipes = recipes.slice(0, 10);
return (
<section style={{ display: 'grid', gap: '1rem' }}>
<div
style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '1rem',
display: 'grid',
gap: '0.75rem',
}}
>
<h2 style={{ margin: 0 }}>Recept mot hemmavaror</h2>
<div style={{ display: 'grid', gridTemplateColumns: '1fr auto', gap: '1rem', alignItems: 'start' }}>
<div
style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '1rem',
display: 'grid',
gap: '0.75rem',
}}
>
<h2 style={{ margin: 0 }}>Recept mot hemmavaror</h2>
<label>
Recept
<br />
<select
value={selectedRecipeId}
onChange={(e) => setSelectedRecipeId(e.target.value)}
style={{ width: '100%', padding: '0.5rem' }}
>
<option value="">Välj recept</option>
{recipes.map((recipe) => (
<option key={recipe.id} value={recipe.id}>
{recipe.name}
</option>
))}
</select>
</label>
<label>
Recept
<br />
<select
value={selectedRecipeId}
onChange={(e) => setSelectedRecipeId(e.target.value)}
style={{ width: '100%', padding: '0.5rem' }}
>
<option value="">Välj recept</option>
{recipes.map((recipe) => (
<option key={recipe.id} value={recipe.id}>
{recipe.name}
</option>
))}
</select>
</label>
<div style={{ display: 'flex', gap: '0.75rem' }}>
<button
type="button"
onClick={loadPreview}
disabled={isPending}
style={{ padding: '0.6rem 1rem' }}
>
{isPending ? 'Hämtar preview...' : 'Visa preview'}
</button>
{selectedRecipeId && (
<div style={{ display: 'flex', gap: '0.75rem' }}>
<button
type="button"
onClick={loadPreview}
disabled={isPending}
style={{ padding: '0.6rem 1rem' }}
>
{isPending ? 'Hämtar preview...' : 'Visa preview'}
</button>
{selectedRecipeId && (
<Link
href={`/recipes/${selectedRecipeId}/edit`}
style={{
@@ -144,9 +173,48 @@ export default function RecipePreview({ recipes }: Props) {
Redigera recept
</Link>
)}
</div>
{error ? <p style={{ color: 'crimson', margin: 0 }}>{error}</p> : null}
</div>
{error ? <p style={{ color: 'crimson', margin: 0 }}>{error}</p> : null}
{/* Receptlista till höger */}
<div
style={{
border: '1px solid #ddd',
borderRadius: '8px',
padding: '1rem',
minWidth: '180px',
maxWidth: '220px',
}}
>
<h3 style={{ margin: '0 0 0.75rem 0', fontSize: '1rem' }}>Mina recept</h3>
<ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'grid', gap: '0.4rem' }}>
{listedRecipes.map((recipe) => (
<li key={recipe.id}>
<button
type="button"
disabled={isPending}
onClick={() => selectAndLoad(String(recipe.id))}
style={{
width: '100%',
textAlign: 'left',
padding: '0.4rem 0.6rem',
background: String(recipe.id) === selectedRecipeId ? '#e8f0fe' : 'transparent',
border: `1px solid ${String(recipe.id) === selectedRecipeId ? '#4285f4' : '#eee'}`,
borderRadius: '4px',
cursor: 'pointer',
fontWeight: String(recipe.id) === selectedRecipeId ? 600 : 400,
color: String(recipe.id) === selectedRecipeId ? '#1a56db' : '#333',
fontSize: '0.9rem',
}}
>
{recipe.name}
</button>
</li>
))}
</ul>
</div>
</div>
{preview ? (