begin implementation of edit story functionality
This commit is contained in:
		
							parent
							
								
									0ab70fec08
								
							
						
					
					
						commit
						dc9b72f0e8
					
				
							
								
								
									
										
											BIN
										
									
								
								prisma/dev.db
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								prisma/dev.db
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
					@ -11,7 +11,7 @@ import { prepGenreData, prepStoryData } from "./validate"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//TODO - data validation, error handling, unauthorized access handling
 | 
					//TODO - data validation, error handling, unauthorized access handling
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function createStory(data: Story & { genres: number[] }): Promise<Story | boolean | undefined> {
 | 
					export async function createStory(data: Story & { genres: number[] }): Promise<{ success: string }> {
 | 
				
			||||||
	// will return undefined if middleware authorization fails
 | 
						// will return undefined if middleware authorization fails
 | 
				
			||||||
	"use server"
 | 
						"use server"
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ export async function createStory(data: Story & { genres: number[] }): Promise<S
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		revalidatePath("/story")
 | 
							revalidatePath("/story")
 | 
				
			||||||
		return res
 | 
							return { success: `Created the story '${data.title}'.` }
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ export async function createStory(data: Story & { genres: number[] }): Promise<S
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function createPub(data: Pub & { genres: number[] }): Promise<Pub | boolean | undefined> {
 | 
					export async function createPub(data: Pub & { genres: number[] }): Promise<{ success: string }> {
 | 
				
			||||||
	"use server"
 | 
						"use server"
 | 
				
			||||||
	//prepare data
 | 
						//prepare data
 | 
				
			||||||
	const pubData = {
 | 
						const pubData = {
 | 
				
			||||||
| 
						 | 
					@ -67,7 +67,7 @@ export async function createPub(data: Pub & { genres: number[] }): Promise<Pub |
 | 
				
			||||||
				{ genres: { set: genresArray } }
 | 
									{ genres: { set: genresArray } }
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		revalidatePath("/publication")
 | 
							revalidatePath("/publication")
 | 
				
			||||||
		return genresRes
 | 
							return { success: `Created the publication '${data.title}'.` }
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ export async function createPub(data: Pub & { genres: number[] }): Promise<Pub |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function createSub(data: Sub): Promise<Sub | undefined> {
 | 
					export async function createSub(data: Sub): Promise<Sub | boolean> {
 | 
				
			||||||
	"use server"
 | 
						"use server"
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
		subSchema.parse(data)
 | 
							subSchema.parse(data)
 | 
				
			||||||
| 
						 | 
					@ -86,6 +86,6 @@ export async function createSub(data: Sub): Promise<Sub | undefined> {
 | 
				
			||||||
		return res
 | 
							return res
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return undefined
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,15 +0,0 @@
 | 
				
			||||||
"use server"
 | 
					 | 
				
			||||||
import prisma from "./db"
 | 
					 | 
				
			||||||
import { revalidatePath } from "next/cache"
 | 
					 | 
				
			||||||
import { redirect } from "next/navigation"
 | 
					 | 
				
			||||||
import { SubForm } from "app/ui/forms/sub"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export async function editSubmission(data: SubForm) {
 | 
					 | 
				
			||||||
	const res = await prisma.sub.update({
 | 
					 | 
				
			||||||
		where: { id: data.id },
 | 
					 | 
				
			||||||
		data
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	console.log(`updated ${data} to ${res}`)
 | 
					 | 
				
			||||||
	revalidatePath("/submission")
 | 
					 | 
				
			||||||
	redirect("/submission")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
"use server"
 | 
					"use server"
 | 
				
			||||||
import { Genre, Story, Sub } from "@prisma/client"
 | 
					import { prepGenreData, prepPubData, prepStoryData } from "./validate"
 | 
				
			||||||
 | 
					import { Genre, Pub, Story, Sub } from "@prisma/client"
 | 
				
			||||||
import prisma from "./db"
 | 
					import prisma from "./db"
 | 
				
			||||||
import { revalidatePath } from "next/cache"
 | 
					import { revalidatePath } from "next/cache"
 | 
				
			||||||
import { redirect } from "next/navigation"
 | 
					import { redirect } from "next/navigation"
 | 
				
			||||||
| 
						 | 
					@ -21,7 +22,7 @@ export async function updateField({ datum, table, column, id, pathname }: { datu
 | 
				
			||||||
		return res
 | 
							return res
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return undefined
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,11 +40,11 @@ export async function updateGenres({ genres, table, id, pathname }: { genres: {
 | 
				
			||||||
		return res
 | 
							return res
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return undefined
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function updateSub(data: Sub): Promise<Sub | undefined> {
 | 
					export async function updateSub(data: Sub): Promise<Sub | boolean> {
 | 
				
			||||||
	"use server"
 | 
						"use server"
 | 
				
			||||||
	try {
 | 
						try {
 | 
				
			||||||
		subSchema.parse(data)
 | 
							subSchema.parse(data)
 | 
				
			||||||
| 
						 | 
					@ -52,35 +53,62 @@ export async function updateSub(data: Sub): Promise<Sub | undefined> {
 | 
				
			||||||
		return res
 | 
							return res
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return undefined
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function updateStory(data: Story & { genres: number[] }): Promise<Story | undefined> {
 | 
					export async function updateStory(data: Story & { genres: number[] }): Promise<Story | boolean> {
 | 
				
			||||||
	"use server"
 | 
						"use server"
 | 
				
			||||||
	//prepare data
 | 
					 | 
				
			||||||
	const genresArray = data.genres.map((e) => { return { id: e } })
 | 
					 | 
				
			||||||
	const storyData = {
 | 
					 | 
				
			||||||
		title: data.title,
 | 
					 | 
				
			||||||
		word_count: data.word_count,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	//prepare schemas
 | 
					 | 
				
			||||||
	const schema = storySchema.omit({ id: true, genres: true })
 | 
					 | 
				
			||||||
	const genreSchema = z.object({ id: z.number() })
 | 
					 | 
				
			||||||
	const genresSchema = z.array(genreSchema)
 | 
					 | 
				
			||||||
	try {
 | 
					 | 
				
			||||||
		//validate
 | 
					 | 
				
			||||||
		schema.safeParse(storyData)
 | 
					 | 
				
			||||||
		genresSchema.safeParse(genresArray)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							//prep and validate
 | 
				
			||||||
 | 
							const storyData = await prepStoryData(data)
 | 
				
			||||||
 | 
							const genresArray = await prepGenreData(data.genres)
 | 
				
			||||||
 | 
							//submit
 | 
				
			||||||
 | 
							const res = prisma.story.update({
 | 
				
			||||||
 | 
								where: { id: data.id },
 | 
				
			||||||
 | 
								data: storyData
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							await prisma.story.update({
 | 
				
			||||||
 | 
								where: { id: data.id },
 | 
				
			||||||
 | 
								data: {
 | 
				
			||||||
 | 
									genres: { set: genresArray }
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
	} catch (error) {
 | 
						} catch (error) {
 | 
				
			||||||
		console.error(error)
 | 
							console.error(error)
 | 
				
			||||||
		return undefined
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function updatePub(data: Pub & { genres: number[] }): Promise<Pub | boolean> {
 | 
				
			||||||
 | 
						"use server"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						try {
 | 
				
			||||||
 | 
							//prep and validate
 | 
				
			||||||
 | 
							const pubData = await prepPubData
 | 
				
			||||||
 | 
								(data)
 | 
				
			||||||
 | 
							const genresArray = await prepGenreData(data.genres)
 | 
				
			||||||
 | 
							//submit
 | 
				
			||||||
 | 
							const res = prisma.pub.update({
 | 
				
			||||||
 | 
								where: { id: data.id },
 | 
				
			||||||
 | 
								data: pubData
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							await prisma.pub.update({
 | 
				
			||||||
 | 
								where: { id: data.id },
 | 
				
			||||||
 | 
								data: {
 | 
				
			||||||
 | 
									genres: { set: genresArray }
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
 | 
						} catch (error) {
 | 
				
			||||||
 | 
							console.error(error)
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,26 +1,30 @@
 | 
				
			||||||
import { z } from "zod";
 | 
					import { z } from "zod";
 | 
				
			||||||
import { storySchema } from "app/ui/forms/schemas";
 | 
					import { storySchema } from "app/ui/forms/schemas";
 | 
				
			||||||
import { Story } from "@prisma/client";
 | 
					import { Pub, Story } from "@prisma/client";
 | 
				
			||||||
 | 
					import { pubSchema } from "app/ui/forms/schemas";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//schemas
 | 
					//schemas
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const schema = storySchema.omit({ id: true, genres: true })
 | 
					const storySchemaTrimmed = storySchema.omit({ genres: true })
 | 
				
			||||||
 | 
					const pubSchemaTrimmed = pubSchema.omit({ genres: true })
 | 
				
			||||||
const genreSchema = z.object({ id: z.number() })
 | 
					const genreSchema = z.object({ id: z.number() })
 | 
				
			||||||
const genresSchema = z.array(genreSchema)
 | 
					const genresSchema = z.array(genreSchema)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function prepStoryData(data: Story & { genres: number[] }): Promise<{ title: string, word_count: number }> {
 | 
					export async function prepStoryData(data: Story & { genres: number[] }): Promise<{ title: string, word_count: number }> {
 | 
				
			||||||
	const storyData = {
 | 
						const storyData = structuredClone(data)
 | 
				
			||||||
		title: data.title,
 | 
						delete storyData.genres
 | 
				
			||||||
		word_count: data.word_count,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	//prepare schemas
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	//throw an error if validation fails
 | 
						//throw an error if validation fails
 | 
				
			||||||
	schema.safeParse(storyData)
 | 
						storySchemaTrimmed.safeParse(storyData)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	return storyData
 | 
						return storyData
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function prepPubData(data: Pub & { genres: number[] }): Promise<Pub | Boolean> {
 | 
				
			||||||
 | 
						const pubData = structuredClone(data)
 | 
				
			||||||
 | 
						delete pubData.genres
 | 
				
			||||||
 | 
						pubSchemaTrimmed.safeParse(pubData)
 | 
				
			||||||
 | 
						return pubData
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export async function prepGenreData(data: number[]): Promise<{ id: number }[]> {
 | 
					export async function prepGenreData(data: number[]): Promise<{ id: number }[]> {
 | 
				
			||||||
	"use server"
 | 
						"use server"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +29,7 @@ export default function CreatePubDialog({ genres }: ComponentProps<"div"> & { ge
 | 
				
			||||||
          <DialogTitle>New publication</DialogTitle>
 | 
					          <DialogTitle>New publication</DialogTitle>
 | 
				
			||||||
          <DialogDescription>Create an entry for a new publication i.e. a place you intend to submit stories to.</DialogDescription>
 | 
					          <DialogDescription>Create an entry for a new publication i.e. a place you intend to submit stories to.</DialogDescription>
 | 
				
			||||||
        </DialogHeader>
 | 
					        </DialogHeader>
 | 
				
			||||||
        <PubForm createPub={createPub} genres={genres} closeDialog={closeDialog} />
 | 
					        <PubForm dbAction={createPub} genres={genres} closeDialog={closeDialog} />
 | 
				
			||||||
        <DialogFooter>
 | 
					        <DialogFooter>
 | 
				
			||||||
          <Button form="pubform">Submit</Button>
 | 
					          <Button form="pubform">Submit</Button>
 | 
				
			||||||
        </DialogFooter>
 | 
					        </DialogFooter>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,40 @@
 | 
				
			||||||
 | 
					"use client"
 | 
				
			||||||
 | 
					import { Dialog, DialogHeader, DialogTrigger, DialogContent, DialogClose, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
 | 
				
			||||||
 | 
					import { Button } from "@/components/ui/button";
 | 
				
			||||||
 | 
					import { ComponentProps } from "react";
 | 
				
			||||||
 | 
					import { Genre } from "@prisma/client";
 | 
				
			||||||
 | 
					import { createPub } from "app/lib/create";
 | 
				
			||||||
 | 
					import PubForm from "app/ui/forms/pub";
 | 
				
			||||||
 | 
					import { Plus } from "lucide-react";
 | 
				
			||||||
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function CreatePubDialog({ genres }: ComponentProps<"div"> & { genres: Genre[] }) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [isOpen, setIsOpen] = useState(false)
 | 
				
			||||||
 | 
					  function closeDialog() {
 | 
				
			||||||
 | 
					    setIsOpen(false)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <Dialog open={isOpen} onOpenChange={setIsOpen}>
 | 
				
			||||||
 | 
					      <DialogTrigger asChild>
 | 
				
			||||||
 | 
					        <Button>
 | 
				
			||||||
 | 
					          <span className="hidden md:block">Create new publication</span>
 | 
				
			||||||
 | 
					          <Plus className="block md:hidden" />
 | 
				
			||||||
 | 
					        </Button>
 | 
				
			||||||
 | 
					      </DialogTrigger>
 | 
				
			||||||
 | 
					      <DialogContent>
 | 
				
			||||||
 | 
					        <DialogHeader>
 | 
				
			||||||
 | 
					          <DialogTitle>Edit publication</DialogTitle>
 | 
				
			||||||
 | 
					          <DialogDescription>Modify an entry for an existing publication.</DialogDescription>
 | 
				
			||||||
 | 
					        </DialogHeader>
 | 
				
			||||||
 | 
					        <PubForm dbAction={createPub} genres={genres} closeDialog={closeDialog} />
 | 
				
			||||||
 | 
					        <DialogFooter>
 | 
				
			||||||
 | 
					          <Button form="pubform">Submit</Button>
 | 
				
			||||||
 | 
					        </DialogFooter>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      </DialogContent>
 | 
				
			||||||
 | 
					    </Dialog>
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ export default function CreateStoryDialog({ genres }: ComponentProps<"div"> & {
 | 
				
			||||||
          <DialogTitle>New story</DialogTitle>
 | 
					          <DialogTitle>New story</DialogTitle>
 | 
				
			||||||
          <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
					          <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
				
			||||||
        </DialogHeader>
 | 
					        </DialogHeader>
 | 
				
			||||||
        <StoryForm createStory={createStory} genres={genres} className="" closeDialog={closeDialog} />
 | 
					        <StoryForm dbAction={createStory} genres={genres} className="" closeDialog={closeDialog} />
 | 
				
			||||||
        <DialogFooter>
 | 
					        <DialogFooter>
 | 
				
			||||||
          <Button form="storyform">Submit</Button>
 | 
					          <Button form="storyform">Submit</Button>
 | 
				
			||||||
        </DialogFooter>
 | 
					        </DialogFooter>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,28 @@
 | 
				
			||||||
 | 
					"use client"
 | 
				
			||||||
 | 
					import { createStory } from "app/lib/create"
 | 
				
			||||||
 | 
					import { Dialog, DialogHeader, DialogTrigger, DialogContent, DialogClose, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
 | 
				
			||||||
 | 
					import { Button } from "@/components/ui/button";
 | 
				
			||||||
 | 
					import { ComponentProps, useState } from "react";
 | 
				
			||||||
 | 
					import { Genre, Story } from "@prisma/client";
 | 
				
			||||||
 | 
					import StoryForm from "app/ui/forms/story";
 | 
				
			||||||
 | 
					import { Plus } from "lucide-react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function EditStoryDialog({ genres, closeDialog, defaults }: ComponentProps<"div"> & { genres: Genre[], closeDialog: () => void, defaults: Story }) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <>
 | 
				
			||||||
 | 
					      <DialogHeader>
 | 
				
			||||||
 | 
					        <DialogTitle>Edit story</DialogTitle>
 | 
				
			||||||
 | 
					        <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
				
			||||||
 | 
					      </DialogHeader>
 | 
				
			||||||
 | 
					      <StoryForm dbAction={createStory} genres={genres} className="" closeDialog={closeDialog} defaults={defaults} />
 | 
				
			||||||
 | 
					      <DialogFooter>
 | 
				
			||||||
 | 
					        <Button form="storyform">Submit</Button>
 | 
				
			||||||
 | 
					      </DialogFooter>
 | 
				
			||||||
 | 
					    </>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,16 +10,8 @@ import { Plus } from "lucide-react";
 | 
				
			||||||
import { useState } from "react";
 | 
					import { useState } from "react";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type CreateSubDefaults = {
 | 
					 | 
				
			||||||
  subId?: number,
 | 
					 | 
				
			||||||
  storyId: number,
 | 
					 | 
				
			||||||
  pubId: number,
 | 
					 | 
				
			||||||
  submitted: Date,
 | 
					 | 
				
			||||||
  responded: Date,
 | 
					 | 
				
			||||||
  respoonseId: number
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function CreateSubmissionDialog({ stories, pubs, responses, defaults }: ComponentProps<"div"> & { stories: Story[], pubs: Pub[], responses: Response[], defaults?: CreateSubDefaults }) {
 | 
					export default function CreateSubmissionDialog({ stories, pubs, responses }: ComponentProps<"div"> & { stories: Story[], pubs: Pub[], responses: Response[] }) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [isOpen, setIsOpen] = useState(false)
 | 
					  const [isOpen, setIsOpen] = useState(false)
 | 
				
			||||||
  function closeDialog() {
 | 
					  function closeDialog() {
 | 
				
			||||||
| 
						 | 
					@ -39,7 +31,7 @@ export default function CreateSubmissionDialog({ stories, pubs, responses, defau
 | 
				
			||||||
          <DialogTitle>New submission</DialogTitle>
 | 
					          <DialogTitle>New submission</DialogTitle>
 | 
				
			||||||
          <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
					          <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
				
			||||||
        </DialogHeader>
 | 
					        </DialogHeader>
 | 
				
			||||||
        <SubmissionForm pubs={pubs} responses={responses} stories={stories} defaults={defaults} closeDialog={closeDialog} />
 | 
					        <SubmissionForm pubs={pubs} responses={responses} stories={stories} closeDialog={closeDialog} />
 | 
				
			||||||
        <DialogFooter>
 | 
					        <DialogFooter>
 | 
				
			||||||
          <Button form="subform">Submit</Button>
 | 
					          <Button form="subform">Submit</Button>
 | 
				
			||||||
        </DialogFooter>
 | 
					        </DialogFooter>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -777,6 +777,14 @@ body {
 | 
				
			||||||
  margin-top: 1.5rem;
 | 
					  margin-top: 1.5rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mt-auto {
 | 
				
			||||||
 | 
					  margin-top: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.mb-4 {
 | 
				
			||||||
 | 
					  margin-bottom: 1rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.block {
 | 
					.block {
 | 
				
			||||||
  display: block;
 | 
					  display: block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -879,6 +887,10 @@ body {
 | 
				
			||||||
  height: 100vh;
 | 
					  height: 100vh;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.h-5\/6 {
 | 
				
			||||||
 | 
					  height: 83.333333%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.max-h-96 {
 | 
					.max-h-96 {
 | 
				
			||||||
  max-height: 24rem;
 | 
					  max-height: 24rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -964,6 +976,10 @@ body {
 | 
				
			||||||
  width: 100vw;
 | 
					  width: 100vw;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.w-5\/6 {
 | 
				
			||||||
 | 
					  width: 83.333333%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.min-w-\[8rem\] {
 | 
					.min-w-\[8rem\] {
 | 
				
			||||||
  min-width: 8rem;
 | 
					  min-width: 8rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1251,6 +1267,11 @@ body {
 | 
				
			||||||
  border-top-right-radius: 1.5rem;
 | 
					  border-top-right-radius: 1.5rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.rounded-l-3xl {
 | 
				
			||||||
 | 
					  border-top-left-radius: 1.5rem;
 | 
				
			||||||
 | 
					  border-bottom-left-radius: 1.5rem;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.rounded-tl-3xl {
 | 
					.rounded-tl-3xl {
 | 
				
			||||||
  border-top-left-radius: 1.5rem;
 | 
					  border-top-left-radius: 1.5rem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,13 +17,13 @@ import { toast } from "@/components/ui/use-toast"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { randomPublicationTitle } from "app/lib/shortStoryTitleGenerator"
 | 
					import { randomPublicationTitle } from "app/lib/shortStoryTitleGenerator"
 | 
				
			||||||
import { ComponentProps } from "react"
 | 
					import { ComponentProps } from "react"
 | 
				
			||||||
import { Genre } from "@prisma/client"
 | 
					import { Genre, Pub } from "@prisma/client"
 | 
				
			||||||
import GenrePicker from "./genrePicker"
 | 
					import GenrePicker from "./genrePicker"
 | 
				
			||||||
import { pubSchema } from "./schemas"
 | 
					import { pubSchema } from "./schemas"
 | 
				
			||||||
import { useRouter } from "next/navigation"
 | 
					import { useRouter } from "next/navigation"
 | 
				
			||||||
import { Ban } from "lucide-react"
 | 
					import { Ban } from "lucide-react"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function PubForm({ genres, createPub, className, closeDialog }: ComponentProps<"div"> & { genres: Array<Genre>, createPub: (data: any) => void, closeDialog: () => void }) {
 | 
					export default function PubForm({ genres, dbAction, className, closeDialog, defaults }: ComponentProps<"div"> & { genres: Array<Genre>, dbAction: (data: any) => Promise<{ success: string }>, closeDialog: () => void, defaults?: Pub }) {
 | 
				
			||||||
	const form = useForm<z.infer<typeof pubSchema>>({
 | 
						const form = useForm<z.infer<typeof pubSchema>>({
 | 
				
			||||||
		resolver: zodResolver(pubSchema),
 | 
							resolver: zodResolver(pubSchema),
 | 
				
			||||||
		defaultValues: {
 | 
							defaultValues: {
 | 
				
			||||||
| 
						 | 
					@ -38,9 +38,9 @@ export default function PubForm({ genres, createPub, className, closeDialog }: C
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function onSubmit(values: z.infer<typeof pubSchema>) {
 | 
						async function onSubmit(values: z.infer<typeof pubSchema>) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			const res = await createPub(values)
 | 
								const res = await dbAction(values)
 | 
				
			||||||
			if (!res) throw new Error("something went wrong")
 | 
								if (!res) throw new Error("something went wrong")
 | 
				
			||||||
			toast({ title: "Successfully submitted:", description: values.title })
 | 
								toast({ title: "Success!", description: res.success })
 | 
				
			||||||
			router.refresh()
 | 
								router.refresh()
 | 
				
			||||||
			closeDialog()
 | 
								closeDialog()
 | 
				
			||||||
		} catch (error) {
 | 
							} catch (error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,23 +29,25 @@ export const formSchema = z.object({
 | 
				
			||||||
	genres: z.array(z.number())
 | 
						genres: z.array(z.number())
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function StoryForm({ genres, createStory, className, closeDialog }: ComponentProps<"div"> & { genres: Array<Genre>, createStory: (data: any) => void, className: string, closeDialog: () => void }) {
 | 
					export default function StoryForm({ genres, dbAction, className, closeDialog, defaults }: ComponentProps<"div"> & { genres: Array<Genre>, dbAction: (data: any) => Promise<{ success: string }>, className: string, closeDialog: () => void, defaults?: Story }) {
 | 
				
			||||||
	const form = useForm<z.infer<typeof formSchema>>({
 | 
						const form = useForm<z.infer<typeof formSchema>>({
 | 
				
			||||||
		resolver: zodResolver(formSchema),
 | 
							resolver: zodResolver(formSchema),
 | 
				
			||||||
		defaultValues: {
 | 
							defaultValues: {
 | 
				
			||||||
			word_count: 500,
 | 
								title: defaults?.title ?? "",
 | 
				
			||||||
 | 
								word_count: defaults?.word_count ?? 500,
 | 
				
			||||||
			genres: []
 | 
								genres: []
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
						console.log("DEFAULTS: " + defaults)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	const router = useRouter()
 | 
						const router = useRouter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	async function onSubmit(values: z.infer<typeof formSchema>) {
 | 
						async function onSubmit(values: z.infer<typeof formSchema>) {
 | 
				
			||||||
		try {
 | 
							try {
 | 
				
			||||||
			const res = await createStory(values)
 | 
								const res = await dbAction(values)
 | 
				
			||||||
			//server actions return undefined if middleware authentication fails
 | 
								//server actions return undefined if middleware authentication fails
 | 
				
			||||||
			if (!res) throw new Error("something went wrong")
 | 
								if (!res.success) throw new Error("something went wrong")
 | 
				
			||||||
			toast({ title: "Sucessfully submitted:", description: values.title })
 | 
								toast({ title: "Success!", description: res.success })
 | 
				
			||||||
			router.refresh()
 | 
								router.refresh()
 | 
				
			||||||
			closeDialog()
 | 
								closeDialog()
 | 
				
			||||||
		} catch (error) {
 | 
							} catch (error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ import { Ban } from "lucide-react"
 | 
				
			||||||
export type SubForm = z.infer<typeof subSchema>
 | 
					export type SubForm = z.infer<typeof subSchema>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function SubmissionForm({ stories, pubs, responses, defaults, closeDialog }: { stories: any, pubs: any, responses: any, defaults: any, closeDialog: () => void }) {
 | 
					export default function SubmissionForm({ stories, pubs, responses, defaults, closeDialog }: { stories: any, pubs: any, responses: any, defaults?: any, closeDialog: () => void }) {
 | 
				
			||||||
	const form = useForm<z.infer<typeof subSchema>>({
 | 
						const form = useForm<z.infer<typeof subSchema>>({
 | 
				
			||||||
		resolver: zodResolver(subSchema),
 | 
							resolver: zodResolver(subSchema),
 | 
				
			||||||
		defaultValues: {
 | 
							defaultValues: {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,15 +19,9 @@ export default function FormContextMenu({ table, row, openEditDialog, openDelete
 | 
				
			||||||
        : ""
 | 
					        : ""
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {
 | 
					      <ContextMenuItem onClick={() => openEditDialog(row)}>
 | 
				
			||||||
        pathname === "/submission" ?
 | 
					        Edit
 | 
				
			||||||
          <>
 | 
					      </ContextMenuItem>
 | 
				
			||||||
            <ContextMenuItem onClick={() => openEditDialog(row)}>
 | 
					 | 
				
			||||||
              Edit
 | 
					 | 
				
			||||||
            </ContextMenuItem>
 | 
					 | 
				
			||||||
          </>
 | 
					 | 
				
			||||||
          : ""
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        selectedRows.length > 0 ?
 | 
					        selectedRows.length > 0 ?
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,7 @@ import EditSubmissionDialog from "app/submission/edit"
 | 
				
			||||||
import { DialogTitle } from "@radix-ui/react-dialog"
 | 
					import { DialogTitle } from "@radix-ui/react-dialog"
 | 
				
			||||||
import { toast } from "@/components/ui/use-toast"
 | 
					import { toast } from "@/components/ui/use-toast"
 | 
				
			||||||
import { useRouter } from "next/navigation"
 | 
					import { useRouter } from "next/navigation"
 | 
				
			||||||
 | 
					import EditStoryDialog from "app/story/edit"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface DataTableProps<TData, TValue> {
 | 
					export interface DataTableProps<TData, TValue> {
 | 
				
			||||||
  columns: ColumnDef<TData, TValue>[]
 | 
					  columns: ColumnDef<TData, TValue>[]
 | 
				
			||||||
| 
						 | 
					@ -167,13 +168,23 @@ export function DataTable<TData, TValue>({
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      <Dialog open={isEditDialogVisible} onOpenChange={setIsEditDialogVisible}>
 | 
					      <Dialog open={isEditDialogVisible} onOpenChange={setIsEditDialogVisible}>
 | 
				
			||||||
        <DialogContent>
 | 
					        <DialogContent>
 | 
				
			||||||
          <EditSubmissionDialog
 | 
					          {tableName === "sub" ?
 | 
				
			||||||
            stories={stories}
 | 
					            <EditSubmissionDialog
 | 
				
			||||||
            pubs={pubs}
 | 
					              stories={stories}
 | 
				
			||||||
            responses={responses}
 | 
					              pubs={pubs}
 | 
				
			||||||
            defaults={dialogRow?.original}
 | 
					              responses={responses}
 | 
				
			||||||
            closeDialog={closeEditDialog}
 | 
					              defaults={dialogRow?.original}
 | 
				
			||||||
          />
 | 
					              closeDialog={closeEditDialog}
 | 
				
			||||||
 | 
					            />
 | 
				
			||||||
 | 
					            : tableName === "story" ?
 | 
				
			||||||
 | 
					              < EditStoryDialog
 | 
				
			||||||
 | 
					                genres={genres}
 | 
				
			||||||
 | 
					                // TODO: prepare genre data so that it can be read by StoryForm 
 | 
				
			||||||
 | 
					                defaults={dialogRow?.original}
 | 
				
			||||||
 | 
					                closeDialog={closeEditDialog}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					              : ""
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        </DialogContent>
 | 
					        </DialogContent>
 | 
				
			||||||
      </Dialog>
 | 
					      </Dialog>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -223,7 +234,7 @@ export function DataTable<TData, TValue>({
 | 
				
			||||||
                const recordIds = rowIds.map(id => Number(table.getRow(id).original.id))
 | 
					                const recordIds = rowIds.map(id => Number(table.getRow(id).original.id))
 | 
				
			||||||
                const res = await deleteRecords(recordIds, pathname)
 | 
					                const res = await deleteRecords(recordIds, pathname)
 | 
				
			||||||
                if (!res) toast({ title: "Oh dear...", description: "Failed to delete." })
 | 
					                if (!res) toast({ title: "Oh dear...", description: "Failed to delete." })
 | 
				
			||||||
                if (res) toast({ title: "Sucessfully deleted records of id:", description: JSON.stringify(recordIds) })
 | 
					                if (res) toast({ title: "Successfully deleted records of id:", description: JSON.stringify(recordIds) })
 | 
				
			||||||
                router.refresh()
 | 
					                router.refresh()
 | 
				
			||||||
                setIsDeleteDialogVisible(false)
 | 
					                setIsDeleteDialogVisible(false)
 | 
				
			||||||
              }}>
 | 
					              }}>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue