Compare commits
8 Commits
6839c1c369
...
f454f6739e
Author | SHA1 | Date |
---|---|---|
|
f454f6739e | |
|
99b2fb9628 | |
|
7b994ec06e | |
|
52a30ec141 | |
|
3a91fd7cb4 | |
|
0eb09073ca | |
|
de2c8991c6 | |
|
fff436f87c |
BIN
prisma/dev.db
BIN
prisma/dev.db
Binary file not shown.
|
@ -1,6 +1,25 @@
|
||||||
import PubForm from "app/ui/forms/pub";
|
import PubForm from "app/ui/forms/pub";
|
||||||
import { getGenres } from "app/lib/get";
|
import { getGenres } from "app/lib/get";
|
||||||
|
import prisma from "app/lib/db";
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const genres = await getGenres()
|
async function createPub(data) {
|
||||||
return <PubForm genres={genres} />
|
"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} />
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
"use client"
|
"use client"
|
||||||
import { ColumnDef } from "@tanstack/react-table"
|
import { ColumnDef, createColumnHelper } from "@tanstack/react-table"
|
||||||
import { Genre, Story } from "@prisma/client"
|
import { StoryWithGenres } from "./page"
|
||||||
import { ArrowUpDown, MoreHorizontal } from "lucide-react"
|
import { ArrowUpDown, MoreHorizontal } from "lucide-react"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
export const columns: ColumnDef<Story & { genres: Array<Genre> }>[] = [
|
import { Badge } from "@/components/ui/badge"
|
||||||
// {
|
|
||||||
// accessorKey: "id",
|
|
||||||
// header: "Id",
|
|
||||||
// enableHiding: true,
|
const columnHelper = createColumnHelper<StoryWithGenres>()
|
||||||
// },
|
|
||||||
|
export const columns: ColumnDef<StoryWithGenres>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "title",
|
accessorKey: "title",
|
||||||
header: ({ column }) => {
|
header: ({ column }) => {
|
||||||
|
@ -39,18 +40,25 @@ export const columns: ColumnDef<Story & { genres: Array<Genre> }>[] = [
|
||||||
},
|
},
|
||||||
enableColumnFilter: false
|
enableColumnFilter: false
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
accessorFn: row => {
|
// accessorFn: row => {
|
||||||
let unpacked = ""
|
// let unpacked = ""
|
||||||
for (let i = 0; i < row.genres.length; i++) {
|
// for (let i = 0; i < row.genres.length; i++) {
|
||||||
unpacked = unpacked + " " + row.genres[i].name
|
// unpacked = unpacked + " " + row.genres[i].name
|
||||||
|
// }
|
||||||
|
// return unpacked
|
||||||
|
// },
|
||||||
|
// header: "Genres"
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// },
|
||||||
|
columnHelper.accessor("genres", {
|
||||||
|
cell: props => {
|
||||||
|
const genres = props.getValue()
|
||||||
|
.map(e => <Badge>{e.name}</Badge>)
|
||||||
|
return genres
|
||||||
}
|
}
|
||||||
return unpacked
|
})
|
||||||
},
|
|
||||||
header: "Genres"
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
// {
|
// {
|
||||||
// accessorKey: "deleted",
|
// accessorKey: "deleted",
|
||||||
// header: "Deleted"
|
// header: "Deleted"
|
||||||
|
|
|
@ -70,8 +70,8 @@ export function DataTable<TData, TValue>({
|
||||||
const [filterBy, setFilterBy] = useState(table.getAllColumns()[0])
|
const [filterBy, setFilterBy] = useState(table.getAllColumns()[0])
|
||||||
console.log(filterBy.id)
|
console.log(filterBy.id)
|
||||||
return (<>
|
return (<>
|
||||||
<div className="flex items-center py-4">
|
<div className="flex justify-between py-4">
|
||||||
<div className="">
|
<div className="flex gap-2">
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="outline" className="ml-auto">
|
<Button variant="outline" className="ml-auto">
|
||||||
|
@ -104,7 +104,7 @@ export function DataTable<TData, TValue>({
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild>
|
<DropdownMenuTrigger asChild>
|
||||||
<Button variant="outline" className="ml-auto">
|
<Button variant="outline" className="justify-self-end">
|
||||||
Show/hide
|
Show/hide
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
|
|
|
@ -3,7 +3,9 @@ import { DataTable } from "./data-table";
|
||||||
import { columns } from "./columns";
|
import { columns } from "./columns";
|
||||||
import { getStoriesWithGenres } from "app/lib/get";
|
import { getStoriesWithGenres } from "app/lib/get";
|
||||||
import { Genre } from "@prisma/client";
|
import { Genre } from "@prisma/client";
|
||||||
const stories: Array<Story & { genres: Array<Genre> }> = await getStoriesWithGenres()
|
export type StoryWithGenres = Story & { genres: Array<Genre> }
|
||||||
|
|
||||||
|
const stories: Array<StoryWithGenres> = await getStoriesWithGenres()
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto py-10">
|
<div className="container mx-auto py-10">
|
||||||
|
|
|
@ -2,10 +2,16 @@
|
||||||
import { getPubs, getResponses, getStories } from "app/lib/get";
|
import { getPubs, getResponses, getStories } from "app/lib/get";
|
||||||
import SubmissionForm from "app/ui/forms/sub";
|
import SubmissionForm from "app/ui/forms/sub";
|
||||||
import { SelectForm } from "app/ui/forms/selectDemo";
|
import { SelectForm } from "app/ui/forms/selectDemo";
|
||||||
|
import prisma from "app/lib/db";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const stories = await getStories()
|
const stories = await getStories()
|
||||||
const pubs = await getPubs()
|
const pubs = await getPubs()
|
||||||
const responses = await getResponses()
|
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} />
|
||||||
}
|
}
|
||||||
|
|
|
@ -815,15 +815,15 @@ body {
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.w-full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.w-fit {
|
.w-fit {
|
||||||
width: -moz-fit-content;
|
width: -moz-fit-content;
|
||||||
width: fit-content;
|
width: fit-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.min-w-\[8rem\] {
|
.min-w-\[8rem\] {
|
||||||
min-width: 8rem;
|
min-width: 8rem;
|
||||||
}
|
}
|
||||||
|
@ -837,19 +837,14 @@ body {
|
||||||
min-width: fit-content;
|
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-w-screen-sm {
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.max-w-sm {
|
||||||
|
max-width: 24rem;
|
||||||
|
}
|
||||||
|
|
||||||
.shrink-0 {
|
.shrink-0 {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
@ -862,6 +857,10 @@ body {
|
||||||
border-collapse: collapse;
|
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 {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
@ -988,10 +987,6 @@ body {
|
||||||
border-radius: calc(var(--radius) - 4px);
|
border-radius: calc(var(--radius) - 4px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-full {
|
|
||||||
border-radius: 9999px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border {
|
.border {
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
}
|
}
|
||||||
|
@ -1016,10 +1011,6 @@ body {
|
||||||
border-color: hsl(var(--primary));
|
border-color: hsl(var(--primary));
|
||||||
}
|
}
|
||||||
|
|
||||||
.border-transparent {
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bg-accent {
|
.bg-accent {
|
||||||
background-color: hsl(var(--accent));
|
background-color: hsl(var(--accent));
|
||||||
}
|
}
|
||||||
|
@ -1130,21 +1121,6 @@ body {
|
||||||
padding-bottom: 1rem;
|
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 {
|
.pl-3 {
|
||||||
padding-left: 0.75rem;
|
padding-left: 0.75rem;
|
||||||
}
|
}
|
||||||
|
@ -1424,14 +1400,6 @@ body {
|
||||||
background-color: hsl(var(--secondary) / 0.8);
|
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 {
|
.hover\:text-accent-foreground:hover {
|
||||||
color: hsl(var(--accent-foreground));
|
color: hsl(var(--accent-foreground));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
)
|
|
@ -3,6 +3,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@radix-ui/react-popover
|
||||||
import { Checkbox } from "@radix-ui/react-checkbox"
|
import { Checkbox } from "@radix-ui/react-checkbox"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/ui/button"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
export default function GenresTrigger({ value, genres }) {
|
export default function GenresTrigger({ value, genres }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -15,8 +16,7 @@ export default function GenresTrigger({ value, genres }) {
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{value.length !== 0 ? (
|
{value.length !== 0 ? (
|
||||||
value.map((e, i) => genres.find(f => e === f.id).name +
|
value.map((e, i) => (<Badge>{genres.find(f => e === f.id).name}</Badge>))
|
||||||
(i < value.length - 1 ? ', ' : ''))
|
|
||||||
) : (
|
) : (
|
||||||
<FormLabel>Genres</FormLabel>
|
<FormLabel>Genres</FormLabel>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -30,7 +30,7 @@ const formSchema = z.object({
|
||||||
genres: z.array(z.number()),
|
genres: z.array(z.number()),
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function PubForm({ genres }) {
|
export default function PubForm({ genres, createPub }) {
|
||||||
const form = useForm<z.infer<typeof formSchema>>({
|
const form = useForm<z.infer<typeof formSchema>>({
|
||||||
resolver: zodResolver(formSchema),
|
resolver: zodResolver(formSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
@ -52,7 +52,7 @@ export default function PubForm({ genres }) {
|
||||||
</pre>
|
</pre>
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
createPub(values)
|
||||||
console.log(values)
|
console.log(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ import {
|
||||||
} from "@/components/ui/popover"
|
} from "@/components/ui/popover"
|
||||||
import GenresTrigger from "./genresTrigger"
|
import GenresTrigger from "./genresTrigger"
|
||||||
import GenreCheckbox from "./genreCheckbox"
|
import GenreCheckbox from "./genreCheckbox"
|
||||||
|
import { Badge } from "@/components/ui/badge"
|
||||||
|
import { useRef, useImperativeHandle } from "react"
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
title: z.string().min(2).max(50),
|
title: z.string().min(2).max(50),
|
||||||
|
@ -69,7 +71,9 @@ export default function StoryForm({ genres, createStory }) {
|
||||||
console.log(JSON.stringify(errors))
|
console.log(JSON.stringify(errors))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const genrePickerRef = useRef<HTMLInputElement>(null)
|
||||||
|
const { ref, ...rest } = form.register("genres")
|
||||||
|
useImperativeHandle(ref, () => genrePickerRef.current)
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(onSubmit, onErrors)} className="space-y-8">
|
<form onSubmit={form.handleSubmit(onSubmit, onErrors)} className="space-y-8">
|
||||||
|
|
|
@ -36,13 +36,13 @@ import { useState } from "react"
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
storyId: z.coerce.number(),
|
storyId: z.coerce.number(),
|
||||||
pubId: z.coerce.number(),
|
pubId: z.coerce.number(),
|
||||||
submitted: z.date(),
|
submitted: z.date().transform((date) => date.toString()),
|
||||||
responded: z.date().optional(),
|
responded: z.date().transform((date) => date.toString()).optional(),
|
||||||
responseId: z.number()
|
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>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
|
@ -81,6 +81,7 @@ export default function SubmissionForm({ stories, pubs, responses }) {
|
||||||
</pre>
|
</pre>
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
createSub(values)
|
||||||
console.log(values)
|
console.log(values)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue