implement 'edit' functionality for pubs

This commit is contained in:
andrzej 2024-09-27 12:17:37 +02:00
parent 9bc1750848
commit 5b4e961859
15 changed files with 117 additions and 83 deletions

Binary file not shown.

View File

@ -6,6 +6,8 @@ import { revalidatePath } from "next/cache"
import { redirect } from "next/navigation" import { redirect } from "next/navigation"
import { storySchema, subSchema } from "app/ui/forms/schemas" import { storySchema, subSchema } from "app/ui/forms/schemas"
import { z } from "zod" import { z } from "zod"
import { StoryWithGenres } from "app/story/page"
import { PubWithGenres } from "app/publication/page"
export async function updateField({ datum, table, column, id, pathname }: { datum?: string | number | Genre[], table: string, column: string, id: number, pathname: string }) { export async function updateField({ datum, table, column, id, pathname }: { datum?: string | number | Genre[], table: string, column: string, id: number, pathname: string }) {
@ -22,7 +24,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 false return null
} }
} }
@ -40,11 +42,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 false return null
} }
} }
export async function updateSub(data: Sub): Promise<Sub | boolean> { export async function updateSub(data: Sub): Promise<Sub> {
"use server" "use server"
try { try {
subSchema.parse(data) subSchema.parse(data)
@ -53,12 +55,12 @@ export async function updateSub(data: Sub): Promise<Sub | boolean> {
return res return res
} catch (error) { } catch (error) {
console.error(error) console.error(error)
return false return null
} }
} }
export async function updateStory(data: Story & { genres: number[] }): Promise<Story | boolean> { export async function updateStory(data: StoryWithGenres): Promise<{ success: string }> {
"use server" "use server"
try { try {
@ -66,25 +68,25 @@ export async function updateStory(data: Story & { genres: number[] }): Promise<S
const storyData = await prepStoryData(data) const storyData = await prepStoryData(data)
const genresArray = await prepGenreData(data.genres) const genresArray = await prepGenreData(data.genres)
//submit //submit
const res = prisma.story.update({ const res = await prisma.story.update({
where: { id: data.id }, where: { id: data.id },
data: storyData data: storyData
}) })
await prisma.story.update({ const genreRes = await prisma.story.update({
where: { id: data.id }, where: { id: data.id },
data: { data: {
genres: { set: genresArray } genres: { set: genresArray }
} }
}) })
return res return { success: "Updated the story '" + res.title + "'." }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
return false return null
} }
} }
export async function updatePub(data: Pub & { genres: number[] }): Promise<Pub | boolean> { export async function updatePub(data: PubWithGenres): Promise<{ success: string }> {
"use server" "use server"
try { try {
@ -93,7 +95,7 @@ export async function updatePub(data: Pub & { genres: number[] }): Promise<Pub |
(data) (data)
const genresArray = await prepGenreData(data.genres) const genresArray = await prepGenreData(data.genres)
//submit //submit
const res = prisma.pub.update({ const res = await prisma.pub.update({
where: { id: data.id }, where: { id: data.id },
data: pubData data: pubData
}) })
@ -103,10 +105,10 @@ export async function updatePub(data: Pub & { genres: number[] }): Promise<Pub |
genres: { set: genresArray } genres: { set: genresArray }
} }
}) })
return res return { success: "Updated the publication '" + res.title + "'" }
} catch (error) { } catch (error) {
console.error(error) console.error(error)
return false return null
} }
} }

View File

