dumb refactor but sunk cost is to great keep pushing

This commit is contained in:
2025-08-03 22:53:52 +02:00
parent 2816842b5d
commit e74b30e04c
35 changed files with 621 additions and 1287 deletions

View File

@@ -1,12 +1,17 @@
'use server'
'use client'
import UpdateCvCategoryForm from "../_components/UpdateForm";
import { trpc } from "~/app/_trpc/Client";
import { useParams } from "next/navigation";
import CreateUpdateCvCategoryForm from "../_components/CreateUpdateForm";
export default async function Page({params}:{params: Promise<{id:string}>}) {
console.log(params)
const {id} = await params;
return (
<UpdateCvCategoryForm id={id} />
)
export default function Page() {
const {id} = useParams<{id: string}>();
const {data} = trpc.category.select.useQuery({id: id})
if (data !== undefined && data.length > 0) {
return (
<CreateUpdateCvCategoryForm category={data[0]}/>
)
}
return (<></>)
}

View File

@@ -1,12 +1,10 @@
import { ChevronsUpDown, Plus } from "lucide-react"
import { Button } from "~/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "~/components/ui/collapsible";
import { type EntryRouterOutputs } from "~/server/routers/cv/entry";
import type { CategoryRouterOutputs } from "~/server/routers/cv/category";
import { type Element } from "~/lib/utils";
import UpdateCvCategoryForm from "./UpdateForm";
import CreateCvCategoryForm from "./CreateForm";
export default function CollapsibleCvCategoryForm(params:{category?:Element<CategoryRouterOutputs['list']>}) {
import CreateUpdateCvCategoryForm from "./CreateUpdateForm";
import type { RouterOutputs } from "~/server/routers/_app";
export default function CollapsibleCvCategoryForm(params:{category?:Element<RouterOutputs['category']['select']>}) {
return (
<Collapsible >
<CollapsibleTrigger asChild>
@@ -19,8 +17,8 @@ export default function CollapsibleCvCategoryForm(params:{category?:Element<Cate
<CollapsibleContent className="autoAlpha">
{
params.category ?
<UpdateCvCategoryForm className="w-full" id={params.category.id} key={params.category.id} /> :
<CreateCvCategoryForm className="w-full"/>
<CreateUpdateCvCategoryForm className="w-full" category={params.category} /> :
<CreateUpdateCvCategoryForm className="w-full"/>
}
</CollapsibleContent>

View File

@@ -1,48 +1,43 @@
'use client'
import { insertSchema } from "~/lib/schema/cv/category"
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from "zod";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "~/components/ui/form";
import { Form, FormControl, FormField, FormItem, FormLabel } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Select, SelectContent, SelectTrigger, SelectItem, SelectValue } from "~/components/ui/select";
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import type { IterableElement } from 'type-fest'
import { usePathname, useRouter } from "next/navigation";
import { entitySchemas } from "~/lib/utils";
import { entitySchemas, makeOnSuccess } from "~/lib/utils";
import type { RouterOutputs } from "~/server/routers/_app";
export default function CreateCvCategoryForm(params:{className?:string,category?:IterableElement<RouterOutputs['cv']['categoryv2']['select']>}) {
import DependentFormMessaage from '~/app/_components/MutationFormMessage';
import { useState } from 'react';
import DependentText from '~/app/_components/DependentText';
export default function CreateUpdateCvCategoryForm(params:{className?:string,category?:IterableElement<RouterOutputs['category']['select']>,isUpdate?:boolean}) {
const schemas = entitySchemas('cvCategory')
const pathname = usePathname();
const router = useRouter();
const [isUpdate,setIsUpdate] = useState<boolean>(params.isUpdate ? params.isUpdate : (params.category ? true : false))
const form = useForm<z.infer<typeof schemas.insert>>({
resolver: zodResolver(schemas.insert),
defaultValues: {
id: crypto.randomUUID(),
layoutPosition: "col1"
id: params.category ? params.category.id : crypto.randomUUID(),
name: params.category ? params.category.name : "",
layoutPosition: params.category ? params.category.layoutPosition : "col1"
}
})
const createMutation = trpc.cv.categoryv2.insert.useMutation()
const createMutation = trpc.category.insert.useMutation({onSuccess: makeOnSuccess('create',form,setIsUpdate)})
const updateMutation = trpc.category.update.useMutation({onSuccess: makeOnSuccess('update',form)})
function onSubmit(values: z.infer<typeof schemas.insert>) {
const res = createMutation.mutate(values)
isUpdate ?
updateMutation.mutate(values) :
createMutation.mutate(values)
}
const updateMutation = trpc.cv.categoryv2.update.useMutation()
const deleteMutation = trpc.cv.categoryv2.delete.useMutation({
onSuccess: () => {
if (pathname.includes('list')) {
router.refresh()
} else {
router.back()
}
}
})
//TODO use SelectFormField and TextInputFormField
return (
<Card.Card className={params.className ? params.className : "w-5/6 lg:w-1/2"}>
<Card.CardHeader>
<Card.CardTitle>
Create Category
<DependentText bool={isUpdate} true='Update Category' false='Create Category'/>
</Card.CardTitle>
</Card.CardHeader>
<Card.CardContent>
@@ -60,7 +55,7 @@ export default function CreateCvCategoryForm(params:{className?:string,category?
Name
</FormLabel>
<FormControl>
<Input placeholder="name" onChange={field.onChange} value={field.value == null ? undefined : field.value} />
<Input placeholder="name" onChange={field.onChange} value={field.value ? field.value : ""} />
</FormControl>
</FormItem>
)}
@@ -80,7 +75,7 @@ export default function CreateCvCategoryForm(params:{className?:string,category?
<SelectValue placeholder={form.getValues().layoutPosition} />
</SelectTrigger>
<SelectContent>
{insertSchema.shape.layoutPosition.unwrap().unwrap().options.map((o) => (
{schemas.insert.shape.layoutPosition.unwrap().unwrap().options.map((o) => (
<SelectItem key={o} value={o}> {o} </SelectItem>
))}
</SelectContent>
@@ -90,10 +85,10 @@ export default function CreateCvCategoryForm(params:{className?:string,category?
)}
>
</FormField>
<Button type="submit"> Create </Button>
<FormMessage className={createMutation.status == "success" ? "text-green-500" : "text-red-500"}>
{createMutation.error ? createMutation.error.message : createMutation.status}
</FormMessage>
<Button type="submit">
<DependentText bool={isUpdate} true='Update' false='Create'/>
</Button>
<DependentFormMessaage falseStatus={createMutation.status} trueStatus={updateMutation.status} falseError={createMutation.error} trueError={updateMutation.error} bool={isUpdate}/>
</form>
</Form>
</Card.CardContent>

View File

@@ -1,146 +0,0 @@
'use client'
import { updateRouteSchema } from "~/lib/schema/cv/category"
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from "zod";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Select, SelectContent, SelectTrigger, SelectItem, SelectValue } from "~/components/ui/select";
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import { useRouter, usePathname } from "next/navigation";
import { Delete } from "lucide-react";
import { cn } from "~/lib/utils";
export default function UpdateCvCategoryForm(params: { id: string, className?: string }) {
const router = useRouter();
const pathname = usePathname();
const id = params.id;
const category = trpc.cv.category.get.useQuery({ id: id })
const form = useForm<z.infer<typeof updateRouteSchema>>({
resolver: zodResolver(updateRouteSchema),
defaultValues: {
by: { id: id },
update: {
layoutPosition: category.data?.layoutPosition,
name: category.data?.layoutPosition
}
}
})
category.promise.then((data) => {
form.setValue("update.layoutPosition", data?.layoutPosition)
form.setValue("update.name", data?.name)
})
const updateMutation = trpc.cv.category.update.useMutation({
onSuccess: () => {
category.refetch()
}
})
const deleteMutation = trpc.cv.category.delete.useMutation({
onSuccess: () => {
if (pathname.includes('list')) {
router.refresh()
} else {
router.back()
}
}
})
const deleteCategory = (id: string) => {
console.log(`deleting ${id}`)
deleteMutation.mutate(id)
}
function onSubmit(values: z.infer<typeof updateRouteSchema>) {
updateMutation.mutate({
by: { id: id },
update: {
layoutPosition: values.update.layoutPosition,
name: values.update.name
}
})
}
if (category.data !== undefined) {
return (
<Card.Card className={params.className ? params.className : "w-5/6 lg:w-1/2"}>
<Card.CardHeader>
<Card.CardTitle>
Update Category
</Card.CardTitle>
</Card.CardHeader>
<Card.CardContent>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<FormField
control={form.control}
name="update.name"
render={({ field }) => (
<FormItem>
<FormLabel>
Name
</FormLabel>
<FormControl>
<Input placeholder="name" onChange={field.onChange} value={field.value == null ? undefined : field.value} />
</FormControl>
</FormItem>
)}
>
</FormField>
<FormField
control={form.control}
name="by.id"
render={({ field }) => (
<FormItem>
<FormControl>
<Input hidden onChange={field.onChange} value={field.value} />
</FormControl>
</FormItem>
)}
>
</FormField>
<FormField
control={form.control}
name="update.layoutPosition"
render={({ field }) => (
<FormItem>
<FormLabel>
Layout Position
</FormLabel>
<FormControl>
<Select onValueChange={field.onChange} defaultValue={field.value == null ? undefined : field.value}>
<SelectTrigger>
<SelectValue placeholder={form.getValues().update.layoutPosition} />
</SelectTrigger>
<SelectContent>
{updateRouteSchema.shape.update.shape.layoutPosition.unwrap().unwrap().options.map((o) => (
<SelectItem key={o} value={o}> {o} </SelectItem>
))}
</SelectContent>
</Select>
</FormControl>
</FormItem>
)}
>
</FormField>
<Button type="submit"> Update </Button>
<FormMessage className={cn(updateMutation.status == "success" ? "text-green-500" : "text-red-500", "flex flex-row justify-between")}>
{updateMutation.error ? updateMutation.error.message : updateMutation.status}
<Button
className="ml-auto cursor-pointer" variant="destructive" onClick={() => { deleteCategory(id) }}>
Delete
<Delete />
</Button>
</FormMessage>
</form>
</Form>
</Card.CardContent>
</Card.Card>
)
} else {
return (
<>
</>
)
}
}

View File

@@ -1,8 +1,8 @@
'use client'
import CreateCvCategoryForm from "../_components/CreateForm";
import CreateUpdateCvCategoryForm from "../_components/CreateUpdateForm";
export default function Page() {
return (
<CreateCvCategoryForm/>
<CreateUpdateCvCategoryForm/>
)
}

View File

@@ -2,26 +2,27 @@
import Link from "next/link";
import { trpc } from "~/app/_trpc/Client";
import { useGSAP } from '@gsap/react'
import { useRef } from "react";
import { Suspense, useRef } from "react";
import * as Card from '~/components/ui/card'
import { useGsapContext } from "~/app/_providers/GsapProvicer";
import CollapsibleCvEntryForm from "../../entry/_components/CollapsibleForm";
import UpdateCvCategoryForm from "../_components/UpdateForm";
import CollapsibleCvCategoryForm from "../_components/CollapsibleForm";
import CreateUpdateCvCategoryForm from "../_components/CreateUpdateForm";
export default function CvPage() {
const cvCategories = trpc.cv.category.list.useQuery(undefined,{refetchInterval:1000});
const categories = trpc.category.select.useQuery({},{refetchInterval:1000});
const entires = trpc.entry.select.useSuspenseQuery({},{refetchInterval:1000})
const gsap = useGsapContext()
const container = useRef<HTMLDivElement>(null);
useGSAP(() => {
gsap?.from('.gsapan', { x: -100, opacity: 0, duration: 0.5, stagger: { each: 0.3 } });
}, { scope: container, dependencies: [cvCategories.status], revertOnUpdate: true });
}, { scope: container, dependencies: [categories.status], revertOnUpdate: true });
return (
<div ref={container} className="w-5/6 lg:w-1/2 flex flex-col gap-3">
{cvCategories.data == undefined ?
{categories.data == undefined ?
<div className="gsapan"></div>
:
<>
{cvCategories.data.map((cat) => {
{categories.data.map((cat) => {
return (
<Card.Card className="gsapan" key={cat.id}>
<Link href={`/admin/cv/category/${cat.id}`}>
@@ -33,20 +34,22 @@ export default function CvPage() {
</Link>
<Card.CardContent className="flex flex-row">
<div className="flex flex-col w-full">
<UpdateCvCategoryForm id={cat.id} className="w-full" />
<CreateUpdateCvCategoryForm category={cat} className="w-full" />
<br />
<span>Entries:</span>
<Suspense fallback={(<></>)}>
<div className="w-full">
{
cat.cvEntry.length > 0 ? (
entires[0].filter((e) => {return e.categoryId == cat.id}).length > 0 ? (
<>
{cat.cvEntry.map((entry) => (
{entires[0].filter((e) => {return e.categoryId == cat.id}).map((entry) => (
<CollapsibleCvEntryForm key={entry.id} entry={entry}/>
))}
</>
) : (<></>)
}
</div>
</Suspense>
<div className="flex flex-col w-full">
<CollapsibleCvEntryForm categoryId={cat.id} />
</div>

View File

@@ -1,12 +1,16 @@
'use server'
'use client'
import UpdateCvEntryForm from "../_components/UpdateForm";
import { trpc } from "~/app/_trpc/Client";
import { useParams } from "next/navigation";
import CreateUpdateCvEntryForm from "../_components/CreateUpdateForm";
export default async function Page({params}:{params: Promise<{id:string}>}) {
console.log(params)
const {id} = await params;
return (
<UpdateCvEntryForm id={id} className={undefined} />
)
export default function Page() {
const {id} = useParams<{id: string}>();
const {data} = trpc.entry.select.useQuery({id: id})
if (data !== undefined && data.length > 0) {
return (
<CreateUpdateCvEntryForm entry={data[0]}/>
)
}
return (<></>)
}

View File

@@ -1,12 +1,10 @@
import { ChevronsUpDown, Plus } from "lucide-react"
import { Button } from "~/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "~/components/ui/collapsible";
import { type EntryRouterOutputs } from "~/server/routers/cv/entry";
import type { CategoryRouterOutputs } from "~/server/routers/cv/category";
import { type Element } from "~/lib/utils";
import UpdateCvEntryForm from "./UpdateForm";
import CreateCvEntryForm from "./CreateForm";
export default function CollapsibleCvEntryForm(params:{entry?:Element<Element<CategoryRouterOutputs['list']>['cvEntry']>|EntryRouterOutputs['get']|Element<EntryRouterOutputs['list']>, categoryId?: string}) {
import CreateUpdateCvEntryForm from "./CreateUpdateForm";
import type { IterableElement } from "type-fest";
import type { RouterOutputs } from "~/server/routers/_app";
export default function CollapsibleCvEntryForm(params:{entry?:IterableElement<RouterOutputs['entry']['select']>, categoryId?: string}) {
return (
<Collapsible>
<CollapsibleTrigger asChild>
@@ -19,9 +17,8 @@ export default function CollapsibleCvEntryForm(params:{entry?:Element<Element<Ca
<CollapsibleContent className="autoAlpha">
{
params.entry ?
<UpdateCvEntryForm id={params.entry.id} className="w-full" key={params.entry.id} /> :
<CreateCvEntryForm className="w-full" categoryId={params.categoryId ? params.categoryId : undefined}/>
<CreateUpdateCvEntryForm className="w-full" entry={params.entry}/> :
<CreateUpdateCvEntryForm className="w-full"/>
}
</CollapsibleContent>
</Collapsible>

View File

@@ -1,254 +0,0 @@
'use client'
import { insertSchema, insertSchemaForm } from "~/lib/schema/cv/entry"
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { format } from 'date-fns'
import { z } from "zod";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Select, SelectContent, SelectTrigger, SelectItem, SelectValue } from "~/components/ui/select";
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import { Popover, PopoverContent, PopoverTrigger } from "~/components/ui/popover";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "~/components/ui/calendar";
import { cn } from "~/lib/utils";
import { useEffect, useState } from "react"
import { Checkbox } from "~/components/ui/checkbox"
import MDEditor from '@uiw/react-md-editor'
import { useTheme } from "next-themes"
export default function CreateCvEntryForm(params:{className:string|undefined, categoryId:string|undefined}) {
const { theme } = useTheme()
const categories = trpc.cv.category.list.useQuery()
const [categorySelectPlaceHolder,setCategorySelectPlaceHolder] = useState("Select category")
const [categorySelectDefaultValue,setCategorySelectDefaultValue] = useState("")
const [mdeTab,setMdeTab] = useState<"write" | "preview" | undefined>("write");
useEffect(() => {
console.log('category success effect')
if (categories.data !== undefined) {
setCategorySelectDefaultValue(categories.data[0]?.id? categories.data[0].id : "")
setCategorySelectPlaceHolder(categories.data[0]?.name? categories.data[0].name : "Select category")
}
if (params.categoryId) {
let matching = categories.data?.filter((c) => {
return c.id == params.categoryId
})
if (matching !== undefined && matching.length > 0) {
setCategorySelectDefaultValue(matching[0]?.id ? matching[0].id : categorySelectDefaultValue )
setCategorySelectPlaceHolder(matching[0]?.name ? matching[0].name : categorySelectPlaceHolder)
}
}
},[categories.isSuccess])
const now = new Date();
now.setTime(Date.now());
const form = useForm<z.infer<typeof insertSchemaForm>>({
resolver: zodResolver(insertSchemaForm),
defaultValues: {
id: crypto.randomUUID(),
title: "",
description: "",
categoryId: params.categoryId ? params.categoryId : "",
fromTime: now,
toTime: now,
hideDates: false,
}
})
const mutation = trpc.cv.entry.create.useMutation({
onSuccess: (data) => { form.setValue("id", data[0] ? data[0].id : "") }
})
function onSubmit(values: z.infer<typeof insertSchemaForm>) {
let { id, title, categoryId, description, hideDates } = values
let v: z.infer<typeof insertSchema> = {
id: id,
categoryId: categoryId,
description: description,
title: title,
fromTime: format(values.fromTime,'yyyy-MM-dd'),
toTime: format(values.toTime,'yyyy-MM-dd'),
hideDates: hideDates
}
mutation.mutate(v)
form.setValue("id", crypto.randomUUID())
}
return (
<Card.Card className={params.className ? params.className : "w-5/6 lg:w-1/2"}>
<Card.CardHeader>
<Card.CardTitle>
Create Entry
</Card.CardTitle>
</Card.CardHeader>
<Card.CardContent>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<FormField
control={form.control}
name="categoryId"
render={({ field }) => (
<FormItem>
<FormLabel>
Category
</FormLabel>
{
categories.data ? (
<Select onValueChange={field.onChange} defaultValue={categorySelectDefaultValue}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={categorySelectPlaceHolder} />
</SelectTrigger>
</FormControl>
<SelectContent>
{ categories.data?.map((c) => {
return (<SelectItem key={c.id} value={c.id}> {c.name} </SelectItem>)
})}
</SelectContent>
</Select>
) : <Select></Select>
}
</FormItem>
)}
/>
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>
Title
</FormLabel>
<FormControl>
<Input placeholder="title" onChange={field.onChange} value={field.value == null ? undefined : field.value} />
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="description"
render={({ field }) => (
<FormItem>
<FormLabel>
Description
</FormLabel>
<FormControl>
<MDEditor
value={field.value ? field.value : ""}
onChange={field.onChange}
data-color-mode={theme ? theme : "dark"}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="fromTime"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>From Date</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="toTime"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>To Date</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="hideDates"
render={({field}) => (
<FormItem>
<FormLabel>Hide dates</FormLabel>
<FormControl>
<Checkbox
checked={field.value ? field.value : false}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<Button type="submit"> Create </Button>
<FormMessage className={mutation.status == "success" ? "text-green-500" : "text-red-500"}>
{mutation.error ? mutation.error.message : mutation.status}
</FormMessage>
</form>
</Form>
</Card.CardContent>
</Card.Card>
)
}

View File

@@ -0,0 +1,119 @@
'use client'
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm, type UseFormReturn } from 'react-hook-form'
import { format } from 'date-fns'
import { z } from "zod";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Select, SelectContent, SelectTrigger, SelectItem, SelectValue } from "~/components/ui/select";
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import { Popover, PopoverContent, PopoverTrigger } from "~/components/ui/popover";
import { CalendarIcon } from "lucide-react";
import { Calendar } from "~/components/ui/calendar";
import { cn, entitySchemas, ft, makeOnSuccess, tt, type DatesAreString, type Pretty } from "~/lib/utils";
import { Checkbox } from "~/components/ui/checkbox"
import MDEditor from '@uiw/react-md-editor'
import { useTheme } from "next-themes"
import type { Entries, IterableElement } from 'type-fest';
import type { RouterOutputs } from '~/server/routers/_app';
import DependentText from '~/app/_components/DependentText';
import DependentFormMessaage from '~/app/_components/MutationFormMessage';
import { useEffect, useState } from 'react';
import SelectFormField from '~/app/_components/SelectFormField';
import TexttInputFormField from '~/app/_components/TextInputFormField';
import MdeFormField from '~/app/_components/MdeFormField';
import CalendarFormField from '~/app/_components/CalenderFormField';
export default function CreateUpdateCvEntryForm(params: { className?: string, entry?: IterableElement<RouterOutputs['entry']['select']>, isUpdate?: boolean }) {
const [isUpdate, setIsUpdate] = useState<boolean>(params.isUpdate ? params.isUpdate : (params.entry ? true : false))
const [categoryId,setCategoryId] = useState<string|undefined>()
const [categoryName,setCategoryName] = useState<string|undefined>()
const { theme } = useTheme()
const schemas = entitySchemas('cvEntry')
const {data:categories,isSuccess: categoriesSuccess} = trpc.category.select.useQuery({})
useEffect(() => {
if (isUpdate) {
return
}
setCategoryId(categories?.at(0)?.id)
if (categories !== undefined && categories[0]?.name !== null) {
setCategoryName(categories[0]?.name)
}
},[categoriesSuccess])
let defaultValues = {
id: params.entry ? params.entry.id : crypto.randomUUID(),
title: params.entry ? params.entry.title : "",
description: params.entry ? params.entry.description : "",
categoryId: params.entry ? params.entry.categoryId : categoriesSuccess ? categories.at(0)?.id : "",
fromTime: params.entry ? ft(params.entry).fromTime : new Date(),
toTime: params.entry ? tt(params.entry).toTime : new Date(),
hideDates: params.entry ? params.entry.hideDates : false,
};
const form = useForm<z.infer<typeof schemas.insert>>({
resolver: zodResolver(schemas.insert),
defaultValues: defaultValues,
// values: params.entry ? ut(ct(tt(ff(params.entry)))) : defaultValues
})
const createMutation = trpc.entry.insert.useMutation({onSuccess: makeOnSuccess('create',form,setIsUpdate)})
const updateMutation = trpc.entry.update.useMutation({onSuccess: makeOnSuccess('update',form)})
function onSubmit(values: z.infer<typeof schemas.insert>) {
isUpdate ?
updateMutation.mutate(values) :
createMutation.mutate(values)
}
//TODO use SelectFormField and TextInputFormField
return (
<Card.Card className={params.className ? params.className : "w-5/6 lg:w-1/2"}>
<Card.CardHeader>
<Card.CardTitle>
<DependentText bool={isUpdate} true='Update Entry' false='Create Entry' />
</Card.CardTitle>
</Card.CardHeader>
<Card.CardContent>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<SelectFormField control={form.control} name='categoryId' label='Category' defaultValue={categoryId} placeholder={categoryName}>
{
categoriesSuccess ?
<>
{categories.map((c) => {
return (<SelectItem key={c.id} value={c.id}> {c.name} </SelectItem>)
})}
</> :
<SelectItem key="abc" value="abcd"/>
}
</SelectFormField>
<TexttInputFormField control={form.control} name='title' label='Title'/>
<MdeFormField control={form.control} name='description' label='Description' dataColorMode={(theme as "dark" | "light") ? (theme as "dark" | "light") : "dark"}/>
<CalendarFormField control={form.control} name='fromTime' label='From Date'/>
<CalendarFormField control={form.control} name='toTime' label='To Date'/>
<FormField
control={form.control}
name="hideDates"
render={({ field }) => (
<FormItem>
<FormLabel>Hide dates</FormLabel>
<FormControl>
<Checkbox
checked={field.value ? field.value : false}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<Button type="submit">
<DependentText bool={isUpdate} true='Update' false='Create' />
</Button>
<DependentFormMessaage falseStatus={createMutation.status} trueStatus={updateMutation.status} falseError={createMutation.error} trueError={updateMutation.error} bool={isUpdate} />
</form>
</Form>
</Card.CardContent>
</Card.Card>
)
}

View File

@@ -1,275 +0,0 @@
'use client'
import { updateRouteSchema, updateRouteSchemaCliennt } from "~/lib/schema/cv/entry"
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from "zod";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import { Select, SelectContent, SelectTrigger, SelectItem, SelectValue } from "~/components/ui/select";
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import { format } from 'date-fns'
import { Popover, PopoverContent, PopoverTrigger } from "~/components/ui/popover";
import { cn, type Element } from "~/lib/utils";
import { CalendarIcon, Delete } from "lucide-react";
import { Calendar } from "~/components/ui/calendar";
import { Textarea } from "~/components/ui/textarea";
import { usePathname, useRouter } from "next/navigation";
import { Checkbox } from "~/components/ui/checkbox";
import MDEditor from '@uiw/react-md-editor'
import { useTheme } from "next-themes"
import type { EntryRouterOutputs } from "~/server/routers/cv/entry";
export default function UpdateCvEntryForm(params : { id: string, className: string | undefined }) {
const { theme } = useTheme()
const id = params.id
const categories = trpc.cv.category.list.useQuery()
const entry = trpc.cv.entry.get.useQuery({ id: id })
const router = useRouter();
const pathname = usePathname();
const form = useForm<z.infer<typeof updateRouteSchemaCliennt>>({
resolver: zodResolver(updateRouteSchemaCliennt),
defaultValues: {
by: { id: id },
update: {
categoryId: entry.data?.categoryId,
title: entry.data?.title,
description: entry.data?.description,
}
}
})
const updateFormValues = (v:EntryRouterOutputs['get']|Element<EntryRouterOutputs['update']>) => {
form.setValue('update.title', v?.title)
form.setValue('update.description', v?.description);
form.setValue('update.fromTime', new Date(Date.parse(v ? v.fromTime : "")))
form.setValue('update.toTime', new Date(Date.parse(v ? v.toTime : "")))
form.setValue('update.categoryId', v?.categoryId)
form.setValue('update.hideDates', v?.hideDates)
}
entry.promise.then((v) => {
updateFormValues(v)
})
const updateMutation = trpc.cv.entry.update.useMutation({
onSuccess: (v) => {
if (v[0] !== undefined) {
updateFormValues(v[0])
}
}
})
const deleteMutation = trpc.cv.entry.delete.useMutation({
onSuccess: () => {
if (!pathname.includes('list')) {
router.back()
}
}
})
const deleteEntry = (id: string) => {
deleteMutation.mutate(id)
}
function onSubmit(values: z.infer<typeof updateRouteSchemaCliennt>) {
let { title, categoryId, description, hideDates } = values.update;
updateMutation.mutate({
by: { id: id },
update: {
fromTime: format(values.update.fromTime, 'yyyy-MM-dd'),
toTime: format(values.update.toTime, 'yyyy-MM-dd'),
title: title,
categoryId: categoryId,
description: description,
hideDates: hideDates
}
})
}
if (entry.data !== undefined) {
return (
<Card.Card className={params.className ? params.className : "w-5/6 lg:w-1/2"}>
<Card.CardHeader>
<Card.CardTitle>
Create Entry
</Card.CardTitle>
</Card.CardHeader>
<Card.CardContent>
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<FormField
control={form.control}
name="update.categoryId"
render={({ field }) => (
<FormItem>
<FormLabel>
Category
</FormLabel>
{
categories.data ? (
<Select onValueChange={field.onChange} defaultValue={categories.data[0]?.id}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={categories.data[0]?.name ? categories.data[0]?.name : "Select category"} />
</SelectTrigger>
</FormControl>
<SelectContent>
{categories.data?.map((c) => {
return (<SelectItem key={c.id} value={c.id}> {c.name} </SelectItem>)
})}
</SelectContent>
</Select>
) : <Select></Select>
}
</FormItem>
)}
/>
<FormField
control={form.control}
name="update.title"
render={({ field }) => (
<FormItem>
<FormLabel>
Title
</FormLabel>
<FormControl>
<Input placeholder="title" onChange={field.onChange} value={field.value == null ? undefined : field.value} />
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="update.description"
render={({ field }) => (
<FormItem>
<FormLabel>
Description
</FormLabel>
<FormControl>
<MDEditor
value={field.value ? field.value : ""}
onChange={field.onChange}
data-color-mode={theme ? theme : "dark"}
previewOptions={{skipHtml:false}}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="update.fromTime"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>From Date</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="update.toTime"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>To Date</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant={"outline"}
className={cn(
"w-[240px] pl-3 text-left font-normal",
!field.value && "text-muted-foreground"
)}
>
{field.value ? (
format(field.value, "PPP")
) : (
<span>Pick a date</span>
)}
<CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={field.value}
onSelect={field.onChange}
disabled={(date) =>
date > new Date() || date < new Date("1900-01-01")
}
initialFocus
/>
</PopoverContent>
</Popover>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name="update.hideDates"
render={({field}) => (
<FormItem>
<FormLabel>Hide dates</FormLabel>
<FormControl>
<Checkbox
checked={field.value ? field.value : false}
onCheckedChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
<Button type="submit"> Update </Button>
<FormMessage className={cn(updateMutation.status == "success" ? "text-green-500" : "text-red-500", "flex flex-row justify-between")}>
{updateMutation.error ? updateMutation.error.message : updateMutation.status}
<Button
className="ml-auto cursor-pointer" variant="destructive" onClick={() => { deleteEntry(id) }}>
Delete
<Delete />
</Button>
</FormMessage>
</form>
</Form>
</Card.CardContent>
</Card.Card>
)
} else {
return (
<>
</>
)
}
}

View File

@@ -1,8 +1,8 @@
'use client'
import CreateCvEntryForm from "../_components/CreateForm"
import CreateUpdateCvEntryForm from "../_components/CreateUpdateForm"
export default function Page() {
return (
<CreateCvEntryForm/>
<CreateUpdateCvEntryForm />
)
}

View File

@@ -7,19 +7,19 @@ import * as Card from '~/components/ui/card'
import { useGsapContext } from "~/app/_providers/GsapProvicer";
export default function CvPage() {
const cvEntries = trpc.cv.entry.list.useQuery();
const entires = trpc.entry.select.useQuery({});
const gsap = useGsapContext()
const container = useRef<HTMLDivElement>(null);
useGSAP(() => {
gsap?.from('.gsapan', { x: -100, opacity: 0, duration: 0.5, stagger: { each: 0.3 } })
}, { scope: container, dependencies: [cvEntries.status], revertOnUpdate: true });
}, { scope: container, dependencies: [entires.status], revertOnUpdate: true });
return (
<div ref={container} className="w-5/6 lg:w-1/2 flex flex-col gap-3">
{cvEntries.data == undefined ?
{entires.data == undefined ?
<div className="gsapan"></div>
:
<>
{cvEntries.data.map((ent) => {
{entires.data.map((ent) => {
return (
<Card.Card className="gsapan" key={ent.id}>
<Link href={`/admin/cv/entry/${ent.id}`}>
@@ -31,9 +31,8 @@ export default function CvPage() {
</Link>
<Card.CardContent className="flex flex-row">
<div>
Category id : {ent.id} <br />
Category Name :
<Link href={`/admin/cv/entry/${ent.categoryId}`}> {ent.category?.name} </Link>
Category:
<Link href={`/admin/cv/category/${ent.categoryId}`}> {ent.categoryId} </Link>
</div>
</Card.CardContent>
</Card.Card>

View File

@@ -2,9 +2,9 @@ import { ChevronsUpDown, Plus } from "lucide-react"
import { Button } from "~/components/ui/button";
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "~/components/ui/collapsible";
import { type Element } from "~/lib/utils";
import CreateUpdateProjectForm from "./CreateForm";
import type { ProjectRouterOutputs } from "~/server/routers/project";
export default function CollapsibleForm(params:{project:Element<ProjectRouterOutputs['list']>|undefined}) {
import CreateUpdateProjectForm from "./CreateUpdateProjectForm";
import type { RouterOutputs } from "~/server/routers/_app";
export default function CollapsibleForm(params:{project?:Element<RouterOutputs['project']['select']>}) {
return (
<Collapsible >
<CollapsibleTrigger asChild>
@@ -18,7 +18,7 @@ export default function CollapsibleForm(params:{project:Element<ProjectRouterOut
{
params.project ?
<CreateUpdateProjectForm className="w-full" project={params.project}/> :
<CreateUpdateProjectForm className="w-full" project={params.project}/>
<CreateUpdateProjectForm className="w-full"/>
}
</CollapsibleContent>

View File

@@ -1,5 +1,4 @@
"use client"
import { insertSchema } from "~/lib/schema/project/project"
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from "zod";
@@ -9,41 +8,56 @@ import { Select, SelectContent, SelectTrigger, SelectItem, SelectValue } from "~
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import type { Entries } from 'type-fest'
import { type Element } from "~/lib/utils";
import type { ProjectRouterOutputs } from "~/server/routers/project";
import { Suspense } from "react";
export default function CreateUpdateProjectForm(params:{className?:string, project?:Element<ProjectRouterOutputs['list']>}) {
const [techStacks,] = trpc.project.stack.list.useSuspenseQuery()
const form = useForm<z.infer<typeof insertSchema>>({
resolver: zodResolver(insertSchema),
import type { Entries, IterableElement } from 'type-fest'
import { entitySchemas, makeOnSuccess } from "~/lib/utils";
import { Suspense, useEffect, useState } from "react";
import type { RouterOutputs } from '~/server/routers/_app';
import TexttInputFormField from '~/app/_components/TextInputFormField';
import SelectFormField from '~/app/_components/SelectFormField';
import DependentFormMessaage from '~/app/_components/MutationFormMessage';
import DependentText from '~/app/_components/DependentText';
export default function CreateUpdateProjectForm(params: { className?: string, project?: IterableElement<RouterOutputs['project']['select']>, isUpdate?: boolean }) {
const [isUpdate, setIsUpdate] = useState<boolean>(params.isUpdate ? params.isUpdate : (params.project ? true : false))
const [stackId, setstackId] = useState<string | undefined>()
const [stackName, setstackName] = useState<string | undefined>()
const schemas = entitySchemas('project')
const { data: stacks, isSuccess: stacksSuccess } = trpc.techStack.select.useQuery({})
useEffect(() => {
if (isUpdate) {
return
}
setstackId(stacks?.at(0)?.id)
if (stacks !== undefined) {
setstackName(stacks.at(0)?.stackItems ? stacks.at(0)?.stackItems?.join("-") : "")
}
}, [stacksSuccess])
const form = useForm<z.infer<typeof schemas.insert>>({
resolver: zodResolver(schemas.insert),
defaultValues: {
id: params.project ? params.project.id : crypto.randomUUID(),
id: params.project ? params.project.id : crypto.randomUUID(),
stackId: params.project ? params.project.stackId : stacksSuccess ? stacks?.at(0)?.id : "",
releaseStatus: params.project ? params.project.releaseStatus : "unreleased",
releaseLink: params.project ? params.project.releaseLink : "",
sourceType: params.project ? params.project.sourceType : "open",
sourceLink: params.project ? params.project.sourceLink : ""
}
})
const createMutation = trpc.project.create.useMutation({
onSuccess: (data) => { form.setValue("id", data[0] ? data[0].id : "") }
const createMutation = trpc.project.insert.useMutation({
onSuccess: makeOnSuccess('create',form,setIsUpdate)
})
const updateMutation = trpc.project.update.useMutation({
onSuccess: (data) => {
if (data.length > 0 && data[0] !== undefined) {
let entries = Object.entries(data[0]) as Entries<typeof data[0]>
entries.forEach( (entry) => {
form.setValue(entry[0],entry[1])
})
}
}
onSuccess: makeOnSuccess('update',form)
})
function onSubmit(values: z.infer<typeof insertSchema>) {
function onSubmit(values: z.infer<typeof schemas.insert>) {
params.project ?
updateMutation.mutate({by: {id: values.id}, update: { ...values}}) :
updateMutation.mutate(values) :
createMutation.mutate(values)
}
return (
<Card.Card className={params.className ? params.className : "w-5/6 lg:w-1/2"}>
<Card.CardHeader>
<Card.CardTitle>
Create Entry
<DependentText bool={isUpdate} true='Update Project' false='Create Project'/>
</Card.CardTitle>
</Card.CardHeader>
<Card.CardContent>
@@ -52,99 +66,32 @@ export default function CreateUpdateProjectForm(params:{className?:string, proje
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-8"
>
<FormField
control={form.control}
name="stackId"
render={({ field }) => (
<FormItem>
<FormLabel>
Stack
</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value ? field.value : ""}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={field.value ? field.value : ""} />
</SelectTrigger>
</FormControl>
<SelectContent>
<Suspense fallback={(<> </>)}>
{techStacks.map((stack) => {
return (<SelectItem key={stack.id} value={stack.id}> { stack.stackItems ? stack.stackItems.join("-") : "Empty Stack" } </SelectItem>)
})}
</Suspense>
</SelectContent>
</Select>
</FormItem>
)}
/>
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>
Title
</FormLabel>
<FormControl>
<Input placeholder="title" onChange={field.onChange} value={field.value == null ? undefined : field.value} />
</FormControl>
</FormItem>
)}
/>
<FormField
control={form.control}
name="sourceType"
render={({ field }) => (
<FormItem>
<FormLabel>
Source Type
</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value ? field.value : "open"}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={field.value} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="open"> open </SelectItem>
<SelectItem value="closed"> closed </SelectItem>
</SelectContent>
</Select>
</FormItem>
)}
/>
<FormField
control={form.control}
name="releaseStatus"
render={({ field }) => (
<FormItem className="flex flex-col">
<FormLabel>Release Status</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value ? field.value : "released"}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder={field.value} />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="released"> released </SelectItem>
<SelectItem value="unreleased"> unreleased </SelectItem>
</SelectContent>
</Select>
</FormItem>
)}
/>
<Button type="submit"> Create </Button>
<FormMessage className={updateMutation.status == "success" || createMutation.status == "success" ? "text-green-500" : "text-red-500"}>
{ params.project ?
(
<>{updateMutation.error ? updateMutation.error.message : updateMutation.status}</>
) :
(
<>{createMutation.error ? createMutation.error.message : createMutation.status}</>
)
<SelectFormField control={form.control} name='stackId' label='Stack' defaultValue={stackId} placeholder={stackName} >
{
stacksSuccess ?
<>
{stacks.map((stack) => {
return (<SelectItem key={stack.id} value={stack.id}> {stack.stackItems ? stack.stackItems.join("-") : "Empty Stack"} </SelectItem>)
})}
</> :
<SelectItem key='placeholder' value="placeholder" />
}
</FormMessage>
</SelectFormField>
<TexttInputFormField control={form.control} name='title' label='Title' />
<SelectFormField control={form.control} name='sourceType' label='Source Type' defaultValue={'open'} placeholder='open' >
<SelectItem value="open"> open </SelectItem>
<SelectItem value="closed"> closed </SelectItem>
</SelectFormField>
<TexttInputFormField control={form.control} label='Source Link' name='sourceLink' />
<SelectFormField control={form.control} name='releaseStatus' label='Release Status' defaultValue={'unreleased'} placeholder='unreleased' >
<SelectItem value="released"> released </SelectItem>
<SelectItem value="unreleased"> unreleased </SelectItem>
</SelectFormField>
<TexttInputFormField control={form.control} label='Release Link' name='releaseLink' />
<Button type="submit">
<DependentText bool={isUpdate} true='Update' false='Create'/>
</Button>
<DependentFormMessaage falseStatus={createMutation.status} trueStatus={updateMutation.status} falseError={createMutation.error} trueError={updateMutation.error} bool={isUpdate}/>
</form>
</Form>
</Card.CardContent>

View File

@@ -1,5 +1,4 @@
"use client"
import { insertSchema } from "~/lib/schema/project/techStack"
import { zodResolver } from '@hookform/resolvers/zod'
import { useForm } from 'react-hook-form'
import { z } from "zod";
@@ -8,36 +7,42 @@ import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "
import { trpc } from "~/app/_trpc/Client";
import { Button } from "~/components/ui/button";
import * as Card from '~/components/ui/card'
import type { Entries } from 'type-fest'
import { type Element } from "~/lib/utils";
import type { StackRouter, StackRouterOutputs } from "~/server/routers/project/techStack";
import type { Entries, IterableElement } from 'type-fest'
import { stackItemEnum } from "~/server/db/schema";
import { ToggleGroup, ToggleGroupItem } from "~/components/ui/toggle-group";
import type { RouterOutputs } from '~/server/routers/_app';
import { entitySchemas } from '~/lib/utils';
import { useState } from 'react';
export default function CreateUpdateForm(params:{className:string|undefined, techStack?:Element<StackRouterOutputs['list']>}) {
const form = useForm<z.infer<typeof insertSchema>>({
resolver: zodResolver(insertSchema),
export default function CreateUpdateStackForm(params:{className?:string, techStack?:IterableElement<RouterOutputs['techStack']['select']>,isUpdate?: boolean }) {
const schemas = entitySchemas('techStack')
const form = useForm<z.infer<typeof schemas.insert>>({
resolver: zodResolver(schemas.insert),
defaultValues: {
id: params.techStack ? params.techStack.id : crypto.randomUUID(),
stackItems: params.techStack ? params.techStack.stackItems : [],
}
})
const createMutation = trpc.project.stack.create.useMutation({
onSuccess: (data) => { form.setValue("id", data[0] ? data[0].id : "") }
const [isUpdate, setIsUpdate] = useState<boolean>(params.isUpdate ? params.isUpdate : (params.techStack ? true : false))
const createMutation = trpc.techStack.insert.useMutation({
onSuccess: (data) => {
form.setValue("id", data[0] ? data[0].id : "");
setIsUpdate(true)
}
})
const updateMutation = trpc.project.stack.update.useMutation({
const updateMutation = trpc.techStack.update.useMutation({
onSuccess: (data) => {
if (data.length > 0 && data[0] !== undefined) {
let entries = Object.entries(data[0]) as Entries<typeof data[0]>
entries.forEach( (entry) => {
form.setValue(entry[0],entry[1])
entries.forEach((entry) => {
form.setValue(entry[0], entry[1])
})
}
}
})
function onSubmit(values: z.infer<typeof insertSchema>) {
function onSubmit(values: z.infer<typeof schemas.insert>) {
params.techStack ?
updateMutation.mutate({by: {id: values.id}, update: { ...values}}) :
updateMutation.mutate(values) :
createMutation.mutate(values)
}
return (