controlled create dialogs
This commit is contained in:
		
							parent
							
								
									81b36d0c8c
								
							
						
					
					
						commit
						52e3a6f31c
					
				
							
								
								
									
										
											BIN
										
									
								
								prisma/dev.db
								
								
								
								
							
							
						
						
									
										
											BIN
										
									
								
								prisma/dev.db
								
								
								
								
							
										
											Binary file not shown.
										
									
								
							| 
						 | 
				
			
			@ -6,12 +6,18 @@ 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>
 | 
			
		||||
    <Dialog open={isOpen} onOpenChange={setIsOpen}>
 | 
			
		||||
      <DialogTrigger asChild>
 | 
			
		||||
        <Button>
 | 
			
		||||
          <span className="hidden md:block">Create new publication</span>
 | 
			
		||||
| 
						 | 
				
			
			@ -23,11 +29,9 @@ export default function CreatePubDialog({ genres }: ComponentProps<"div"> & { ge
 | 
			
		|||
          <DialogTitle>New publication</DialogTitle>
 | 
			
		||||
          <DialogDescription>Create an entry for a new publication i.e. a place you intend to submit stories to.</DialogDescription>
 | 
			
		||||
        </DialogHeader>
 | 
			
		||||
        <PubForm createPub={createPub} genres={genres} />
 | 
			
		||||
        <PubForm createPub={createPub} genres={genres} closeDialog={closeDialog} />
 | 
			
		||||
        <DialogFooter>
 | 
			
		||||
          <DialogClose >
 | 
			
		||||
            <Button form="pubform">Submit</Button>
 | 
			
		||||
          </DialogClose>
 | 
			
		||||
          <Button form="pubform">Submit</Button>
 | 
			
		||||
        </DialogFooter>
 | 
			
		||||
 | 
			
		||||
      </DialogContent>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,9 @@ import { Plus } from "lucide-react";
 | 
			
		|||
export default function CreateStoryDialog({ genres }: ComponentProps<"div"> & { genres: Genre[] }) {
 | 
			
		||||
 | 
			
		||||
  const [isOpen, setIsOpen] = useState(false)
 | 
			
		||||
  function closeDialog() {
 | 
			
		||||
    setIsOpen(false)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog open={isOpen} onOpenChange={setIsOpen}>
 | 
			
		||||
| 
						 | 
				
			
			@ -25,12 +28,9 @@ export default function CreateStoryDialog({ genres }: ComponentProps<"div"> & {
 | 
			
		|||
          <DialogTitle>New story</DialogTitle>
 | 
			
		||||
          <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
			
		||||
        </DialogHeader>
 | 
			
		||||
        <StoryForm createStory={createStory} genres={genres} className="" />
 | 
			
		||||
        <StoryForm createStory={createStory} genres={genres} className="" closeDialog={closeDialog} />
 | 
			
		||||
        <DialogFooter>
 | 
			
		||||
          <DialogClose>
 | 
			
		||||
            {/* TODO: pass setIsOpen to form as prop, to be handled post-verification */}
 | 
			
		||||
            <Button form="storyform">Submit</Button>
 | 
			
		||||
          </DialogClose>
 | 
			
		||||
          <Button form="storyform">Submit</Button>
 | 
			
		||||
        </DialogFooter>
 | 
			
		||||
 | 
			
		||||
      </DialogContent>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import { ComponentProps } from "react";
 | 
			
		|||
import { Pub, Response, Story } from "@prisma/client";
 | 
			
		||||
import SubmissionForm from "app/ui/forms/sub";
 | 
			
		||||
import { Plus } from "lucide-react";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
type CreateSubDefaults = {
 | 
			
		||||
| 
						 | 
				
			
			@ -20,8 +21,13 @@ type CreateSubDefaults = {
 | 
			
		|||
 | 
			
		||||
export default function CreateSubmissionDialog({ stories, pubs, responses, defaults }: ComponentProps<"div"> & { stories: Story[], pubs: Pub[], responses: Response[], defaults?: CreateSubDefaults }) {
 | 
			
		||||
 | 
			
		||||
  const [isOpen, setIsOpen] = useState(false)
 | 
			
		||||
  function closeDialog() {
 | 
			
		||||
    setIsOpen(false)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <Dialog>
 | 
			
		||||
    <Dialog open={isOpen} onOpenChange={setIsOpen}>
 | 
			
		||||
      <DialogTrigger asChild>
 | 
			
		||||
        <Button>
 | 
			
		||||
          <span className="hidden md:block">Create new submission</span>
 | 
			
		||||
| 
						 | 
				
			
			@ -33,10 +39,8 @@ export default function CreateSubmissionDialog({ stories, pubs, responses, defau
 | 
			
		|||
          <DialogTitle>New submission</DialogTitle>
 | 
			
		||||
          <DialogDescription>Create an entry for a new story i.e. a thing you intend to submit for publication.</DialogDescription>
 | 
			
		||||
        </DialogHeader>
 | 
			
		||||
        <SubmissionForm pubs={pubs} responses={responses} stories={stories} defaults={defaults} />
 | 
			
		||||
        <SubmissionForm pubs={pubs} responses={responses} stories={stories} defaults={defaults} closeDialog={closeDialog} />
 | 
			
		||||
        <DialogFooter>
 | 
			
		||||
          <DialogClose asChild>
 | 
			
		||||
          </DialogClose>
 | 
			
		||||
          <Button form="subform">Submit</Button>
 | 
			
		||||
        </DialogFooter>
 | 
			
		||||
      </DialogContent>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,10 +6,11 @@ import { ComponentProps } from "react";
 | 
			
		|||
import { Pub, Response, Story } from "@prisma/client";
 | 
			
		||||
import SubmissionForm, { SubForm } from "app/ui/forms/sub";
 | 
			
		||||
import EditSubmissionForm from "app/ui/forms/editSub";
 | 
			
		||||
import { useState } from "react";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default function EditSubmissionDialog({ stories, pubs, responses, defaults, children, closeDialog }: ComponentProps<"div"> & { stories: Story[], pubs: Pub[], responses: Response[], defaults: SubForm, closeDialog: () => void }) {
 | 
			
		||||
 | 
			
		||||
export default function EditSubmissionDialog({ stories, pubs, responses, defaults, children }: ComponentProps<"div"> & { stories: Story[], pubs: Pub[], responses: Response[], defaults: SubForm }) {
 | 
			
		||||
 | 
			
		||||
  return (
 | 
			
		||||
    <>
 | 
			
		||||
| 
						 | 
				
			
			@ -17,10 +18,8 @@ export default function EditSubmissionDialog({ stories, pubs, responses, default
 | 
			
		|||
        <DialogTitle>Edit Submission</DialogTitle>
 | 
			
		||||
        <DialogDescription>Change response status, edit dates etc</DialogDescription>
 | 
			
		||||
      </DialogHeader>
 | 
			
		||||
      <EditSubmissionForm pubs={pubs} responses={responses} stories={stories} defaults={defaults} />
 | 
			
		||||
      <EditSubmissionForm pubs={pubs} responses={responses} stories={stories} defaults={defaults} closeDialog={closeDialog} />
 | 
			
		||||
      <DialogFooter>
 | 
			
		||||
        <DialogClose asChild>
 | 
			
		||||
        </DialogClose>
 | 
			
		||||
        <Button form="subform">Submit</Button>
 | 
			
		||||
      </DialogFooter>
 | 
			
		||||
    </>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1097,10 +1097,6 @@ body {
 | 
			
		|||
  justify-content: space-between;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.justify-around {
 | 
			
		||||
  justify-content: space-around;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.gap-1 {
 | 
			
		||||
  gap: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1202,6 +1198,10 @@ body {
 | 
			
		|||
  white-space: nowrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-3xl {
 | 
			
		||||
  border-radius: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-full {
 | 
			
		||||
  border-radius: 9999px;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1214,25 +1214,11 @@ body {
 | 
			
		|||
  border-radius: calc(var(--radius) - 4px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-3xl {
 | 
			
		||||
  border-radius: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-l-3xl {
 | 
			
		||||
  border-top-left-radius: 1.5rem;
 | 
			
		||||
  border-bottom-left-radius: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-t-3xl {
 | 
			
		||||
  border-top-left-radius: 1.5rem;
 | 
			
		||||
  border-top-right-radius: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-l {
 | 
			
		||||
  border-top-left-radius: 0.25rem;
 | 
			
		||||
  border-bottom-left-radius: 0.25rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rounded-tl-3xl {
 | 
			
		||||
  border-top-left-radius: 1.5rem;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,7 +40,7 @@ import { useRouter } from "next/navigation"
 | 
			
		|||
export type SubForm = z.infer<typeof subSchema>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default function EditSubmissionForm({ stories, pubs, responses, defaults }) {
 | 
			
		||||
export default function EditSubmissionForm({ stories, pubs, responses, defaults, closeDialog }) {
 | 
			
		||||
	const form = useForm<z.infer<typeof subSchema>>({
 | 
			
		||||
		resolver: zodResolver(subSchema),
 | 
			
		||||
		defaultValues: {
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +76,7 @@ export default function EditSubmissionForm({ stories, pubs, responses, defaults
 | 
			
		|||
			if (res === undefined) throw new Error("something went wrong")
 | 
			
		||||
			toast({ title: "Successfully created new submission!" })
 | 
			
		||||
			router.refresh()
 | 
			
		||||
			closeDialog()
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			toast({
 | 
			
		||||
				title: "UH-OH",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,9 @@ import { Genre } from "@prisma/client"
 | 
			
		|||
import GenrePicker from "./genrePicker"
 | 
			
		||||
import { pubSchema } from "./schemas"
 | 
			
		||||
import { useRouter } from "next/navigation"
 | 
			
		||||
import { Ban } from "lucide-react"
 | 
			
		||||
 | 
			
		||||
export default function PubForm({ genres, createPub, className }: ComponentProps<"div"> & { genres: Array<Genre>, createPub: (data: any) => void }) {
 | 
			
		||||
export default function PubForm({ genres, createPub, className, closeDialog }: ComponentProps<"div"> & { genres: Array<Genre>, createPub: (data: any) => void, closeDialog: () => void }) {
 | 
			
		||||
	const form = useForm<z.infer<typeof pubSchema>>({
 | 
			
		||||
		resolver: zodResolver(pubSchema),
 | 
			
		||||
		defaultValues: {
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +42,7 @@ export default function PubForm({ genres, createPub, className }: ComponentProps
 | 
			
		|||
			if (!res) throw new Error("something went wrong")
 | 
			
		||||
			toast({ title: "Successfully submitted:", description: values.title })
 | 
			
		||||
			router.refresh()
 | 
			
		||||
			closeDialog()
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			toast({
 | 
			
		||||
				title: "Oh dear... ",
 | 
			
		||||
| 
						 | 
				
			
			@ -51,11 +53,8 @@ export default function PubForm({ genres, createPub, className }: ComponentProps
 | 
			
		|||
 | 
			
		||||
	function onErrors(errors) {
 | 
			
		||||
		toast({
 | 
			
		||||
			title: "You have errors",
 | 
			
		||||
			description: (
 | 
			
		||||
				<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
 | 
			
		||||
					<code className="text-white">{JSON.stringify(errors, null, 2)}</code>
 | 
			
		||||
				</pre>
 | 
			
		||||
				<Ban />
 | 
			
		||||
			),
 | 
			
		||||
		})
 | 
			
		||||
		console.log(JSON.stringify(errors))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,11 +15,12 @@ import {
 | 
			
		|||
import { Input } from "@/components/ui/input"
 | 
			
		||||
import { toast } from "@/components/ui/use-toast"
 | 
			
		||||
 | 
			
		||||
import { ComponentProps } from "react"
 | 
			
		||||
import { ComponentProps, SetStateAction } from "react"
 | 
			
		||||
import { Genre, Story } from "@prisma/client"
 | 
			
		||||
import { randomStoryTitle } from "app/lib/shortStoryTitleGenerator"
 | 
			
		||||
import GenrePicker from "./genrePicker"
 | 
			
		||||
import { useRouter } from "next/navigation"
 | 
			
		||||
import { Ban, Cross } from "lucide-react"
 | 
			
		||||
 | 
			
		||||
export const formSchema = z.object({
 | 
			
		||||
	id: z.number().optional(),
 | 
			
		||||
| 
						 | 
				
			
			@ -28,7 +29,7 @@ export const formSchema = z.object({
 | 
			
		|||
	genres: z.array(z.number())
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export default function StoryForm({ genres, createStory, className }: ComponentProps<"div"> & { genres: Array<Genre>, createStory: (data: any) => void, className: string }) {
 | 
			
		||||
export default function StoryForm({ genres, createStory, className, closeDialog }: ComponentProps<"div"> & { genres: Array<Genre>, createStory: (data: any) => void, className: string, closeDialog: () => void }) {
 | 
			
		||||
	const form = useForm<z.infer<typeof formSchema>>({
 | 
			
		||||
		resolver: zodResolver(formSchema),
 | 
			
		||||
		defaultValues: {
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +47,7 @@ export default function StoryForm({ genres, createStory, className }: ComponentP
 | 
			
		|||
			if (!res) throw new Error("something went wrong")
 | 
			
		||||
			toast({ title: "Sucessfully submitted:", description: values.title })
 | 
			
		||||
			router.refresh()
 | 
			
		||||
			closeDialog()
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			toast({
 | 
			
		||||
				title: "Oh dear... ",
 | 
			
		||||
| 
						 | 
				
			
			@ -58,12 +60,7 @@ export default function StoryForm({ genres, createStory, className }: ComponentP
 | 
			
		|||
 | 
			
		||||
	function onErrors(errors) {
 | 
			
		||||
		toast({
 | 
			
		||||
			title: "You have errors",
 | 
			
		||||
			description: (
 | 
			
		||||
				<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
 | 
			
		||||
					<code className="text-white">{JSON.stringify(errors, null, 2)}</code>
 | 
			
		||||
				</pre>
 | 
			
		||||
			),
 | 
			
		||||
			description: (<Ban />)
 | 
			
		||||
		})
 | 
			
		||||
		console.log(JSON.stringify(errors))
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -100,7 +97,7 @@ export default function StoryForm({ genres, createStory, className }: ComponentP
 | 
			
		|||
								<FormItem className="flex flex-col">
 | 
			
		||||
									<FormLabel className="h-5">Word count</FormLabel>
 | 
			
		||||
									<FormControl>
 | 
			
		||||
										<Input className=" w-24" type="number" step={500} min={1} {...field}></Input>
 | 
			
		||||
										<Input className=" w-24" type="number" step={500} {...field}></Input>
 | 
			
		||||
									</FormControl>
 | 
			
		||||
									<FormMessage />
 | 
			
		||||
								</FormItem>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,11 +35,12 @@ import { useState } from "react"
 | 
			
		|||
import { createSub } from "app/lib/create"
 | 
			
		||||
import { subSchema } from "./schemas"
 | 
			
		||||
import { useRouter } from "next/navigation"
 | 
			
		||||
import { Ban } from "lucide-react"
 | 
			
		||||
 | 
			
		||||
export type SubForm = z.infer<typeof subSchema>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export default function SubmissionForm({ stories, pubs, responses, defaults }) {
 | 
			
		||||
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>>({
 | 
			
		||||
		resolver: zodResolver(subSchema),
 | 
			
		||||
		defaultValues: {
 | 
			
		||||
| 
						 | 
				
			
			@ -71,24 +72,22 @@ export default function SubmissionForm({ stories, pubs, responses, defaults }) {
 | 
			
		|||
	async function onSubmit(values: z.infer<typeof subSchema>) {
 | 
			
		||||
		try {
 | 
			
		||||
			const res = await createSub(values)
 | 
			
		||||
			if (res === undefined) throw new Error("something went wrong")
 | 
			
		||||
			if (!res) throw new Error("something went wrong")
 | 
			
		||||
			toast({ title: "Successfully created new submission!" })
 | 
			
		||||
			router.refresh()
 | 
			
		||||
			closeDialog()
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			toast({
 | 
			
		||||
				title: "UH-OH",
 | 
			
		||||
				description: error.message
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
		router.refresh()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	function onErrors(errors) {
 | 
			
		||||
		toast({
 | 
			
		||||
			title: "You have errors",
 | 
			
		||||
			description: (
 | 
			
		||||
				<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
 | 
			
		||||
					<code className="text-white">{JSON.stringify(errors, null, 2)}</code>
 | 
			
		||||
				</pre>
 | 
			
		||||
				<Ban />
 | 
			
		||||
			),
 | 
			
		||||
		})
 | 
			
		||||
		console.log(JSON.stringify(errors))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,12 +1,7 @@
 | 
			
		|||
import { Dialog, DialogTrigger, DialogClose, DialogDescription, DialogContent, DialogTitle, DialogHeader, DialogFooter } from "@/components/ui/dialog"
 | 
			
		||||
import { Button } from "@/components/ui/button"
 | 
			
		||||
import { ContextMenuContent, ContextMenuItem, ContextMenuSubTrigger, ContextMenuSeparator, ContextMenuSub, ContextMenuSubContent } from "@/components/ui/context-menu"
 | 
			
		||||
import { deleteRecord } from "app/lib/del"
 | 
			
		||||
import Link from "next/link"
 | 
			
		||||
import { ComponentProps, useState } from "react"
 | 
			
		||||
import { Row, Table, TableState } from "@tanstack/react-table"
 | 
			
		||||
import { tableNameToItemName } from "app/lib/nameMaps"
 | 
			
		||||
import EditSubmissionDialog from "app/submission/edit"
 | 
			
		||||
 | 
			
		||||
export default function FormContextMenu({ table, row, openEditDialog, openDeleteDialog }: ComponentProps<"div"> & { table: Table<any>, row: Row<any>, openEditDialog: (row: Row<any>) => void, openDeleteDialog: (row: Row<any>) => void }) {
 | 
			
		||||
  const pathname = table.options.meta.pathname
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -119,6 +119,9 @@ export function DataTable<TData, TValue>({
 | 
			
		|||
    setIsDeleteDialogVisible(true)
 | 
			
		||||
    SetDialogRow(row)
 | 
			
		||||
  }
 | 
			
		||||
  function closeEditDialog() {
 | 
			
		||||
    setIsEditDialogVisible(false)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,6 +172,7 @@ export function DataTable<TData, TValue>({
 | 
			
		|||
            pubs={pubs}
 | 
			
		||||
            responses={responses}
 | 
			
		||||
            defaults={dialogRow?.original}
 | 
			
		||||
            closeDialog={closeEditDialog}
 | 
			
		||||
          />
 | 
			
		||||
        </DialogContent>
 | 
			
		||||
      </Dialog>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue