Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 107 additions & 16 deletions client/src/components/new-recipe/RecipeStep1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import { useState } from 'react'
import type { Dispatch, SetStateAction } from 'react'
import Rating from '@mui/material/Rating'

import { Button } from '../ui/Button'
import { Field } from '../ui/Field'
import { Input, Textarea } from '../ui/Input'
import { Tag } from '../ui/Tag'
import { ImageUpload } from '../ui/ImageUpload'
import TagDialog from './TagDialog'

import type { RecipeFormData } from '../../routes/NewRecipePage'

// Sånn at informasjonen blir lagret mellom stegene
Expand Down Expand Up @@ -49,7 +50,10 @@ export default function RecipeStep1({
key: K,
value: RecipeFormData[K],
) => {
setData((prev) => ({ ...prev, [key]: value }))
setData((prev) => ({
...prev,
[key]: value,
}))
}

// Legger til eller fjerner en tag (maks 6 totalt)
Expand All @@ -69,6 +73,35 @@ export default function RecipeStep1({
(tag) => !dietaryTags.includes(tag),
)

// Når brukeren velger et bilde
const handleImageChange = (
event: React.ChangeEvent<HTMLInputElement>,
) => {
const file = event.target.files?.[0]

if (!file) return

const allowedTypes = [
'image/jpeg',
'image/png',
'image/webp',
]

if (!allowedTypes.includes(file.type)) {
alert('Du kan bare laste opp JPG, PNG eller WebP.')
event.target.value = ''
return
}

if (file.size > 5 * 1024 * 1024) {
alert('Bildet kan ikke være større enn 5 MB.')
event.target.value = ''
return
}

update('imageFile', file)
}

return (
<div className="w-full">
<p className="mb-3 text-sm text-olive">
Expand All @@ -78,13 +111,50 @@ export default function RecipeStep1({
<div className="grid gap-4 md:grid-cols-2">
{/* VENSTRE SIDE */}
<div className="space-y-2">
{/* BILDEOPPLASTING */}
<Field label="Bilde">
<ImageUpload
value={data.imageFile}
onChange={(file) => update('imageFile', file)}
/>
<div className="space-y-2">
<label className="upload-button flex cursor-pointer flex-col items-center justify-center">
<span className="text-sm font-semibold text-primary">
{data.imageFile
? 'Bytt bilde'
: 'Last opp bilde'}
</span>

<span className="mt-1 text-xs text-olive">
PNG, JPG eller WebP (maks 5 MB)
</span>

<input
type="file"
accept="image/jpeg,image/png,image/webp"
onChange={handleImageChange}
className="sr-only"
/>
</label>

{/* Viser valgt bilde */}
{data.imageFile && (
<div className="relative overflow-hidden rounded-medium border border-peach">
<img
src={URL.createObjectURL(data.imageFile)}
alt="Forhåndsvisning av oppskriftsbilde"
className="h-40 w-full object-cover"
/>

<button
type="button"
onClick={() => update('imageFile', null)}
className="absolute right-2 top-2 cursor-pointer rounded-full bg-background px-3 py-1 text-xs font-semibold text-primary shadow-sm"
>
Fjern bilde ×
</button>
</div>
)}
</div>
</Field>

{/* BESKRIVELSE */}
<Field
label="Kort beskrivelse"
htmlFor="description"
Expand All @@ -101,17 +171,20 @@ export default function RecipeStep1({
/>
</Field>

{/* VURDERING */}
<Field label="Vurdering" required>
<Rating
name="recipe-rating"
value={data.rating}
precision={1}
sx={{ color: '#9A2A47' }}
onChange={(_, value) => update('rating', value)}
onChange={(_, value) =>
update('rating', value)
}
/>
</Field>

{/* Lenke til Instagram Reel eller TikTok */}
{/* VIDEO */}
<Field
label="Instagram Reel / TikTok (valgfritt)"
htmlFor="video-url"
Expand All @@ -130,6 +203,7 @@ export default function RecipeStep1({

{/* HØYRE SIDE */}
<div className="space-y-3">
{/* OPPSKRIFTSTITTEL */}
<Field
label="Navn på oppskrift"
htmlFor="recipe-title"
Expand All @@ -145,7 +219,7 @@ export default function RecipeStep1({
/>
</Field>

{/* Tid og porsjoner */}
{/* TID OG PORSJONER */}
<div className="grid grid-cols-2 gap-4">
<Field
label="Tilberedningstid"
Expand All @@ -159,9 +233,13 @@ export default function RecipeStep1({
min={1}
value={data.prepTime}
onChange={(e) =>
update('prepTime', Number(e.target.value))
update(
'prepTime',
Number(e.target.value),
)
}
/>

<span className="text-sm text-olive">
min
</span>
Expand Down Expand Up @@ -193,7 +271,10 @@ export default function RecipeStep1({
className="stepper-button"
aria-label="Øk antall porsjoner"
onClick={() =>
update('servings', data.servings + 1)
update(
'servings',
data.servings + 1,
)
}
>
+
Expand All @@ -202,6 +283,7 @@ export default function RecipeStep1({
</Field>
</div>

{/* KATEGORI */}
<Field label="Kategori" required>
<div className="flex flex-wrap gap-2">
{categories.map((category) => (
Expand Down Expand Up @@ -235,7 +317,9 @@ export default function RecipeStep1({
{/* Åpner dialogen med flere tags */}
<Tag
selected={false}
onClick={() => setTagDialogOpen(true)}
onClick={() =>
setTagDialogOpen(true)
}
>
Annet +
</Tag>
Expand All @@ -256,7 +340,7 @@ export default function RecipeStep1({
</div>
)}

{/* Viser hvor mange tags som er valgt */}
{/* Antall valgte tags */}
<p className="mt-2 text-xs text-olive">
{data.tags.length} av {MAX_TAGS} tags valgt
</p>
Expand All @@ -266,7 +350,10 @@ export default function RecipeStep1({

{/* KNAPPER */}
<div className="mt-3 flex items-center justify-end gap-5 border-t border-peach pt-3">
<Button variant="ghost" size="small">
<Button
variant="ghost"
size="small"
>
Lagre utkast
</Button>

Expand All @@ -283,8 +370,12 @@ export default function RecipeStep1({
<TagDialog
open={tagDialogOpen}
selectedTags={data.tags}
onChange={(tags) => update('tags', tags)}
onClose={() => setTagDialogOpen(false)}
onChange={(tags) =>
update('tags', tags)
}
onClose={() =>
setTagDialogOpen(false)
}
/>
</div>
)
Expand Down
Loading