From 79e34039020f24a5832d176f60594ab07862c1d7 Mon Sep 17 00:00:00 2001 From: andrzej Date: Tue, 23 Jul 2024 17:40:35 +0200 Subject: [PATCH] implement genre picker cell (janky) --- prisma/dev.db | Bin 69632 -> 69632 bytes src/app/lib/update.ts | 18 ++- src/app/story/columns.tsx | 13 +- src/app/story/page.tsx | 6 +- src/app/submission/columns.tsx | 17 --- src/app/submission/create.tsx | 2 +- src/app/submission/page.tsx | 2 + src/app/tailwind.css | 4 - src/app/ui/forms/genreCheckbox.tsx | 30 ---- src/app/ui/forms/genrePicker.tsx | 6 +- src/app/ui/tables/data-table.tsx | 11 +- src/app/ui/tables/inputs/genrePickerInput.tsx | 134 ++++++++++++++++++ src/app/ui/tables/inputs/numberInput.tsx | 1 - src/app/ui/tables/inputs/textInput.tsx | 4 +- 14 files changed, 174 insertions(+), 74 deletions(-) delete mode 100644 src/app/ui/forms/genreCheckbox.tsx create mode 100644 src/app/ui/tables/inputs/genrePickerInput.tsx diff --git a/prisma/dev.db b/prisma/dev.db index 8dfbea3a6b8c189ec906188e9a2e9692f615f229..b78283ed8df19387f0f6e6388631aba083fc65eb 100644 GIT binary patch delta 235 zcmZozz|ydQWr8%L)650H7J*NWO8=yIpfVN(cXP(4AX|vXa XLlD&<`}mnzm^m3i>RCk=Jum^QeUxbZ?k&}^?1xzt9v$Ak#j=Qq%nNeuko_&)-5a9jY| ca$!He2n#bOBhV&JMrIJf1T>qKdC>y{0JfMa`v3p{ diff --git a/src/app/lib/update.ts b/src/app/lib/update.ts index db8d627..9d2b0db 100644 --- a/src/app/lib/update.ts +++ b/src/app/lib/update.ts @@ -1,16 +1,15 @@ "use server" -import { Genre, Story } from "@prisma/client" -import { StoryWithGenres } from "app/story/page" +import { Genre } from "@prisma/client" import prisma from "./db" import { revalidatePath } from "next/cache" import { redirect } from "next/navigation" -export async function updateField({ string: string, number, table, column, id, pathname }: { string?: string, number?: number, 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 }) { const res = await prisma[table].update({ where: { id }, data: { - [column]: string ?? number + [column]: datum } }) console.log(`updated record in ${table}: ${JSON.stringify(res)}`) @@ -18,3 +17,14 @@ export async function updateField({ string: string, number, table, column, id, p redirect(pathname) } +export async function updateGenres({ genres, table, id, pathname }: { genres: { id: number }[], table: string, id: number, pathname: string }) { + const res = await prisma[table].update({ + where: { id }, + data: { + genres: { set: genres } + } + }) + console.log(`updated record in ${table}: ${JSON.stringify(res)}`) + revalidatePath(pathname) + redirect(pathname) +} diff --git a/src/app/story/columns.tsx b/src/app/story/columns.tsx index 2beee52..5efbcf0 100644 --- a/src/app/story/columns.tsx +++ b/src/app/story/columns.tsx @@ -8,6 +8,7 @@ import { selectCol } from "app/ui/tables/selectColumn" import NumberInputCell from "app/ui/tables/inputs/numberInput" import { formSchema } from "app/ui/forms/story" import { TextInputCell } from "app/ui/tables/inputs/textInput" +import GenrePickerInputCell from "app/ui/tables/inputs/genrePickerInput" const columnHelper = createColumnHelper() export const columns: ColumnDef[] = [ @@ -50,11 +51,13 @@ export const columns: ColumnDef[] = [ } }, columnHelper.accessor("genres", { - cell: props => { - const genres = props.getValue() - return - }, - filterFn: "arrIncludes" + // cell: props => { + // const genres = props.getValue() + // return + // }, + cell: GenrePickerInputCell, + filterFn: "arrIncludes", + meta: {} //TODO - write custom filter function, to account for an array of objects }), diff --git a/src/app/story/page.tsx b/src/app/story/page.tsx index 66eeddf..0fde7ef 100644 --- a/src/app/story/page.tsx +++ b/src/app/story/page.tsx @@ -15,15 +15,15 @@ export type StoryWithGenres = Story & { genres: Array } export default async function Page() { const genres = await getGenres() const storiesWithGenres: Array = await getStoriesWithGenres() - const pubsWithGenres = await getPubsWithGenres() return (
- + - {/* TODO - EDIT STORY DIALOG */}
) diff --git a/src/app/submission/columns.tsx b/src/app/submission/columns.tsx index 8ea0949..fb1dd37 100644 --- a/src/app/submission/columns.tsx +++ b/src/app/submission/columns.tsx @@ -3,26 +3,9 @@ import { CellContext, ColumnDef, createColumnHelper } from "@tanstack/react-tabl import { ArrowUpDown } from "lucide-react" import { Button } from "@/components/ui/button" import { SubComplete } from "./page" -import { actions } from "app/ui/tables/actions" import { selectCol } from "app/ui/tables/selectColumn" -import EditSubmissionDialog from "./edit" -const EditSubCell = (props: CellContext) => { - // return { - // props.getValue() instanceof Date ? - //

- // {props.getValue().toLocaleDateString()} - //

- // :

{props.getValue()}

- // - // }
-} export const columns: ColumnDef[] = [ selectCol, diff --git a/src/app/submission/create.tsx b/src/app/submission/create.tsx index 643d324..c8fb7d1 100644 --- a/src/app/submission/create.tsx +++ b/src/app/submission/create.tsx @@ -17,7 +17,7 @@ type CreateSubDefaults = { 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, defaults }: ComponentProps<"div"> & { stories: Story[], pubs: Pub[], responses: Response[], defaults?: CreateSubDefaults }) { return ( diff --git a/src/app/submission/page.tsx b/src/app/submission/page.tsx index 7b6333c..12ba067 100644 --- a/src/app/submission/page.tsx +++ b/src/app/submission/page.tsx @@ -15,12 +15,14 @@ export default async function Page() { const stories = await getStories() const pubs = await getPubs() const responses = await getResponses() + const genres = await getGenres() return (
- - { - return checked - ? field.onChange([...field.value, item.id]) - : field.onChange( - field.value?.filter( - (value) => value !== item.id - ) - ) - }} - /> - - - {item.name} - - - - - ) -} diff --git a/src/app/ui/forms/genrePicker.tsx b/src/app/ui/forms/genrePicker.tsx index c34bcac..ce6cc98 100644 --- a/src/app/ui/forms/genrePicker.tsx +++ b/src/app/ui/forms/genrePicker.tsx @@ -4,9 +4,11 @@ import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Checkbox } from "@/components/ui/checkbox" import { cn } from "@/lib/utils" -import GenreCheckbox from "./genreCheckbox" +import { ComponentProps } from "react" +import { Genre } from "@prisma/client" +import { UseFormReturn } from "react-hook-form" -export default function GenrePicker({ genres, form }) { +export default function GenrePicker({ genres, form }: ComponentProps<"div"> & { genres: Genre[], form: UseFormReturn }) { return ( { columns: ColumnDef[] @@ -62,8 +61,9 @@ export function DataTable({ tableName, stories, pubs, - responses -}: DataTableProps & ComponentProps<"div"> & { tableName: string, stories?: Story[], pubs?: Pub[], responses?: Response[] }) { + responses, + genres +}: DataTableProps & ComponentProps<"div"> & { tableName: string, stories?: Story[], pubs?: Pub[], responses?: Response[], genres?: Genre[] }) { //STATE const [sorting, setSorting] = useState([]) const [columnFilters, setColumnFilters] = useState( @@ -97,7 +97,8 @@ export function DataTable({ pathname, stories, pubs, - responses + responses, + genres } }) diff --git a/src/app/ui/tables/inputs/genrePickerInput.tsx b/src/app/ui/tables/inputs/genrePickerInput.tsx new file mode 100644 index 0000000..97ccaae --- /dev/null +++ b/src/app/ui/tables/inputs/genrePickerInput.tsx @@ -0,0 +1,134 @@ +"use client" +import { FormField, FormItem, FormLabel, FormMessage, FormControl, Form } from "@/components/ui/form" +import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" +import { Button } from "@/components/ui/button" +import { Checkbox } from "@/components/ui/checkbox" +import { ComponentProps, useState } from "react" +import { useForm, UseFormReturn } from "react-hook-form" +import { CellContext } from "@tanstack/react-table" +import { z } from "zod" +import { zodResolver } from "@hookform/resolvers/zod" +import { toast } from "@/components/ui/use-toast" +import GenreBadges from "app/ui/genreBadges" +import { updateField, updateGenres } from "app/lib/update" +export default function GenrePickerInputCell(props: CellContext) { + + + + const table = props.table.options.meta.tableName + const pathname = props.table.options.meta.pathname + const id = props.row.original.id + const column = props.column.id + const value = props.cell.getValue() + const genres = props.table.options.meta.genres + const [isActive, setIsActive] = useState(false) + + async function onSubmit({ genres }: { genres: number[] }) { + const genresArray = genres.map((e) => { return { id: e } }) + toast({ + title: "You submitted the following values:", + description: ( +
+          {JSON.stringify(genresArray, null, 2)}
+        
+ ), + }) + const res = await updateGenres({ + id, + table, + genres: genresArray, + pathname + }) + setIsActive(false) + } + + function onErrors(errors) { + toast({ + title: "You have errors", + description: ( +
+          {JSON.stringify(errors, null, 2)}
+        
+ ), + }) + console.log(JSON.stringify(errors)) + } + const formSchema = z.object({ + genres: z.array(z.number()) + }) + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + genres: value.map(e => e.id) + } + }) + return ( +
+ + + + ( + + + {value.length > 0 ? : + } + + + + + + {genres.map((item) => ( + < FormField + key={item.id} + control={form.control} + name="genres" + render={({ field }) => { + return ( + + + { + console.log(field.value) + return checked + ? field.onChange([...field.value, item.id]) + : field.onChange( + field.value?.filter( + (value) => value !== item.id + ) + ) + }} + /> + + + {item.name} + + + ) + }} + /> + ))} + + + + + + )} + /> + + +
+ + ) +} + + + + + diff --git a/src/app/ui/tables/inputs/numberInput.tsx b/src/app/ui/tables/inputs/numberInput.tsx index 0b495cb..e840c69 100644 --- a/src/app/ui/tables/inputs/numberInput.tsx +++ b/src/app/ui/tables/inputs/numberInput.tsx @@ -17,7 +17,6 @@ export default function NumberInputCell(props: CellContext) { const column = props.column.id const pathname = props.table.options.meta.pathname const value = props.cell.getValue() - console.log(`|${value}|`) const formSchema = props.column.columnDef.meta.formSchema.pick({ [column]: true }) const form = useForm>({ diff --git a/src/app/ui/tables/inputs/textInput.tsx b/src/app/ui/tables/inputs/textInput.tsx index 8b11c00..7a5afd3 100644 --- a/src/app/ui/tables/inputs/textInput.tsx +++ b/src/app/ui/tables/inputs/textInput.tsx @@ -38,7 +38,7 @@ export function TextInputCell(props: CellContext) { const res = await updateField({ id, table, - string: value[column], + datum: value[column], column, pathname }) @@ -59,7 +59,7 @@ export function TextInputCell(props: CellContext) { return (
setIsActive(prev => !prev)} - className="w-full h-fit flex items-center justify-center" + className="w-full h-fit flex items-center justify-left" tabIndex={0} onKeyDown={e => { if (e.code === "Enter" && !isActive) {