Compare commits

..

3 Commits

Author SHA1 Message Date
andrzej 0eb09073ca db updates 2024-06-17 23:31:24 +02:00
andrzej de2c8991c6 add create server actions 2024-06-17 23:23:09 +02:00
andrzej fff436f87c extracted genre picker experiment
I need to properly handle refs for this to work, but this may be more trouble than it's worth
2024-06-17 22:56:24 +02:00
12 changed files with 204 additions and 118 deletions

Binary file not shown.

View File

@ -1,14 +1,7 @@
"use server"
import prisma from "./db"
export async function getStories() {
return prisma.story.findMany(
{
include: {
genres: true
}
}
)
return prisma.story.findMany()
}
export async function getPubs() {
return prisma.pub.findMany()

View File

@ -1,6 +1,25 @@
import PubForm from "app/ui/forms/pub";
import { getGenres } from "app/lib/get";
import prisma from "app/lib/db";
export default async function Page() {
const genres = await getGenres()
return <PubForm genres={genres} />
async function createPub(data) {
"use server"
const genresArray = data.genres.map(e => { return { id: e } })
const res = await prisma.pub.create({
data: {
title: data.title,
link: data.link,
query_after_days: data.query_after_days
}
})
console.log(res)
const genresRes = await prisma.pub.update({
where: { id: res.id },
data:
{ genres: { set: genresArray } }
})
console.log(genresRes)
}
const genres = await getGenres()
return <PubForm genres={genres} createPub={createPub} />
}

View File

@ -1,9 +1,9 @@
"use client"
import { ColumnDef } from "@tanstack/react-table"
import { Genre, Story } from "@prisma/client"
import { Story } from "@prisma/client"
import { ArrowUpDown, MoreHorizontal } from "lucide-react"
import { Button } from "@/components/ui/button"
export const columns: ColumnDef<Story & { genres: Array<Genre> }>[] = [
export const columns: ColumnDef<Story>[] = [
// {
// accessorKey: "id",
// header: "Id",
@ -22,34 +22,10 @@ export const columns: ColumnDef<Story & { genres: Array<Genre> }>[] = [
</Button>
)
},
},
{
accessorKey: "word_count",
header: ({ column }) => {
return (
<Button
variant="ghost"
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
>
Word Count
<ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
)
},
enableColumnFilter: false
},
{
accessorFn: row => {
let unpacked = ""
for (let i = 0; i < row.genres.length; i++) {
unpacked = unpacked + " " + row.genres[i].name
}
return unpacked
},
header: "Genres"
header: "Word Count",
},
// {
// accessorKey: "deleted",

View File

@ -5,8 +5,6 @@ import {
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuTrigger,
DropdownMenuRadioItem,
DropdownMenuRadioGroup
} from "@/components/ui/dropdown-menu"
import { Input } from "@/components/ui/input"
import { useState } from "react"
@ -41,7 +39,6 @@ export function DataTable<TData, TValue>({
columns,
data,
}: DataTableProps<TData, TValue>) {
console.log(data)
//STATE
const [sorting, setSorting] = useState<SortingState>([])
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
@ -67,36 +64,13 @@ export function DataTable<TData, TValue>({
},
})
const [filterBy, setFilterBy] = useState(table.getAllColumns()[0])
console.log(filterBy.id)
return (<>
<div className="flex items-center py-4">
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto">
Filter by
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuRadioGroup value={filterBy} onValueChange={setFilterBy} >
{table
.getAllColumns()
.filter((column) => column.getCanFilter())
.map((column) => {
return (
<DropdownMenuRadioItem value={column} className="capitalize" key={column.id}>
{column.id}
</DropdownMenuRadioItem>
)
})}
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
<Input
placeholder={`${filterBy.id}`}
value={(table.getColumn(filterBy.id)?.getFilterValue() as string) ?? ""}
placeholder="Filter emails..."
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
onChange={(event) =>
table.getColumn(filterBy.id)?.setFilterValue(event.target.value)
table.getColumn("email")?.setFilterValue(event.target.value)
}
className="max-w-sm"
/>

View File

@ -1,8 +1,116 @@
import { Story } from "@prisma/client";
import { DataTable } from "./data-table";
import { columns } from "./columns";
import { getStories } from "app/lib/get";
const stories: Story[] = await getStories()
const stories: Story[] = [
{
id: 0,
word_count: 500,
title: "Space Vampire",
deleted: 0,
},
{
id: 1,
word_count: 500,
title: "Ghost Astronaut",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Elf",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Space Orcs",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Space Orcs",
deleted: 0,
},
{
id: 0,
word_count: 500,
title: "Space Vampire",
deleted: 0,
},
{
id: 1,
word_count: 500,
title: "Ghost Astronaut",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Elf",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Space Orcs",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Space Orcs",
deleted: 0,
},
{
id: 0,
word_count: 500,
title: "Space Vampire",
deleted: 0,
},
{
id: 1,
word_count: 500,
title: "Ghost Astronaut",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Elf",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Space Orcs",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Space Orcs",
deleted: 0,
},
{
id: 0,
word_count: 500,
title: "Space Vampire",
deleted: 0,
},
{
id: 1,
word_count: 500,
title: "Ghost Astronaut",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Elf",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Space Orcs",
deleted: 0,
}, {
id: 1,
word_count: 500,
title: "Spooky Space Orcs And Gandalf Too",
deleted: 0,
},
]
export default async function Page() {
return (
<div className="container mx-auto py-10">

View File

@ -2,10 +2,16 @@
import { getPubs, getResponses, getStories } from "app/lib/get";
import SubmissionForm from "app/ui/forms/sub";
import { SelectForm } from "app/ui/forms/selectDemo";
import prisma from "app/lib/db";
export default async function Page() {
const stories = await getStories()
const pubs = await getPubs()
const responses = await getResponses()
return <SubmissionForm stories={stories} pubs={pubs} responses={responses} />
async function createSub(data) {
"use server"
const res = await prisma.sub.create({ data })
console.log(res)
}
return <SubmissionForm stories={stories} pubs={pubs} responses={responses} createSub={createSub} />
}

View File

@ -815,15 +815,15 @@ body {
width: auto;
}
.w-full {
width: 100%;
}
.w-fit {
width: -moz-fit-content;
width: fit-content;
}
.w-full {
width: 100%;
}
.min-w-\[8rem\] {
min-width: 8rem;
}
@ -837,19 +837,14 @@ body {
min-width: fit-content;
}
.max-w-sm {
max-width: 24rem;
}
.max-w-fit {
max-width: -moz-fit-content;
max-width: fit-content;
}
.max-w-screen-sm {
max-width: 640px;
}
.max-w-sm {
max-width: 24rem;
}
.shrink-0 {
flex-shrink: 0;
}
@ -862,6 +857,10 @@ body {
border-collapse: collapse;
}
.transform {
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.cursor-default {
cursor: default;
}
@ -988,10 +987,6 @@ body {
border-radius: calc(var(--radius) - 4px);
}
.rounded-full {
border-radius: 9999px;
}
.border {
border-width: 1px;
}
@ -1016,10 +1011,6 @@ body {
border-color: hsl(var(--primary));
}
.border-transparent {
border-color: transparent;
}
.bg-accent {
background-color: hsl(var(--accent));
}
@ -1130,21 +1121,6 @@ body {
padding-bottom: 1rem;
}
.px-2\.5 {
padding-left: 0.625rem;
padding-right: 0.625rem;
}
.py-0 {
padding-top: 0px;
padding-bottom: 0px;
}
.py-0\.5 {
padding-top: 0.125rem;
padding-bottom: 0.125rem;
}
.pl-3 {
padding-left: 0.75rem;
}
@ -1424,14 +1400,6 @@ body {
background-color: hsl(var(--secondary) / 0.8);
}
.hover\:bg-destructive\/80:hover {
background-color: hsl(var(--destructive) / 0.8);
}
.hover\:bg-primary\/80:hover {
background-color: hsl(var(--primary) / 0.8);
}
.hover\:text-accent-foreground:hover {
color: hsl(var(--accent-foreground));
}

View File

@ -0,0 +1,36 @@
import { forwardRef } from "react";
import { FormField, FormItem, FormMessage } from "@/components/ui/form";
import { Popover, PopoverContent, PopoverPortal, PopoverTrigger } from "@radix-ui/react-popover";
import GenresTrigger from "./genresTrigger";
import GenreCheckbox from "./genreCheckbox";
export const GenrePicker = forwardRef(
({ form, genres }, ref) => (
<FormField
control={form.control}
name="genres"
render={({ field }) => (
<FormItem className="flex flex-col">
<Popover>
<GenresTrigger value={field.value} genres={genres} />
<PopoverContent ref={ref}>
{genres.map((item) => (
<FormField
key={item.id}
control={form.control}
name="genres"
render={({ field }) => {
return (
<GenreCheckbox field={field} item={item} />
)
}}
/>
))}
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
)
)

View File

@ -30,7 +30,7 @@ const formSchema = z.object({
genres: z.array(z.number()),
})
export default function PubForm({ genres }) {
export default function PubForm({ genres, createPub }) {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
@ -52,7 +52,7 @@ export default function PubForm({ genres }) {
</pre>
),
})
createPub(values)
console.log(values)
}

View File

@ -22,6 +22,9 @@ import {
} from "@/components/ui/popover"
import GenresTrigger from "./genresTrigger"
import GenreCheckbox from "./genreCheckbox"
import { PopoverTrigger } from "@radix-ui/react-popover"
import { GenrePicker } from "./genrePicker"
import { useRef, useImperativeHandle } from "react"
const formSchema = z.object({
title: z.string().min(2).max(50),
@ -69,7 +72,9 @@ export default function StoryForm({ genres, createStory }) {
console.log(JSON.stringify(errors))
}
const genrePickerRef = useRef<HTMLInputElement>(null)
const { ref, ...rest } = form.register("genres")
useImperativeHandle(ref, () => genrePickerRef.current)
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit, onErrors)} className="space-y-8">

View File

@ -36,13 +36,13 @@ import { useState } from "react"
const FormSchema = z.object({
storyId: z.coerce.number(),
pubId: z.coerce.number(),
submitted: z.date(),
responded: z.date().optional(),
submitted: z.date().transform((date) => date.toString()),
responded: z.date().transform((date) => date.toString()).optional(),
responseId: z.number()
})
export default function SubmissionForm({ stories, pubs, responses }) {
export default function SubmissionForm({ stories, pubs, responses, createSub }) {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
@ -81,6 +81,7 @@ export default function SubmissionForm({ stories, pubs, responses }) {
</pre>
),
})
createSub(values)
console.log(values)
}