@ -2,6 +2,7 @@ import { z } from "zod";
import { storySchema } from "app/ui/forms/schemas"; import { storySchema } from "app/ui/forms/schemas";
import { Pub, Story } from "@prisma/client"; import { Pub, Story } from "@prisma/client";
import { pubSchema } from "app/ui/forms/schemas"; import { pubSchema } from "app/ui/forms/schemas";
import { StoryWithGenres } from "app/story/page";
//schemas //schemas
@ -10,7 +11,7 @@ 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: StoryWithGenres): Promise<{ title: string, word_count: number }> {
const storyData = structuredClone(data) const storyData = structuredClone(data)
delete storyData.genres delete storyData.genres
//throw an error if validation fails //throw an error if validation fails
@ -18,7 +19,7 @@ export async function prepStoryData(data: Story & { genres: number[] }): Promise
return storyData return storyData
} }
export async function prepPubData(data: Pub & { genres: number[] }): Promise<Pub | Boolean> { export async function prepPubData(data: Pub & { genres: number[] }): Promise<Pub> {
const pubData = structuredClone(data) const pubData = structuredClone(data)
delete pubData.genres delete pubData.genres
pubSchemaTrimmed.safeParse(pubData) pubSchemaTrimmed.safeParse(pubData)

View File

@ -2,7 +2,7 @@
import { ColumnDef, createColumnHelper } from "@tanstack/react-table" import { ColumnDef, createColumnHelper } from "@tanstack/react-table"
import { ArrowUpDown, BookType, Clock, Drama, SquareArrowOutUpRight } from "lucide-react" import { ArrowUpDown, BookType, Clock, Drama, SquareArrowOutUpRight } from "lucide-react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { PubsWithGenres } from "./page" import { PubWithGenres } from "./page"
import { TextInputCell } from "app/ui/tables/inputs/textInput" import { TextInputCell } from "app/ui/tables/inputs/textInput"
import { selectCol } from "app/ui/tables/selectColumn" import { selectCol } from "app/ui/tables/selectColumn"
import NumberInputCell from "app/ui/tables/inputs/numberInput" import NumberInputCell from "app/ui/tables/inputs/numberInput"
@ -10,9 +10,9 @@ import { pubSchema } from "app/ui/forms/schemas"
import GenrePickerInputCell from "app/ui/tables/inputs/genrePickerInput" import GenrePickerInputCell from "app/ui/tables/inputs/genrePickerInput"
const columnHelper = createColumnHelper<PubsWithGenres>() const columnHelper = createColumnHelper<PubWithGenres>()
export const columns: ColumnDef<PubsWithGenres>[] = [ export const columns: ColumnDef<PubWithGenres>[] = [
selectCol, selectCol,
{ {
accessorKey: "title", accessorKey: "title",
@ -26,7 +26,7 @@ export const columns: ColumnDef<PubsWithGenres>[] = [
Title Title
</span> </span>
<span className="block sm:hidden"><BookType /></span> <span className="block sm:hidden"><BookType /></span>
<ArrowUpDown className="ml-2 h-4 w-4" /> <ArrowUpDown className="ml-2 h-4 w-4 hidden md:block" />
</Button> </Button>
) )
}, },

View File

@ -7,34 +7,23 @@ import { createPub } from "app/lib/create";
import PubForm from "app/ui/forms/pub"; import PubForm from "app/ui/forms/pub";
import { Plus } from "lucide-react"; import { Plus } from "lucide-react";
import { useState } from "react"; import { useState } from "react";
import { PubWithGenres } from "./page";
export default function CreatePubDialog({ genres }: ComponentProps<"div"> & { genres: Genre[] }) { export default function EditPubDialog({ genres, closeDialog, defaults, dbAction }: ComponentProps<"div"> & { genres: Genre[], closeDialog: () => void, defaults: PubWithGenres, dbAction: (data: PubWithGenres) => Promise<{ success: string }> }) {
const [isOpen, setIsOpen] = useState(false)
function closeDialog() {
setIsOpen(false)
}
return ( 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> <DialogHeader>
<DialogTitle>Edit publication</DialogTitle> <DialogTitle>Edit publication</DialogTitle>
<DialogDescription>Modify an entry for an existing publication.</DialogDescription> <DialogDescription>Modify an entry for an existing publication.</DialogDescription>
</DialogHeader> </DialogHeader>
<PubForm dbAction={createPub} genres={genres} closeDialog={closeDialog} /> <PubForm dbAction={dbAction} genres={genres} closeDialog={closeDialog} defaults={defaults} />
<DialogFooter> <DialogFooter>
<Button form="pubform">Submit</Button> <Button form="pubform">Submit</Button>
</DialogFooter> </DialogFooter>
</>
</DialogContent>
</Dialog>
) )
} }

View File

@ -4,7 +4,7 @@ import { columns } from "./columns";
import { DataTable } from "app/ui/tables/data-table"; import { DataTable } from "app/ui/tables/data-table";
import CreatePubDialog from "./create"; import CreatePubDialog from "./create";
export type PubsWithGenres = Pub & { genres: Array<Genre> } export type PubWithGenres = Pub & { genres: Array<Genre> }

View File

@ -25,7 +25,7 @@ export const columns: ColumnDef<StoryWithGenres>[] = [
Title Title
</span> </span>
<span className="block sm:hidden"><BookType /></span> <span className="block sm:hidden"><BookType /></span>
<ArrowUpDown className="ml-2 h-4 w-4" /> <ArrowUpDown className="ml-2 h-4 w-4 hidden md:block" />
</Button> </Button>
) )
}, },
@ -52,7 +52,7 @@ export const columns: ColumnDef<StoryWithGenres>[] = [
<span className="sm:hidden"> <span className="sm:hidden">
<Tally5 /> <Tally5 />
</span> </span>
<ArrowUpDown className="ml-2 h-4 w-4" /> <ArrowUpDown className="ml-2 h-4 w-4 hidden md:block" />
</Button> </Button>
) )
}, },

