Fix: Form submission refresh bug and resolve TypeScript type errors

- Add explicit type=button to frame and step buttons to prevent unwanted form submission
- Move e.preventDefault() form submission logic into useNewGuide hook
- Fix TypeScript assignment error by adding 'title' to initial frame objects
- Export CompiledGuideType and update schema type references
This commit is contained in:
johannes-hernehult 2026-06-14 20:14:08 +02:00
parent 1bb6ddf403
commit 0f70457d29
5 changed files with 48 additions and 14 deletions

View file

@ -16,9 +16,18 @@ export default function Frame({
}) { }) {
return ( return (
<div> <div>
<button onClick={() => onRemove(frame.id)}>Remove Frame</button> <button type="button" onClick={() => onRemove(frame.id)}>
Remove Frame
</button>
<label>Title</label>
<input
type="text"
onChange={(e) => updateStep(frame.id, e.target.value)}
/>
<img src={URL.createObjectURL(frame.file)} alt={frame.title} /> <img src={URL.createObjectURL(frame.file)} alt={frame.title} />
<button onClick={() => addStep(frame.id)}>Add Step</button> <button type="button" onClick={() => addStep(frame.id)}>
Add Step
</button>
{frame.steps.map((step: StepType, index: number) => ( {frame.steps.map((step: StepType, index: number) => (
<Step <Step
key={step.id} key={step.id}

View file

@ -21,7 +21,9 @@ export default function Step({
onChange={(e) => updateStep(step.id, e.target.value)} onChange={(e) => updateStep(step.id, e.target.value)}
/> />
</label> </label>
<button onClick={() => removeStep(step.id)}>Remove Step</button> <button type="button" onClick={() => removeStep(step.id)}>
Remove Step
</button>
</div> </div>
); );
} }

View file

@ -1,8 +1,12 @@
import { useState } from "react"; import { useState } from "react";
import { type Frame, type Guide, type Steps } from "../../../lib/schemas"; import {
type CompiledGuideType,
type FrameType,
type GuideType,
} from "../../../lib/schemas";
export default function useNewGuide() { export default function useNewGuide() {
const [guide, setGuide] = useState<Guide>({ const [guide, setGuide] = useState<GuideType>({
id: crypto.randomUUID(), id: crypto.randomUUID(),
title: "", title: "",
description: "", description: "",
@ -10,7 +14,7 @@ export default function useNewGuide() {
updatedAt: new Date(), updatedAt: new Date(),
deletedAt: undefined, deletedAt: undefined,
}); });
const [frames, setFrames] = useState<Frame[]>([]); const [frames, setFrames] = useState<FrameType[]>([]);
const handleUpdateTitle = (title: string) => { const handleUpdateTitle = (title: string) => {
setGuide((prev) => ({ ...prev, title })); setGuide((prev) => ({ ...prev, title }));
@ -31,6 +35,7 @@ export default function useNewGuide() {
return { return {
id: frameId, id: frameId,
file: file, file: file,
title: "",
guideId: guide.id, guideId: guide.id,
steps: [{ id: crypto.randomUUID(), text: "", frameId: frameId }], steps: [{ id: crypto.randomUUID(), text: "", frameId: frameId }],
}; };
@ -87,9 +92,16 @@ export default function useNewGuide() {
); );
}; };
const handleSaveGuide = () => { const handleSaveGuide = (e: React.SubmitEvent<HTMLFormElement>) => {
const compiledGuide = { e.preventDefault();
...guide,
const compiledGuide: CompiledGuideType = {
id: guide.id,
title: guide.title,
description: guide.description,
createdAt: guide.createdAt,
updatedAt: guide.updatedAt,
deletedAt: guide.deletedAt,
frames, frames,
}; };

View file

@ -15,14 +15,10 @@ export default function NewGuide() {
handleUpdateStep, handleUpdateStep,
handleSaveGuide, handleSaveGuide,
} = useNewGuide(); } = useNewGuide();
const handleSubmitForm = (e: React.SubmitEvent<HTMLFormElement>) => {
e.preventDefault();
console.log(e.currentTarget);
};
return ( return (
<div className="new-guide"> <div className="new-guide">
<form className="new-guide__form" onSubmit={handleSubmitForm}> <form className="new-guide__form" onSubmit={(e) => handleSaveGuide(e)}>
<label> <label>
<span>Title</span> <span>Title</span>
<input type="text" name="title" /> <input type="text" name="title" />
@ -45,6 +41,12 @@ export default function NewGuide() {
updateStep={handleUpdateStep} updateStep={handleUpdateStep}
/> />
))} ))}
{frames.length === 0 && <p>No frames added yet.</p>}
{frames.length > 0 && <FileUpload onChange={handleAddFrames} />}
<button type="submit">Save</button>
</form> </form>
</div> </div>
); );

View file

@ -26,3 +26,12 @@ export const GuideSchema = z.object({
export type StepType = z.infer<typeof StepsSchema>; export type StepType = z.infer<typeof StepsSchema>;
export type FrameType = z.infer<typeof FrameSchema>; export type FrameType = z.infer<typeof FrameSchema>;
export type GuideType = z.infer<typeof GuideSchema>; export type GuideType = z.infer<typeof GuideSchema>;
export type CompiledGuideType = {
id: string;
title: string;
description: string | undefined;
createdAt: Date;
updatedAt: Date;
deletedAt: Date | undefined;
frames: FrameType[];
};