style create forms

This commit is contained in:
andrzej 2024-06-24 18:29:51 +02:00
parent be32c7e0a6
commit c4b61069fd
11 changed files with 472 additions and 167 deletions

View File

@ -2,54 +2,104 @@
@tailwind components;
@tailwind utilities;
/**/
/* @layer base { */
/* :root { */
/* --background: 43 62% 98%; */
/* --foreground: 43 73% 2%; */
/* --muted: 43 24% 85%; */
/* --muted-foreground: 43 10% 37%; */
/* --popover: 43 62% 98%; */
/* --popover-foreground: 43 73% 2%; */
/* --card: 43 62% 98%; */
/* --card-foreground: 43 73% 2%; */
/* --border: 43 15% 91%; */
/* --input: 43 15% 91%; */
/* --primary: 43 50% 69%; */
/* --primary-foreground: 43 50% 9%; */
/* --secondary: 43 6% 92%; */
/* --secondary-foreground: 43 6% 32%; */
/* --accent: 43 13% 83%; */
/* --accent-foreground: 43 13% 23%; */
/* --destructive: 8 84% 20%; */
/* --destructive-foreground: 8 84% 80%; */
/* --ring: 43 50% 69%; */
/* --radius: 0.5rem; */
/* } */
/**/
/* .dark { */
/* --background: 43 48% 4%; */
/* --foreground: 43 26% 97%; */
/* --muted: 43 24% 15%; */
/* --muted-foreground: 43 10% 63%; */
/* --popover: 43 48% 4%; */
/* --popover-foreground: 43 26% 97%; */
/* --card: 43 48% 4%; */
/* --card-foreground: 43 26% 97%; */
/* --border: 43 15% 13%; */
/* --input: 43 15% 13%; */
/* --primary: 43 50% 69%; */
/* --primary-foreground: 43 50% 9%; */
/* --secondary: 43 8% 18%; */
/* --secondary-foreground: 43 8% 78%; */
/* --accent: 43 14% 23%; */
/* --accent-foreground: 43 14% 83%; */
/* --destructive: 8 84% 52%; */
/* --destructive-foreground: 0 0% 100%; */
/* --ring: 43 50% 69%; */
/* } */
/* } */
@layer base {
:root {
--background: 43 62% 98%;
--foreground: 43 73% 2%;
--muted: 43 24% 85%;
--muted-foreground: 43 10% 37%;
--popover: 43 62% 98%;
--popover-foreground: 43 73% 2%;
--card: 43 62% 98%;
--card-foreground: 43 73% 2%;
--border: 43 15% 91%;
--input: 43 15% 91%;
--primary: 43 50% 69%;
--primary-foreground: 43 50% 9%;
--secondary: 43 6% 92%;
--secondary-foreground: 43 6% 32%;
--accent: 43 13% 83%;
--accent-foreground: 43 13% 23%;
--destructive: 8 84% 20%;
--destructive-foreground: 8 84% 80%;
--ring: 43 50% 69%;
--background: 220 0% 96%;
--foreground: 222.2 84% 4.9%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--primary: 144.91 90% 32%;
--primary-foreground: 75 10% 97.84%;
--secondary: 240 0% 100%;
--secondary-foreground: 150 95% 30%;
--accent: 150 55% 95%;
--accent-foreground: 155 100% 20%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 0% 100%;
--ring: 150 100% 40%;
--radius: 0.5rem;
}
.dark {
--background: 43 48% 4%;
--foreground: 43 26% 97%;
--muted: 43 24% 15%;
--muted-foreground: 43 10% 63%;
--popover: 43 48% 4%;
--popover-foreground: 43 26% 97%;
--card: 43 48% 4%;
--card-foreground: 43 26% 97%;
--border: 43 15% 13%;
--input: 43 15% 13%;
--primary: 43 50% 69%;
--primary-foreground: 43 50% 9%;
--secondary: 43 8% 18%;
--secondary-foreground: 43 8% 78%;
--accent: 43 14% 23%;
--accent-foreground: 43 14% 83%;
--destructive: 8 84% 52%;
--destructive-foreground: 0 0% 100%;
--ring: 43 50% 69%;
--background: 222.2 40% 4%;
--foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--popover: 230 25% 10%;
--popover-foreground: 210 40% 98%;
--card: 222.2 20% 6%;
--card-foreground: 210 40% 98%;
--border: 217.2 20% 10%;
--input: 217.2 32.6% 17.5%;
--primary: 155 70% 35%;
--primary-foreground: 80 10% 97.84%;
--secondary: 200 50% 98%;
--secondary-foreground: 155 85% 30%;
--accent: 170 60% 10%;
--accent-foreground: 155 60% 65%;
--destructive: 5 90% 65%;
--destructive-foreground: 0 100% 10%;
--ring: 160 90% 45%;
}
}
/**/
/* @layer base { */
/* :root { */

View File

@ -36,7 +36,7 @@ export default function RootLayout({
<div id="layout-container" className="p-4 w-screen h-screen mt-6 flex justify-center">
<div className="grid grid-cols-12 w-5/6">
<div id="sidebar" className="col-start-1 col-end-3 h-5/6 flex flex-col"> <header className="">
<h1 className="font-black text-4xl text-primary-foreground bg-primary antialiased w-full p-2">SubMan</h1>
<h1 className="font-black text-4xl text-primary-foreground bg-primary antialiased w-full p-2 rounded-tl-3xl">SubMan</h1>
<p className="mt-2 mx-1 text-sm antialiased">The self-hosted literary submission tracker.</p>
</header>
<Navlinks className="mt-6" />

View File

@ -0,0 +1,35 @@
function randomArrayItem(array: Array<string>) {
return array[Math.floor(Math.random() * (array.length - 1))]
}
export function randomStoryTitle() {
const titles = [
"The Signalman",
"The Time Machine",
"The Lawnmover Man",
"La Casa de Adela",
"The Tell-Tale Heart",
"The Lottery",
"The Birds",
"The Minority Report",
"The Bear Came Over the Mountain"
]
return randomArrayItem(titles)
}
export function randomPublicationTitle() {
const titles = [
"Nightmare Magazine",
"Apex",
"The Dark",
"Reader's Digest",
"The New Yorker",
"Short Story Magazine",
"Weird Tales",
"Detective Stories"
]
return randomArrayItem(titles)
}

View File

@ -1,6 +1,7 @@
import PubForm from "app/ui/forms/pub";
import { getGenres } from "app/lib/get";
import prisma from "app/lib/db";
import { CreateContainer, CreateContainerContent, CreateContainerDescription, CreateContainerHeader } from "app/ui/createContainer";
export default async function Page() {
async function createPub(data) {
"use server"
@ -21,5 +22,15 @@ export default async function Page() {
console.log(genresRes)
}
const genres = await getGenres()
return <PubForm genres={genres} createPub={createPub} />
return (
<CreateContainer>
<CreateContainerHeader>Create Publication</CreateContainerHeader>
<CreateContainerContent>
<CreateContainerDescription>
Create a new entry for a publication i.e. a place you intend to submit to.
</CreateContainerDescription>
<PubForm genres={genres} createPub={createPub} />
</CreateContainerContent>
</CreateContainer>
)
}

View File

@ -29,8 +29,10 @@ export default async function Page() {
return (
<CreateContainer>
<CreateContainerHeader>Create Story</CreateContainerHeader>
<CreateContainerContent>
<CreateContainerDescription>Make an entry for a new work of fiction i.e. a thing you intend to submit for publication.</CreateContainerDescription>
<CreateContainerContent><StoryForm genres={genres} createStory={createStory} /></CreateContainerContent>
<StoryForm genres={genres} createStory={createStory} className="mt-6" />
</CreateContainerContent>
</CreateContainer>
)
}

View File

@ -447,48 +447,48 @@ video {
}
:root {
--background: 43 62% 98%;
--foreground: 43 73% 2%;
--muted: 43 24% 85%;
--muted-foreground: 43 10% 37%;
--popover: 43 62% 98%;
--popover-foreground: 43 73% 2%;
--card: 43 62% 98%;
--card-foreground: 43 73% 2%;
--border: 43 15% 91%;
--input: 43 15% 91%;
--primary: 43 50% 69%;
--primary-foreground: 43 50% 9%;
--secondary: 43 6% 92%;
--secondary-foreground: 43 6% 32%;
--accent: 43 13% 83%;
--accent-foreground: 43 13% 23%;
--destructive: 8 84% 20%;
--destructive-foreground: 8 84% 80%;
--ring: 43 50% 69%;
--background: 220 0% 96%;
--foreground: 222.2 84% 4.9%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--primary: 144.91 90% 32%;
--primary-foreground: 75 10% 97.84%;
--secondary: 240 0% 100%;
--secondary-foreground: 150 95% 30%;
--accent: 150 55% 95%;
--accent-foreground: 155 100% 20%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 0% 100%;
--ring: 150 100% 40%;
--radius: 0.5rem;
}
.dark {
--background: 43 48% 4%;
--foreground: 43 26% 97%;
--muted: 43 24% 15%;
--muted-foreground: 43 10% 63%;
--popover: 43 48% 4%;
--popover-foreground: 43 26% 97%;
--card: 43 48% 4%;
--card-foreground: 43 26% 97%;
--border: 43 15% 13%;
--input: 43 15% 13%;
--primary: 43 50% 69%;
--primary-foreground: 43 50% 9%;
--secondary: 43 8% 18%;
--secondary-foreground: 43 8% 78%;
--accent: 43 14% 23%;
--accent-foreground: 43 14% 83%;
--destructive: 8 84% 52%;
--destructive-foreground: 0 0% 100%;
--ring: 43 50% 69%;
--background: 222.2 40% 4%;
--foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--popover: 230 25% 10%;
--popover-foreground: 210 40% 98%;
--card: 222.2 20% 6%;
--card-foreground: 210 40% 98%;
--border: 217.2 20% 10%;
--input: 217.2 32.6% 17.5%;
--primary: 155 70% 35%;
--primary-foreground: 80 10% 97.84%;
--secondary: 200 50% 98%;
--secondary-foreground: 155 85% 30%;
--accent: 170 60% 10%;
--accent-foreground: 155 60% 65%;
--destructive: 5 90% 65%;
--destructive-foreground: 0 100% 10%;
--ring: 160 90% 45%;
}
* {
@ -845,6 +845,10 @@ body {
height: 1rem;
}
.h-5 {
height: 1.25rem;
}
.h-5\/6 {
height: 83.333333%;
}
@ -877,6 +881,11 @@ body {
height: 100vh;
}
.h-fit {
height: -moz-fit-content;
height: fit-content;
}
.max-h-96 {
max-height: 24rem;
}
@ -958,6 +967,14 @@ body {
width: 100vw;
}
.w-1\/3 {
width: 33.333333%;
}
.w-2\/5 {
width: 40%;
}
.min-w-\[8rem\] {
min-width: 8rem;
}
@ -983,6 +1000,10 @@ body {
max-width: 24rem;
}
.max-w-full {
max-width: 100%;
}
.shrink-0 {
flex-shrink: 0;
}
@ -1067,6 +1088,10 @@ body {
flex-direction: column-reverse;
}
.flex-wrap {
flex-wrap: wrap;
}
.items-start {
align-items: flex-start;
}
@ -1075,6 +1100,10 @@ body {
align-items: center;
}
.items-baseline {
align-items: baseline;
}
.justify-end {
justify-content: flex-end;
}
@ -1095,6 +1124,10 @@ body {
gap: 0.25rem;
}
.gap-16 {
gap: 4rem;
}
.gap-2 {
gap: 0.5rem;
}
@ -1103,6 +1136,27 @@ body {
gap: 1rem;
}
.gap-y-8 {
row-gap: 2rem;
}
.gap-y-2 {
row-gap: 0.5rem;
}
.gap-y-1 {
row-gap: 0.25rem;
}
.gap-x-16 {
-moz-column-gap: 4rem;
column-gap: 4rem;
}
.gap-y-6 {
row-gap: 1.5rem;
}
.space-x-1 > :not([hidden]) ~ :not([hidden]) {
--tw-space-x-reverse: 0;
margin-right: calc(0.25rem * var(--tw-space-x-reverse));
@ -1197,6 +1251,20 @@ body {
border-radius: calc(var(--radius) - 4px);
}
.rounded-l-3xl {
border-top-left-radius: 1.5rem;
border-bottom-left-radius: 1.5rem;
}
.rounded-t-3xl {
border-top-left-radius: 1.5rem;
border-top-right-radius: 1.5rem;
}
.rounded-tl-3xl {
border-top-left-radius: 1.5rem;
}
.border {
border-width: 1px;
}
@ -1209,6 +1277,10 @@ body {
border-top-width: 1px;
}
.border-border {
border-color: hsl(var(--border));
}
.border-destructive {
border-color: hsl(var(--destructive));
}
@ -1237,10 +1309,18 @@ body {
background-color: rgb(0 0 0 / 0.8);
}
.bg-card {
background-color: hsl(var(--card));
}
.bg-destructive {
background-color: hsl(var(--destructive));
}
.bg-input {
background-color: hsl(var(--input));
}
.bg-muted {
background-color: hsl(var(--muted));
}
@ -1357,14 +1437,14 @@ body {
padding-bottom: 1rem;
}
.pl-2 {
padding-left: 0.5rem;
}
.pl-3 {
padding-left: 0.75rem;
}
.pl-6 {
padding-left: 1.5rem;
}
.pl-8 {
padding-left: 2rem;
}
@ -1635,6 +1715,100 @@ body {
/* :root { */
/* --background: 43 62% 98%; */
/* --foreground: 43 73% 2%; */
/* --muted: 43 24% 85%; */
/* --muted-foreground: 43 10% 37%; */
/* --popover: 43 62% 98%; */
/* --popover-foreground: 43 73% 2%; */
/* --card: 43 62% 98%; */
/* --card-foreground: 43 73% 2%; */
/* --border: 43 15% 91%; */
/* --input: 43 15% 91%; */
/* --primary: 43 50% 69%; */
/* --primary-foreground: 43 50% 9%; */
/* --secondary: 43 6% 92%; */
/* --secondary-foreground: 43 6% 32%; */
/* --accent: 43 13% 83%; */
/* --accent-foreground: 43 13% 23%; */
/* --destructive: 8 84% 20%; */
/* --destructive-foreground: 8 84% 80%; */
/* --ring: 43 50% 69%; */
/* --radius: 0.5rem; */
/* } */
/**/
/* .dark { */
/* --background: 43 48% 4%; */
/* --foreground: 43 26% 97%; */
/* --muted: 43 24% 15%; */
/* --muted-foreground: 43 10% 63%; */
/* --popover: 43 48% 4%; */
/* --popover-foreground: 43 26% 97%; */
/* --card: 43 48% 4%; */
/* --card-foreground: 43 26% 97%; */
/* --border: 43 15% 13%; */
/* --input: 43 15% 13%; */
/* --primary: 43 50% 69%; */
/* --primary-foreground: 43 50% 9%; */
/* --secondary: 43 8% 18%; */
/* --secondary-foreground: 43 8% 78%; */
/* --accent: 43 14% 23%; */
/* --accent-foreground: 43 14% 83%; */
/* --destructive: 8 84% 52%; */
/* --destructive-foreground: 0 0% 100%; */
/* --ring: 43 50% 69%; */
/* } */
/* } */
/**/
/* @layer base { */
/* :root { */
/* --background: 258 70% 100%; */
/* --foreground: 258 77% 0%; */

View File

@ -1,19 +1,22 @@
import { ComponentProps } from "react";
export function CreateContainer({ children }: ComponentProps<"div">) {
return <div className="w-2/5 m-auto bg-card rounded-t-3xl border-border">{children}</div>
}
export function CreateContainerHeader({ children }: ComponentProps<"h1">) {
return <h1 className="text-primary-foreground bg-primary w-full font-black text-3xl p-5 rounded-t-3xl">{children}</h1>
}
export function CreateContainerDescription({ children }: ComponentProps<"p">) {
return <p className="">{children}</p>
}
export function CreateContainerContent({ children, className }: ComponentProps<"div">) {
return <div className="mt-6">
return <div className="p-6">
{children}
</div>
}
export function CreateContainerHeader({ children }: ComponentProps<"h1">) {
return <h1 className="text-primary-foreground bg-primary w-full font-black text-3xl p-5">{children}</h1>
}
export function CreateContainer({ children }: ComponentProps<"div">) {
return <div className="w-2/3 m-auto">{children}</div>
}
export function CreateContainerDescription({ children }: ComponentProps<"p">) {
return <p className="mt-4">{children}</p>
}

View File

@ -11,14 +11,14 @@ export default function GenresTrigger({ value, genres }) {
<Button
variant={"outline"}
className={cn(
"min-w-fit max-w-screen-sm w-fit pl-3 text-left font-normal",
"min-w-fit max-w-full w-fit pl-3 text-left font-normal flex-wrap gap-y-1 h-fit",
!value && "text-muted-foreground"
)}
>
{value.length !== 0 ? (
value.map((e, i) => (<Badge>{genres.find(f => e === f.id).name}</Badge>))
) : (
<FormLabel>Genres</FormLabel>
<p>Select</p>
)}
</Button>
</PopoverTrigger>

View File

@ -22,6 +22,7 @@ import {
} from "@/components/ui/popover"
import GenresTrigger from "./genresTrigger"
import GenreCheckbox from "./genreCheckbox"
import { randomPublicationTitle } from "app/lib/shortStoryTitleGenerator"
const formSchema = z.object({
title: z.string().min(2).max(50),
@ -68,7 +69,11 @@ export default function PubForm({ genres, createPub }) {
console.log(JSON.stringify(errors))
}
const exampleTitle = randomPublicationTitle()
const exampleUrl = "www." +
exampleTitle.replace(/ /g, '')
.toLowerCase() +
".com"
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit, onErrors)} className="space-y-8">
@ -79,7 +84,7 @@ export default function PubForm({ genres, createPub }) {
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input placeholder="title goes here..." {...field} />
<Input placeholder={exampleTitle} {...field} />
</FormControl>
<FormMessage />
</FormItem>
@ -93,21 +98,23 @@ export default function PubForm({ genres, createPub }) {
<FormItem>
<FormLabel>Website</FormLabel>
<FormControl>
<Input placeholder="url to the submissions page" {...field} />
<Input placeholder={exampleUrl} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="inline-flex flex-wrap w-full gap-x-16 gap-y-8 max-w-full h-fit">
<FormField
control={form.control}
name="genres"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormItem className="flex flex-col flex-wrap">
<FormLabel className="h-5">Genres</FormLabel>
<Popover>
<GenresTrigger value={field.value} genres={genres} />
<PopoverContent>
<PopoverContent align="start">
{genres.map((item) => (
<FormField
key={item.id}
@ -128,6 +135,20 @@ export default function PubForm({ genres, createPub }) {
/>
<FormField
control={form.control}
name="query_after_days"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel className="h-5">Query after (days)</FormLabel>
<FormControl>
<Input className=" w-24" type="number" step={5} min={30} {...field}></Input>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<Button type="submit">Submit</Button>
</form>

View File

@ -24,6 +24,7 @@ import GenresTrigger from "./genresTrigger"
import GenreCheckbox from "./genreCheckbox"
import { useRef, useImperativeHandle, ComponentProps } from "react"
import { Genre } from "@prisma/client"
import { randomStoryTitle } from "app/lib/shortStoryTitleGenerator"
const formSchema = z.object({
title: z.string().min(2).max(50),
@ -85,37 +86,28 @@ export default function StoryForm({ genres, createStory, className }: ComponentP
<FormItem>
<FormLabel>Title</FormLabel>
<FormControl>
<Input placeholder="title goes here..." {...field} />
<Input placeholder={randomStoryTitle()} {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="word_count"
render={({ field }) => (
<FormItem>
<FormLabel>Word count</FormLabel>
<FormControl>
<Input className="w-24" type="number" step={500} min={0} {...field}></Input>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<div className="inline-flex flex-wrap w-full gap-x-16 gap-y-8 items-baseline max-w-full">
<FormField
control={form.control}
name="genres"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel className="h-5">Genres</FormLabel>
<Popover>
<GenresTrigger value={field.value} genres={genres} />
<PopoverContent>
<PopoverContent align="start">
{genres.map((item) => (
<FormField
key={item.id}
control={form.control}
name="genres"
@ -133,7 +125,24 @@ export default function StoryForm({ genres, createStory, className }: ComponentP
)}
/>
<Button type="submit">Submit</Button>
<FormField
control={form.control}
name="word_count"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel className="h-5">Word count</FormLabel>
<FormControl>
<Input className=" w-24" type="number" step={500} min={0} {...field}></Input>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</div>
<Button type="submit" className="">Submit</Button>
</form>
</Form>
</div>

View File

@ -23,7 +23,7 @@ export default function Navlinks(props: ComponentProps<"div">) {
<div className="text-secondary-foreground" >
{
links.map(e => (<NavLink key={e.link} href={e.link}
className={twMerge(clsx("text-xl drop-shadow font-black my-2 w-full pl-2 antialiased text-secondary-foreground bg-secondary",
className={twMerge(clsx("text-xl drop-shadow font-black my-2 w-full p-2 pl-6 antialiased text-secondary-foreground bg-secondary rounded-l-3xl",
{
"text-primary-foreground bg-primary": pathname.includes(e.link)
}