View File

@ -1,13 +1,13 @@
"use client" "use client"
import { createStory } from "app/lib/create"
import { Dialog, DialogHeader, DialogTrigger, DialogContent, DialogClose, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog"; import { Dialog, DialogHeader, DialogTrigger, DialogContent, DialogClose, DialogTitle, DialogFooter, DialogDescription } from "@/components/ui/dialog";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { ComponentProps, useState } from "react"; import { ComponentProps, useState } from "react";
import { Genre, Story } from "@prisma/client"; import { Genre, Story } from "@prisma/client";
import StoryForm from "app/ui/forms/story"; import StoryForm from "app/ui/forms/story";
import { StoryWithGenres } from "./page";
export default function EditStoryDialog({ genres, closeDialog, defaults }: ComponentProps<"div"> & { genres: Genre[], closeDialog: () => void, defaults: Story }) { export default function EditStoryDialog({ genres, closeDialog, defaults, dbAction }: ComponentProps<"div"> & { genres: Genre[], closeDialog: () => void, defaults: StoryWithGenres, dbAction: (data: StoryWithGenres) => Promise<{ success: string }> }) {
return ( return (
@ -16,7 +16,7 @@ export default function EditStoryDialog({ genres, closeDialog, defaults }: Compo
<DialogTitle>Edit story</DialogTitle> <DialogTitle>Edit 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 dbAction={createStory} genres={genres} className="" closeDialog={closeDialog} defaults={defaults} /> <StoryForm dbAction={dbAction} genres={genres} className="" closeDialog={closeDialog} defaults={defaults} />
<DialogFooter> <DialogFooter>
<Button form="storyform">Submit</Button> <Button form="storyform">Submit</Button>
</DialogFooter> </DialogFooter>

View File

@ -50,7 +50,7 @@ export const columns: ColumnDef<SubComplete>[] = [
return ( return (
<Button <Button
variant="ghost" variant="ghost"
className="p-0" className="p-0 flex justify-center w-full"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
> >
<span className="hidden md:block"> Date Submitted </span> <span className="hidden md:block"> Date Submitted </span>
@ -76,7 +76,7 @@ export const columns: ColumnDef<SubComplete>[] = [
return ( return (
<Button <Button
variant="ghost" variant="ghost"
className="p-0" className="p-0 flex justify-center w-full"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
> >
<span className="hidden md:block"> Date Responded </span> <span className="hidden md:block"> Date Responded </span>
@ -105,7 +105,7 @@ export const columns: ColumnDef<SubComplete>[] = [
return ( return (
<Button <Button
variant="ghost" variant="ghost"
className="p-0" className="p-0 flex justify-center w-full"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")} onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
> >
<span className="hidden md:block"> Response </span> <span className="hidden md:block"> Response </span>

View File

@ -706,6 +706,10 @@ body {
z-index: 100; z-index: 100;
} }
.float-right {
float: right;
}
.m-auto { .m-auto {
margin: auto; margin: auto;
} }
@ -777,14 +781,6 @@ 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;
} }
@ -887,10 +883,6 @@ body {
height: 100vh; height: 100vh;
} }
.h-5\/6 {
height: 83.333333%;
}
.max-h-96 { .max-h-96 {
max-height: 24rem; max-height: 24rem;
} }
@ -976,8 +968,8 @@ body {
width: 100vw; width: 100vw;
} }
.w-5\/6 { .w-1\/2 {
width: 83.333333%; width: 50%;
} }
.min-w-\[8rem\] { .min-w-\[8rem\] {
@ -1021,6 +1013,18 @@ body {
max-width: 20rem; max-width: 20rem;
} }
.max-w-40 {
max-width: 10rem;
}
.max-w-\[50\%\] {
max-width: 50%;
}
.max-w-60 {
max-width: 15rem;
}
.shrink-0 { .shrink-0 {
flex-shrink: 0; flex-shrink: 0;
} }
@ -1105,6 +1109,18 @@ body {
flex-wrap: wrap; flex-wrap: wrap;
} }
.content-center {
align-content: center;
}
.content-start {
align-content: flex-start;
}
.content-between {
align-content: space-between;
}
.items-start { .items-start {
align-items: flex-start; align-items: flex-start;
} }
@ -1129,6 +1145,10 @@ body {
justify-content: space-between; justify-content: space-between;
} }
.justify-around {
justify-content: space-around;
}
.gap-1 { .gap-1 {
gap: 0.25rem; gap: 0.25rem;
} }
@ -1220,6 +1240,10 @@ body {
margin-bottom: calc(2rem * var(--tw-space-y-reverse)); margin-bottom: calc(2rem * var(--tw-space-y-reverse));
} }
.self-end {
align-self: flex-end;
}
.justify-self-end { .justify-self-end {
justify-self: end; justify-self: end;
} }
@ -1267,11 +1291,6 @@ 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;
} }
@ -1493,6 +1512,10 @@ body {
text-align: center; text-align: center;
} }
.align-top {
vertical-align: top;
}
.align-middle { .align-middle {
vertical-align: middle; vertical-align: middle;
} }
@ -1536,6 +1559,11 @@ body {
line-height: 1rem; line-height: 1rem;
} }
.text-6xl {
font-size: 3.75rem;
line-height: 1;
}
.font-black { .font-black {
font-weight: 900; font-weight: 900;
} }

View File

@ -22,15 +22,17 @@ 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"
import { PubWithGenres } from "app/publication/page"
export default function PubForm({ genres, dbAction, className, closeDialog, defaults }: ComponentProps<"div"> & { genres: Array<Genre>, dbAction: (data: any) => Promise<{ success: string }>, closeDialog: () => void, defaults?: Pub }) { export default function PubForm({ genres, dbAction, className, closeDialog, defaults }: ComponentProps<"div"> & { genres: Array<Genre>, dbAction: (data: any) => Promise<{ success: string }>, closeDialog: () => void, defaults?: PubWithGenres }) {
const form = useForm<z.infer<typeof pubSchema>>({ const form = useForm<z.infer<typeof pubSchema>>({
resolver: zodResolver(pubSchema), resolver: zodResolver(pubSchema),
defaultValues: { defaultValues: {
title: "", id: defaults?.id,
link: "", title: defaults?.title ?? "",
query_after_days: 30, link: defaults?.link ?? "",
genres: [] query_after_days: defaults?.query_after_days ?? 30,
genres: defaults?.genres.map(e => e.id) ?? []
}, },
}) })
@ -39,7 +41,7 @@ export default function PubForm({ genres, dbAction, className, closeDialog, defa
async function onSubmit(values: z.infer<typeof pubSchema>) { async function onSubmit(values: z.infer<typeof pubSchema>) {
try { try {
const res = await dbAction(values) const res = await dbAction(values)
if (!res) throw new Error("something went wrong") if (!res?.success) throw new Error("something went wrong")
toast({ title: "Success!", description: res.success }) toast({ title: "Success!", description: res.success })
router.refresh() router.refresh()
closeDialog() closeDialog()

View File

@ -7,6 +7,7 @@ export const storySchema = z.object({
}) })
export const pubSchema = z.object({ export const pubSchema = z.object({
id: z.coerce.number().optional(),
title: z.string().min(2).max(50), title: z.string().min(2).max(50),
link: z.string(), link: z.string(),
query_after_days: z.coerce.number().min(30), query_after_days: z.coerce.number().min(30),

View File

@ -34,6 +34,7 @@ export default function StoryForm({ genres, dbAction, className, closeDialog, de
const form = useForm<z.infer<typeof formSchema>>({ const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema), resolver: zodResolver(formSchema),
defaultValues: { defaultValues: {
id: defaults?.id,
title: defaults?.title ?? "", title: defaults?.title ?? "",
word_count: defaults?.word_count ?? 500, word_count: defaults?.word_count ?? 500,
genres: defaults?.genres.map(e => e.id) ?? [] genres: defaults?.genres.map(e => e.id) ?? []
@ -47,7 +48,7 @@ export default function StoryForm({ genres, dbAction, className, closeDialog, de
try { try {
const res = await dbAction(values) const res = await dbAction(values)
//server actions return undefined if middleware authentication fails //server actions return undefined if middleware authentication fails
if (!res.success) throw new Error("something went wrong") if (!res?.success) throw new Error("something went wrong")
toast({ title: "Success!", description: res.success }) toast({ title: "Success!", description: res.success })
router.refresh() router.refresh()
closeDialog() closeDialog()
@ -86,7 +87,7 @@ export default function StoryForm({ genres, dbAction, className, closeDialog, de
)} )}
/> />
<div className="inline-flex flex-wrap w-full gap-x-16 gap-y-8 items-baseline max-w-full"> <div className="inline-flex flex-wrap justify-around items-start w-full gap-x-16 gap-y-8 items-baseline max-w-full">
<GenrePicker <GenrePicker
genres={genres} genres={genres}
@ -97,7 +98,7 @@ export default function StoryForm({ genres, dbAction, className, closeDialog, de
control={form.control} control={form.control}
name="word_count" name="word_count"
render={({ field }) => ( render={({ field }) => (
<FormItem className="flex flex-col"> <FormItem className="flex flex-col ">
<FormLabel className="h-5">Word count</FormLabel> <FormLabel className="h-5">Word count</FormLabel>
<FormControl> <FormControl>
<Input className=" w-24" type="number" step={500} {...field}></Input> <Input className=" w-24" type="number" step={500} {...field}></Input>

View File

@ -5,7 +5,7 @@ import { Badge } from "@/components/ui/badge";
export default function GenreBadges(props: ComponentProps<"div"> & { genres: Array<Genre> }) { export default function GenreBadges(props: ComponentProps<"div"> & { genres: Array<Genre> }) {
return ( return (
<div className={"flex flex-wrap gap-1 justify-center " + props.className}> <div className={"flex flex-wrap gap-1 justify-center " + props.className}>
{props.genres.map((e: Genre) => (<Badge className="" key={e.name}>{e.name}</Badge>))} {props.genres.map((e: Genre) => (<Badge className="text-xs md:text-sm" key={e.name}>{e.name}</Badge>))}
</div> </div>
) )
} }

View File

@ -45,7 +45,7 @@ import { deleteRecord, deleteRecords } from "app/lib/del"
import { Pathname } from "app/types" import { Pathname } from "app/types"
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTrigger } from "@/components/ui/dialog" import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTrigger } from "@/components/ui/dialog"
import pluralize from "app/lib/pluralize" import pluralize from "app/lib/pluralize"
import { updateField } from "app/lib/update" import { updateField, updatePub, updateStory } from "app/lib/update"
import { tableNameToItemName } from "app/lib/nameMaps" import { tableNameToItemName } from "app/lib/nameMaps"
import { Genre, Pub, Response, Story } from "@prisma/client" import { Genre, Pub, Response, Story } from "@prisma/client"
import EditSubmissionDialog from "app/submission/edit" import EditSubmissionDialog from "app/submission/edit"
@ -53,6 +53,7 @@ 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" import EditStoryDialog from "app/story/edit"
import EditPubDialog from "app/publication/edit"
export interface DataTableProps<TData, TValue> { export interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[] columns: ColumnDef<TData, TValue>[]
@ -178,8 +179,15 @@ export function DataTable<TData, TValue>({
/> />
: tableName === "story" ? : tableName === "story" ?
< EditStoryDialog < EditStoryDialog
dbAction={updateStory}
genres={genres}
defaults={dialogRow?.original}
closeDialog={closeEditDialog}
/>
: tableName === "pub" ?
<EditPubDialog
dbAction={updatePub}
genres={genres} genres={genres}
// TODO: prepare genre data so that it can be read by StoryForm
defaults={dialogRow?.original} defaults={dialogRow?.original}
closeDialog={closeEditDialog} closeDialog={closeEditDialog}
/> />
@ -205,6 +213,7 @@ export function DataTable<TData, TValue>({
const res = await deleteRecord(dialogRow.original.id, pathname) const res = await deleteRecord(dialogRow.original.id, 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: "Successfully deleted record of id:", description: dialogRow.original.id }) if (res) toast({ title: "Successfully deleted record of id:", description: dialogRow.original.id })
table.resetRowSelection()
router.refresh() router.refresh()
}}>Yes, delete it! }}>Yes, delete it!
</Button> </Button>
@ -235,6 +244,7 @@ export function DataTable<TData, TValue>({
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: "Successfully deleted records of id:", description: JSON.stringify(recordIds) }) if (res) toast({ title: "Successfully deleted records of id:", description: JSON.stringify(recordIds) })
table.resetRowSelection()
router.refresh() router.refresh()
setIsDeleteDialogVisible(false) setIsDeleteDialogVisible(false)
}}> }}>