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
9 changes: 8 additions & 1 deletion client/src/components/layout/NewRecipeButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function NewRecipeButton({ trigger }: NewRecipeButtonProps) {
const { user } = useCurrentUser();
// hvordan steg i ny oppskrift man er på
const [currentStep, setCurrentStep] = useState(1);
const [isOpen, setIsOpen] = useState(false);

if (!user) {
return (
Expand All @@ -29,12 +30,18 @@ export function NewRecipeButton({ trigger }: NewRecipeButtonProps) {
<Dialog
trigger={trigger}
title="Ny oppskrift"
open={isOpen}
onOpenChange={setIsOpen}
headerContent={<RecipeStepIndicator currentStep={currentStep} />}
>
<NewRecipePage
currentStep={currentStep}
setCurrentStep={setCurrentStep}
onPublished={() => {
setIsOpen(false)
setCurrentStep(1)
}}
/>
</Dialog>
);
)
}
14 changes: 9 additions & 5 deletions client/src/components/ui/Dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import CloseIcon from '@mui/icons-material/Close'

// Definerer hvilke props Dialog-komponenten tar imot
type DialogProps = {
trigger: ReactNode // Elementet som åpner dialogen, for eksempel en knapp
title: string // Tittelen som vises øverst i dialogen
headerContent?: ReactNode // Valgfritt innhold i headeren, for eksempel stegindikator
children: ReactNode // Innholdet som vises inne i dialogen
trigger: ReactNode
title: string
headerContent?: ReactNode
children: ReactNode
open?: boolean
onOpenChange?: (open: boolean) => void
}


Expand All @@ -16,9 +18,11 @@ export function Dialog({
title,
headerContent,
children,
open,
onOpenChange,
}: DialogProps) {
return (
<RadixDialog.Root>
<RadixDialog.Root open={open} onOpenChange={onOpenChange}>
{/* Elementet som åpner dialogen */}
<RadixDialog.Trigger asChild>
{trigger}
Expand Down
123 changes: 76 additions & 47 deletions client/src/routes/NewRecipePage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState } from 'react'
import { AnimatePresence, motion, useReducedMotion } from 'motion/react'
import { useNavigate } from 'react-router'
import { useMutation } from '@apollo/client/react'
import { CREATE_RECIPE } from '../graphql/mutations'
Expand Down Expand Up @@ -63,19 +64,22 @@ function parseInstructionText(text: string): string[] {
type NewRecipePageProps = {
currentStep: number
setCurrentStep: (step: number) => void
onPublished: () => void
}

export default function NewRecipePage({
currentStep,
setCurrentStep,
onPublished,
}: NewRecipePageProps) {
const navigate = useNavigate()
const shouldReduceMotion = useReducedMotion()

const [recipeData, setRecipeData] = useState<RecipeFormData>({
title: '',
description: '',
imageFile: null,
prepTime: 0,
prepTime: 30,
servings: 4,
category: 'Middag',
tags: [],
Expand Down Expand Up @@ -194,8 +198,9 @@ export default function NewRecipePage({
}

// Navigerer til detaljsiden for oppskriften som nettopp ble opprettet.
// Forutsetter at appens rute er /recipes/:id.
navigate(`/recipes/${recipeId}`, { replace: true })
// Forutsetter at appens rute er /re cipes/:id.
onPublished()
navigate(`/recipes/${recipeId}`, { replace: true })
} catch (err) {
console.error('Kunne ikke publisere oppskrift:', err)
setPublishError(
Expand All @@ -206,55 +211,79 @@ export default function NewRecipePage({
}
}


return (
<div className="w-full">
{currentStep === 1 && (
<RecipeStep1
data={recipeData}
setData={setRecipeData}
onNext={() => setCurrentStep(2)}
/>
)}

{currentStep === 2 && (
<RecipeStep2
data={recipeData}
setData={setRecipeData}
onBack={() => setCurrentStep(1)}
onNext={() => setCurrentStep(3)}
/>
)}

{currentStep === 3 && (
<RecipeStep3
data={recipeData}
setData={setRecipeData}
onBack={() => setCurrentStep(2)}
onNext={() => setCurrentStep(4)}
/>
)}

{currentStep === 4 && (
<>
<RecipeStep4
data={recipeData}
onBack={() => setCurrentStep(3)}
onPublish={handlePublish}
/>

{(uploading || loading) && (
<p role="status" className="mt-3 text-olive">
Publiserer oppskriften...
</p>
<AnimatePresence mode="wait" initial={false}>
<motion.div
key={currentStep}
initial={{
opacity: 0,
x: shouldReduceMotion ? 0 : 25,
}}
animate={{
opacity: 1,
x: 0,
}}
exit={{
opacity: 0,
x: shouldReduceMotion ? 0 : -25,
}}
transition={{
duration: shouldReduceMotion ? 0 : 0.25,
ease: 'easeInOut',
}}
>
{currentStep === 1 && (
<RecipeStep1
data={recipeData}
setData={setRecipeData}
onNext={() => setCurrentStep(2)}
/>
)}

{(publishError || error) && (
<p role="alert" className="mt-3 text-primary">
Kunne ikke publisere oppskriften: {publishError || error?.message}
</p>
{currentStep === 2 && (
<RecipeStep2
data={recipeData}
setData={setRecipeData}
onBack={() => setCurrentStep(1)}
onNext={() => setCurrentStep(3)}
/>
)}
</>
)}

{currentStep === 3 && (
<RecipeStep3
data={recipeData}
setData={setRecipeData}
onBack={() => setCurrentStep(2)}
onNext={() => setCurrentStep(4)}
/>
)}

{currentStep === 4 && (
<>
<RecipeStep4
data={recipeData}
onBack={() => setCurrentStep(3)}
onPublish={handlePublish}
/>

{(uploading || loading) && (
<p role="status" className="mt-3 text-olive">
Publiserer oppskriften...
</p>
)}

{(publishError || error) && (
<p role="alert" className="mt-3 text-primary">
Kunne ikke publisere oppskriften: {publishError || error?.message}
</p>
)}
</>
)}
</motion.div>
</AnimatePresence>
</div>
)

}