Compare commits
3 Commits
0eb09073ca
...
9583d0da16
Author | SHA1 | Date |
---|---|---|
|
9583d0da16 | |
|
b5b8d8ad09 | |
|
13a9407caa |
BIN
prisma/dev.db
BIN
prisma/dev.db
Binary file not shown.
|
@ -1,7 +1,14 @@
|
|||
"use server"
|
||||
import prisma from "./db"
|
||||
export async function getStories() {
|
||||
return prisma.story.findMany()
|
||||
return prisma.story.findMany(
|
||||
{
|
||||
include: {
|
||||
genres: true
|
||||
}
|
||||
}
|
||||
|
||||
)
|
||||
}
|
||||
export async function getPubs() {
|
||||
return prisma.pub.findMany()
|
||||
|
|
|
@ -1,25 +1,6 @@
|
|||
import PubForm from "app/ui/forms/pub";
|
||||
import { getGenres } from "app/lib/get";
|
||||
import prisma from "app/lib/db";
|
||||
export default async function Page() {
|
||||
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} />
|
||||
return <PubForm genres={genres} />
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
"use client"
|
||||
import { ColumnDef } from "@tanstack/react-table"
|
||||
import { Story } from "@prisma/client"
|
||||
import { Genre, Story } from "@prisma/client"
|
||||
import { ArrowUpDown, MoreHorizontal } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
export const columns: ColumnDef<Story>[] = [
|
||||
export const columns: ColumnDef<Story & { genres: Array<Genre> }>[] = [
|
||||
// {
|
||||
// accessorKey: "id",
|
||||
// header: "Id",
|
||||
|
@ -22,10 +22,34 @@ export const columns: ColumnDef<Story>[] = [
|
|||
</Button>
|
||||
)
|
||||
},
|
||||
|
||||
},
|
||||
{
|
||||
accessorKey: "word_count",
|
||||
header: "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"
|
||||
|
||||
|
||||
},
|
||||
// {
|
||||
// accessorKey: "deleted",
|
||||
|
|
|
@ -5,6 +5,8 @@ import {
|
|||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuRadioGroup
|
||||
} from "@/components/ui/dropdown-menu"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { useState } from "react"
|
||||
|
@ -39,6 +41,7 @@ export function DataTable<TData, TValue>({
|
|||
columns,
|
||||
data,
|
||||
}: DataTableProps<TData, TValue>) {
|
||||
console.log(data)
|
||||
//STATE
|
||||
const [sorting, setSorting] = useState<SortingState>([])
|
||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>(
|
||||
|
@ -64,13 +67,36 @@ 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="Filter emails..."
|
||||
value={(table.getColumn("email")?.getFilterValue() as string) ?? ""}
|
||||
placeholder={`${filterBy.id}`}
|
||||
value={(table.getColumn(filterBy.id)?.getFilterValue() as string) ?? ""}
|
||||
onChange={(event) =>
|
||||
table.getColumn("email")?.setFilterValue(event.target.value)
|
||||
table.getColumn(filterBy.id)?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm"
|
||||
/>
|
||||
|
|
|
@ -1,116 +1,8 @@
|
|||
import { Story } from "@prisma/client";
|
||||
import { DataTable } from "./data-table";
|
||||
import { columns } from "./columns";
|
||||
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,
|
||||
},
|
||||
]
|
||||
import { getStories } from "app/lib/get";
|
||||
const stories: Story[] = await getStories()
|
||||
export default async function Page() {
|
||||
return (
|
||||
<div className="container mx-auto py-10">
|
||||
|
|
|
@ -2,16 +2,10 @@
|
|||
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()
|
||||
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} />
|
||||
return <SubmissionForm stories={stories} pubs={pubs} responses={responses} />
|
||||
}
|
||||
|
|
|
@ -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,14 +837,19 @@ body {
|
|||
min-width: fit-content;
|
||||
}
|
||||
|
||||
.max-w-screen-sm {
|
||||
max-width: 640px;
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
|
||||
.shrink-0 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
@ -857,10 +862,6 @@ 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;
|
||||
}
|
||||
|
@ -987,6 +988,10 @@ body {
|
|||
border-radius: calc(var(--radius) - 4px);
|
||||
}
|
||||
|
||||
.rounded-full {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.border {
|
||||
border-width: 1px;
|
||||
}
|
||||
|
@ -1011,6 +1016,10 @@ body {
|
|||
border-color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.border-transparent {
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.bg-accent {
|
||||
background-color: hsl(var(--accent));
|
||||
}
|
||||
|
@ -1121,6 +1130,21 @@ 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;
|
||||
}
|
||||
|
@ -1400,6 +1424,14 @@ 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));
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
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>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
)
|
|
@ -30,7 +30,7 @@ const formSchema = z.object({
|
|||
genres: z.array(z.number()),
|
||||
})
|
||||
|
||||
export default function PubForm({ genres, createPub }) {
|
||||
export default function PubForm({ genres }) {
|
||||
const form = useForm<z.infer<typeof formSchema>>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
|
@ -52,7 +52,7 @@ export default function PubForm({ genres, createPub }) {
|
|||
</pre>
|
||||
),
|
||||
})
|
||||
createPub(values)
|
||||
|
||||
console.log(values)
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,6 @@ 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),
|
||||
|
@ -72,9 +69,7 @@ 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">
|
||||
|
|
|
@ -36,13 +36,13 @@ import { useState } from "react"
|
|||
const FormSchema = z.object({
|
||||
storyId: z.coerce.number(),
|
||||
pubId: z.coerce.number(),
|
||||
submitted: z.date().transform((date) => date.toString()),
|
||||
responded: z.date().transform((date) => date.toString()).optional(),
|
||||
submitted: z.date(),
|
||||
responded: z.date().optional(),
|
||||
responseId: z.number()
|
||||
})
|
||||
|
||||
|
||||
export default function SubmissionForm({ stories, pubs, responses, createSub }) {
|
||||
export default function SubmissionForm({ stories, pubs, responses }) {
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: {
|
||||
|
@ -81,7 +81,6 @@ export default function SubmissionForm({ stories, pubs, responses, createSub })
|
|||
</pre>
|
||||
),
|
||||
})
|
||||
createSub(values)
|
||||
console.log(values)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue