music and animation system
This commit is contained in:
@@ -20,6 +20,9 @@ export default async function AdminSideBar() {
|
||||
<Link href={"/admin/project/techStack/create"}> Create Stack </Link>
|
||||
<Link href={"/admin/project/list"}> Project List </Link>
|
||||
</SimpleSidebarGroup>
|
||||
<SimpleSidebarGroup lable="Music">
|
||||
<Link href={"/admin/music"}> Manage Music </Link>
|
||||
</SimpleSidebarGroup>
|
||||
<SimpleSidebarGroup lable="Blog">
|
||||
<Link href={"/"}> Some Blog Action </Link>
|
||||
</SimpleSidebarGroup>
|
||||
|
||||
@@ -14,13 +14,13 @@ import { SelectItem } from '~/components/ui/select';
|
||||
import {FormMutationContextProvider} from '~/app/_components/Form/Components/MutationProvider';
|
||||
export default function CreateUpdateCvCategoryForm(params: { className?: string, entity?: IterableElement<RouterOutputs['category']['select']> }) {
|
||||
const schemas = entitySchemas('cvCategory')
|
||||
const [id, setId] = useState<string | undefined>(params.entity ? params.entity.id : undefined)
|
||||
const [id, setId] = useState<string | undefined>(params.entity?.id)
|
||||
const form = useForm<z.infer<typeof schemas.insert>>({
|
||||
resolver: zodResolver(schemas.insert),
|
||||
defaultValues: {
|
||||
id: params.entity ? params.entity.id : crypto.randomUUID(),
|
||||
name: params.entity ? params.entity.name : "",
|
||||
layoutPosition: params.entity ? params.entity.layoutPosition : "col1"
|
||||
id: params.entity?.id || crypto.randomUUID(),
|
||||
name: params.entity?.name || "",
|
||||
layoutPosition: params.entity?.layoutPosition || "col1"
|
||||
}
|
||||
})
|
||||
let path = usePathname()
|
||||
|
||||
105
src/app/admin/music/_components/UploadMusicForm.tsx
Normal file
105
src/app/admin/music/_components/UploadMusicForm.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from "react";
|
||||
import { trpc } from "~/app/_trpc/Client";
|
||||
import { UploadDropzone } from "~/lib/uploadthing";
|
||||
import { Label } from "~/components/ui/label";
|
||||
import { FormScaffold } from "~/app/_components/Form/Components";
|
||||
import { useForm } from "react-hook-form";
|
||||
import { z } from "zod";
|
||||
import { zodResolver } from "@hookform/resolvers/zod";
|
||||
import type { RouterOutputs } from "~/server/routers/_app";
|
||||
import type { IterableElement } from "type-fest";
|
||||
import { Toaster } from "~/components/ui/sonner";
|
||||
import { toast } from "sonner";
|
||||
import { FormMutationContextProvider } from "~/app/_components/Form/Components/MutationProvider";
|
||||
import { TextInputFormField } from "~/app/_components/Form/Fields";
|
||||
import { createMusicInputSchema } from "~/lib/trpc/music/schemas";
|
||||
export default function CreateUpdateMusicForm(props: {
|
||||
entity?: IterableElement<RouterOutputs['music']['list']>,
|
||||
className?: string
|
||||
}) {
|
||||
const entity = props.entity;
|
||||
const [id, setId] = useState<string | undefined>(entity?.id)
|
||||
const utils = trpc.useUtils();
|
||||
const form = useForm<z.infer<typeof createMusicInputSchema>>({
|
||||
resolver: zodResolver(createMusicInputSchema),
|
||||
defaultValues: {
|
||||
id: entity?.id || crypto.randomUUID(),
|
||||
title: entity?.title || "",
|
||||
description: entity?.description || "",
|
||||
fileUrl: entity?.fileUrl,
|
||||
fileKey: entity?.fileKey,
|
||||
fileName: entity?.fileName,
|
||||
}
|
||||
})
|
||||
|
||||
const createMutation = trpc.music.create.useMutation({
|
||||
onSuccess: (values) => {
|
||||
setId(values?.id);
|
||||
utils.music.list.invalidate();
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(e.message)
|
||||
}
|
||||
})
|
||||
const updateMutation = trpc.music.update.useMutation({
|
||||
onSuccess: (_) => {
|
||||
utils.music.list.invalidate();
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(e.message)
|
||||
}
|
||||
})
|
||||
const deleteMutation = trpc.music.delete.useMutation({
|
||||
onSuccess: (_) => {
|
||||
utils.music.list.invalidate();
|
||||
},
|
||||
onError: (e) => {
|
||||
toast(e.message)
|
||||
}
|
||||
})
|
||||
|
||||
function onSubmit(values: z.infer<typeof createMusicInputSchema>) {
|
||||
id ?
|
||||
updateMutation.mutate(values) :
|
||||
createMutation.mutate(values)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Toaster />
|
||||
<FormMutationContextProvider value={{
|
||||
createMutation: createMutation,
|
||||
updateMutation: updateMutation,
|
||||
deleteMutation: deleteMutation
|
||||
}}>
|
||||
<FormScaffold form={form} onSubmit={onSubmit} title='Music' id={id} className={props.className}>
|
||||
<TextInputFormField control={form.control} name='title' label='Title'/>
|
||||
<TextInputFormField control={form.control} name='description' label='Description'/>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
<Label>Audio File</Label>
|
||||
<UploadDropzone
|
||||
endpoint="musicUploader"
|
||||
config={{mode: 'auto'}}
|
||||
onUploadError={(e) => {
|
||||
toast(e.message)
|
||||
}}
|
||||
onClientUploadComplete={(res) => {
|
||||
console.log(res)
|
||||
if (res[0]) {
|
||||
form.setValue('fileKey',res[0].serverData.fileKey);
|
||||
form.setValue('fileName',res[0].serverData.fileName);
|
||||
form.setValue('title',res[0].serverData.fileName);
|
||||
form.setValue('description',res[0].serverData.fileName);
|
||||
form.setValue('fileUrl',res[0].serverData.fileUrl);
|
||||
}
|
||||
console.log(form.getValues());
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</FormScaffold>
|
||||
</FormMutationContextProvider>
|
||||
</>
|
||||
);
|
||||
}
|
||||
26
src/app/admin/music/page.tsx
Normal file
26
src/app/admin/music/page.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
|
||||
import { trpc } from "~/app/_trpc/Client";
|
||||
import * as Card from "~/components/ui/card";
|
||||
import UploadMusicForm from "./_components/UploadMusicForm";
|
||||
import { CollapsibleForm } from "~/app/_components/Form/Components";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export default function AdminMusicPage() {
|
||||
const { data: tracks } = trpc.music.list.useQuery();
|
||||
useEffect(() => {console.log(tracks)}, [tracks])
|
||||
return (
|
||||
<div className="w-5/6 lg:w-1/2 flex flex-col gap-3">
|
||||
{tracks && <>
|
||||
{tracks.map((t) => (
|
||||
<Card.Card key={t.id}>
|
||||
<Card.CardContent>
|
||||
<UploadMusicForm entity={t} className="w-full"/>
|
||||
</Card.CardContent>
|
||||
</Card.Card>
|
||||
))}
|
||||
</>}
|
||||
<CollapsibleForm entityName="Track" form={UploadMusicForm}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user