diff --git a/app/(content)/(gaming)/games/[gameid]/page.tsx b/app/(content)/(gaming)/games/[gameid]/page.tsx index 489cb4920249d8a0883380be24133474b91810bd..20d751b75a932a20817380767d01bd898f1dcb6b 100644 --- a/app/(content)/(gaming)/games/[gameid]/page.tsx +++ b/app/(content)/(gaming)/games/[gameid]/page.tsx @@ -1,5 +1,8 @@ +import { AspectRatio } from "@/components/ui/aspect-ratio"; +import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { getGame } from "@/lib/igdb"; +import { formatDate } from "@/lib/utils"; import { IGame } from "@/types/igdb-types"; import Image from "next/image"; @@ -7,15 +10,9 @@ import Image from "next/image"; export default async function GameDetail({ params }: { params: { gameid: string } }) { const data: IGame[] = await getGame(parseInt(params.gameid)) - // onvert unix timestamp to date in this format: Feb 25, 2022 - const date = new Date(data[0].first_release_date * 1000).toLocaleDateString('en-US', { - month: 'short', - day: 'numeric', - year: 'numeric' - }) + const date = formatDate(data[0].first_release_date * 1000) const companies = data[0].involved_companies.map((company) => { - // put a comma between each company if (company !== data[0].involved_companies[0]) { return `, ${company.company.name}` } @@ -25,15 +22,15 @@ export default async function GameDetail({ params }: { params: { gameid: string return ( <div className="main-content h-full"> <Card className="w-full h-full overflow-hidden"> - <div className="h-64 overflow-hidden -top-1/2"> - <div className="aspect-[889/500] relative block group"> + <div className="h-64 overflow-hidden"> + <AspectRatio ratio={889 / 500}> <Image src={data[0].screenshots[0].url} alt={data[0].name} fill priority className="object-center" /> - </div> + </AspectRatio> </div> <div className="p-6 md:p-12 ss:flex"> <div className="aspect-[264/374]"> @@ -46,23 +43,56 @@ export default async function GameDetail({ params }: { params: { gameid: string className="object-cover rounded-lg" /> </Card> </div> - <div className="ml-6 md:ml-12 grid items-start gap-2"> - <h1>{data[0].name}</h1> - <h1>released on {date} by {companies}</h1> - <h1>{data[0].summary}</h1> + <div className="ml-6 md:ml-12 space-y-3"> + <h1 className="text-2xl font-bold">{data[0].name}</h1> + <h1>released on{' '} + <span className="font-semibold">{date}</span> by{' '} + <span className="font-semibold">{companies}</span> + </h1> + <h1 className="pt-3">{data[0].summary}</h1> + + <div className="pt-6"> + <h1 className="mb-2">Genres</h1> + <div className="flex flex-wrap gap-2"> + {data[0].genres.map((genre, i) => { + return <Button key={i} variant="outline" size="lg" className="px-6 py-3">{genre.name}</Button> + })} + </div> + </div> + <div className="pt-6"> + <h1 className="mb-2">Platforms</h1> + <div className="flex flex-wrap gap-2"> + {data[0].platforms.map((platform, i) => { + return <Button key={i} variant="outline" size="lg" className="px-6 py-3">{platform.name}</Button> + })} + </div> + </div> </div> </div> <div className="px-6 md:px-12"> - <div className='mt-6 border-b border-gray-400 dark:border-gray-200 ' /> + {/* <div className="border-b border-gray-400 dark:border-gray-200" /> */} {/* comments */} </div> - </Card> - <div> - <Card className="side-content"> - a + </Card > + <div className="side-content"> + <Card className="p-6 grid items-start gap-2 bg-secondary"> + <h1>Screenshots</h1> + <div className="grid grid-cols-1 gap-4"> + {data[0].screenshots.slice(1, 4).map((screenshot, i) => { + return ( + <Card key={i} className="aspect-[264/374] relative block"> + <Image + src={screenshot.url} + alt={data[0].name} + fill + priority + className="object-cover rounded-lg" /> + </Card> + ) + })} + </div> </Card> </div> - - </div> + </div > ) } \ No newline at end of file diff --git a/app/(content)/(home)/home/page.tsx b/app/(content)/(home)/home/page.tsx index d3989d4aa18118717bdc7b4ccc0d621344753a06..02156d864cba762c6ae747408ac5199d205ab45c 100644 --- a/app/(content)/(home)/home/page.tsx +++ b/app/(content)/(home)/home/page.tsx @@ -1,13 +1,7 @@ import PostItem from "@/components/post-item"; -import PostMessageForm from "@/components/post-messages"; +import { PostMessageForm } from "@/components/post-messages"; +import { Card } from "@/components/ui/card"; import { db } from "@/lib/db"; -import { Prisma } from "@prisma/client"; - - -type messageType = any // Prisma.PostUncheckedCreateInput -type messageItemProps = { - msg: messageType; -}; export default async function HomePage() { let messages = null @@ -22,27 +16,27 @@ export default async function HomePage() { Like: true }, }) - } catch (error) { - console.log("the database is not running, try: 'npx prisma migrate dev --name init' if you want to use the database") + throw new Error("the database is not running, check your .env file") } return ( - <div> - <h1>Home WIP</h1> - <p>This will be where all Posts show up.</p> - <p>Needs a reload after posting!!</p> + // <div className="main-content px-3"> + <div className="relative md:gap-10 lg:grid lg:grid-cols-[1fr_240px] px-3"> <PostMessageForm /> - {messages ? - <> - {messages.map((msg) => ( - <PostItem msg={msg} key={msg.id} /> - ))} - </> - : - <p>no messages / no database</p>} + <Card className="w-full h-full overflow-hidden p-6 md:p-12"> + {messages ? messages.map((msg) => ( + <PostItem msg={msg} key={msg.id} /> + )) + : + <p>There are no messages currently</p>} + </Card> + + {/* <div className="side-content"> */} + <div className="hidden lg:block flex-col"> + a + </div> </div> ) -} - +} \ No newline at end of file diff --git a/app/(content)/(user)/[userid]/loading.tsx b/app/(content)/(user)/[userid]/loading.tsx new file mode 100644 index 0000000000000000000000000000000000000000..c9e709d65763f4f0b9464eba42b820b28815297c --- /dev/null +++ b/app/(content)/(user)/[userid]/loading.tsx @@ -0,0 +1,38 @@ +import { Card } from "@/components/ui/card" +import { Skeleton } from "@/components/ui/skeleton" + +// loading component, this renders when loading in /games happens +export default function Loading() { + return ( + <div className="main-content h-full"> + <Card className="w-full h-full overflow-hidden"> + <div className="h-64 overflow-hidden"> + <Skeleton className="bg-slate-600 dark:bg-slate-400" /> + </div> + <div className="p-6 md:p-12 ss:flex"> + <Skeleton className="h-52 w-52 -mt-36 rounded-full" /> + <div className="ml-6 md:ml-12 space-y-3"> + <Skeleton className="h-6 w-1/4 bg-gray-400 dark:bg-gray-200" /> + <Skeleton className="h-6 w-1/4 bg-sky-500" /> + </div> + </div> + <div className="px-6 md:px-12"> + {/* <div className="border-b border-gray-400 dark:border-gray-200" /> */} + {/* tweets */} + </div> + </Card > + <div className="side-content"> + <Card className="p-6 grid items-start gap-2 bg-secondary"> + <Skeleton className="h-6 w-1/4 bg-gray-400 dark:bg-gray-200" /> + <div className="grid grid-cols-1 gap-4"> + {Array.from({ length: 2 }, (_, i) => i + 1).map((i) => { + return ( + <Skeleton key={i} className="aspect-[264/374] bg-gray-300" /> + ) + })} + </div> + </Card> + </div> + </div > + ) +} \ No newline at end of file diff --git a/app/(content)/(user)/[userid]/page.tsx b/app/(content)/(user)/[userid]/page.tsx index 86ddc8ad3eadfa841f8e89e7d82f93ea50456d1a..d4b50066daf5a9f30224779a5ee4d38a42c9bbd4 100644 --- a/app/(content)/(user)/[userid]/page.tsx +++ b/app/(content)/(user)/[userid]/page.tsx @@ -1,40 +1,59 @@ -'use client' -import { useSession } from "next-auth/react"; +import { AspectRatio } from "@/components/ui/aspect-ratio" +import { Card } from "@/components/ui/card" +import { Skeleton } from "@/components/ui/skeleton" +import { UserAvatar } from "@/components/user-avatar" +import { getCurrentUser } from "@/lib/session" +import { redirect } from "next/navigation" +export default async function User({ params }: { params: { userid: string } }) { + const user = await getCurrentUser() -export default function User({ params }: { params: { userid: string } }) { - const { data: session } = useSession(); - return ( - <div className="mt-8 px-4"> - <div className="flex-shrink-0"> - <title>{`GameUnity User`}</title> - <div className="h-10 w-10 rounded-full bg-gray-300"></div> {/* Profile picture */} + if (user?.username !== params.userid) { + redirect('/') + } + + return ( + <div className="main-content h-full"> + <Card className="w-full h-full overflow-hidden"> + <div className="h-64 overflow-hidden"> + <AspectRatio ratio={889 / 500} className="bg-slate-600 dark:bg-slate-400"> + {/* profile banner */} + {/* <Image + src={ } + alt={ } + fill + priority + className="object-center" /> */} + </AspectRatio> </div> - <div className="flex flex-col"> - <p className="text-white text-2xl font-semibold"> - {session?.user.name} - </p> - <div - className=" - flex - flex-row - items-center - gap-2 - mt-4 - text-neutral-500 - "> + <div className="p-6 md:p-12 ss:flex"> + <UserAvatar + user={{ name: user.name || null, image: user.image || null }} + className="h-52 w-52 -mt-36" + /> + <div className="ml-6 md:ml-12 space-y-3"> + <h1 className="text-2xl font-bold">{user.name}</h1> + <h1 className="text-md text-sky-500">@{user.username}</h1> + {/* <h1 className="pt-3">{user.bio}</h1> */} </div> </div> - <div className="flex flex-row items-center mt-4 gap-6"> - <div className="flex flex-row items-center gap-1"> - <p className="text-neutral-500">Following</p> - </div> - <div className="flex flex-row items-center gap-1"> - <p className="text-white">{}</p> - <p className="text-neutral-500">Followers</p> - </div> + <div className="px-6 md:px-12"> + {/* <div className="border-b border-gray-400 dark:border-gray-200" /> */} + {/* tweets */} </div> + </Card > + <div className="side-content"> + <Card className="p-6 grid items-start gap-2 bg-secondary"> + <h1>Media</h1> + <div className="grid grid-cols-1 gap-4"> + {Array.from({ length: 2 }, (_, i) => i + 1).map((i) => { + return ( + <Skeleton key={i} className="aspect-[264/374] bg-gray-300" /> + ) + })} + </div> + </Card> </div> - - ) + </div > + ) } \ No newline at end of file diff --git a/app/api/messages/route.ts b/app/api/messages/route.ts index 6abf1de6cd7647c1e65f501faf0e5ec5fba2ab64..2e6107bbb06b51eb24a0e57d43e774801b542b67 100644 --- a/app/api/messages/route.ts +++ b/app/api/messages/route.ts @@ -1,64 +1,33 @@ -import { authOptions } from "@/lib/auth"; import { db } from "@/lib/db"; -import { Prisma } from "@prisma/client"; -import { getServerSession } from "next-auth/next"; +import { getCurrentUser } from "@/lib/session"; import { revalidatePath } from "next/cache"; import { NextRequest, NextResponse } from "next/server"; -type post = Prisma.PostUncheckedCreateInput - export async function POST(req: NextRequest) { - const session = await getServerSession(authOptions); + const user = await getCurrentUser(); - if (!session) { - return NextResponse.json({ status: 401 }); + if (!user) { + return NextResponse.json({ status: 401, message: 'Unauthorized' }); } - const userId = session.user.id - const data = await req.json() - - console.log("router data: " + data.content, "status:") + const userId = user.id; + const content = await req.json() + console.log(content); + console.log(userId); try { await db.post.create({ - /* data: data */ data: { - content: data.content, + content: content.gweet, userId: userId, - published: true } }) - console.log("created") const path = req.nextUrl.searchParams.get('path') || '/'; revalidatePath(path); return NextResponse.json({ status: 201, message: 'Message Created' }) } catch (error: any) { - console.log("fail" + error); - } - console.log("post") -} - -export async function GET(req: NextRequest, res: NextResponse) { - try { - const data = await req.json() - console.log("router data: " + data, "status:") - } catch (error) { - - } - - try { - const messages = await db.post.findMany({ - orderBy: { - createdAt: "desc" - } - }) - - return NextResponse.json({ status: 200, messages: messages }) - } catch (error) { - console.log("fail" + error); - // res.status(400) + return NextResponse.json({ status: 500, message: error.message }) } - console.log("get") } \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index 421584b8612589dd76b986cd3b0c7577f2f5fe0d..15bc36ae3f33022724b746b01fe763355507f7e2 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -24,12 +24,10 @@ export default function RootLayout({ <head /> <body className={inter.className}> <ThemeProvider attribute="class" defaultTheme="system" enableSystem> - <Suspense fallback={<SiteLoad />}> - <Providers> - {children} - <Toaster /> - </Providers> - </Suspense> + <Providers> + {children} + <Toaster /> + </Providers> </ThemeProvider> </body> </html> diff --git a/components/post-item.tsx b/components/post-item.tsx index c348a94568387e8bb1927e4f6ea92d101e2ee4c1..0588a4b03e64237e8d56114cf896487b69f4c4e0 100644 --- a/components/post-item.tsx +++ b/components/post-item.tsx @@ -1,12 +1,8 @@ +import { formatDate } from "@/lib/utils"; import CommentButton from "./comment-button"; import LikeButton from "./like-button"; -type messageType = any // Prisma.PostUncheckedCreateInput -type messageItemProps = { - msg: messageType; -}; - -export default function PostItem({ msg }: any) { +export default function PostItem({ msg }: { msg: any }) { if (!msg.id) { return <div></div>; } @@ -20,7 +16,7 @@ export default function PostItem({ msg }: any) { <div className="flex items-center"> <span className="font-bold mr-2">{msg.user.name}</span> <span className="text-gray-500 text-sm"> - {formatDate(new Date(msg.createdAt!))} + {formatDate(msg.createdAt)} </span> </div> <div className="text-gray-800">{msg.content}</div> @@ -36,12 +32,4 @@ export default function PostItem({ msg }: any) { </div> </div> ) -}; - -function formatDate(date: Date) { - return date.toLocaleDateString("en-US", { - day: "numeric", - month: "short", - year: "numeric" - }); -} \ No newline at end of file +}; \ No newline at end of file diff --git a/components/post-messages.tsx b/components/post-messages.tsx index 85ee1cfc6da452448e85a9cad33c073ab86f5d99..727aa06f6f19683d39a1a8e22669c1b46afa16ef 100644 --- a/components/post-messages.tsx +++ b/components/post-messages.tsx @@ -1,62 +1,77 @@ "use client" -import { Post, Prisma } from "@prisma/client"; -import { useRouter } from "next/navigation"; -import { startTransition, useEffect, useState } from "react"; +import { zodResolver } from "@hookform/resolvers/zod" +import { useForm } from "react-hook-form" +import * as z from "zod" -type messageType = Prisma.PostUncheckedCreateInput +import { Button } from "@/components/ui/button" +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form" -export default function PostMessageForm() { +import { Textarea } from "@/components/ui/textarea" +import { toast } from "@/components/ui/use-toast" - const [formData, setFormData] = useState<messageType>({ content: "" } as messageType); - const router = useRouter(); +const FormSchema = z.object({ + gweet: z + .string() + .min(1, { message: "Come on post something...", }) + .max(1000, { message: "Gweets cannot be more that 1000 characters.", }), +}) - async function postMessage(e: any) { - e.preventDefault() - console.log(formData) - const response = await fetch('http://localhost:3000/api/messages', { +export function PostMessageForm() { + const form = useForm<z.infer<typeof FormSchema>>({ + resolver: zodResolver(FormSchema), + }) + + async function onSubmit(data: z.infer<typeof FormSchema>) { + await fetch('/api/messages', { method: 'POST', - body: JSON.stringify(formData), + body: JSON.stringify(data), next: { tags: ['collection'] } }) - startTransition(() => { - // Refresh the current route and fetch new data from the server without - // losing client-side browser or React state. - router.refresh(); - }); - return await response.json() + toast({ + title: "Your gweet is being processed...", + description: ( + <pre className="mt-2 w-[340px] rounded-md bg-slate-600 p-4"> + <code className="text-white">{JSON.stringify(data, null, 2)}</code> + </pre> + ), + }) } - const characterCount = formData.content.length; - const isOverLimit = characterCount >= 1000; - - const handleInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { - const { value } = e.target; - setFormData({ ...formData, content: value }); - }; - return ( - <div> - <form onSubmit={postMessage}> - <textarea - placeholder="Write something..." - name="content" - value={formData.content} - onChange={handleInputChange} - className="w-full p-2 border border-gray-600 rounded-xl resize-none" - rows={5} - maxLength={1000} - ></textarea> - <div className="flex justify-end mt-2"> - <span className={`${isOverLimit ? "text-red-500" : "text-gray-500"} text-sm`}> - {characterCount}/{1000} - </span> - </div> - <button type="submit" className="mt-2 bg-gray-300 text-gray-800 px-4 py-2 rounded float-right"> - Post - </button> + <Form {...form}> + <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6"> + <FormField + control={form.control} + name="gweet" + render={({ field }) => ( + <FormItem> + <FormLabel>Gweet</FormLabel> + <FormControl> + <Textarea + placeholder="What's on your mind?" + className="resize-none" + {...field} + /> + </FormControl> + <FormDescription> + Your gweets will be public, and everyone can see them. + </FormDescription> + <FormMessage /> + </FormItem> + )} + /> + <Button type="submit">Submit</Button> </form> - </div> + </Form> ) } \ No newline at end of file diff --git a/components/ui/aspect-ratio.tsx b/components/ui/aspect-ratio.tsx new file mode 100644 index 0000000000000000000000000000000000000000..d6a5226f5e9cc09a2bd1ccbce465524e41f04345 --- /dev/null +++ b/components/ui/aspect-ratio.tsx @@ -0,0 +1,7 @@ +"use client" + +import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio" + +const AspectRatio = AspectRatioPrimitive.Root + +export { AspectRatio } diff --git a/components/ui/form.tsx b/components/ui/form.tsx new file mode 100644 index 0000000000000000000000000000000000000000..63b6a610ff63899910a10a61d89db2a078336648 --- /dev/null +++ b/components/ui/form.tsx @@ -0,0 +1,177 @@ +import * as LabelPrimitive from "@radix-ui/react-label" +import { Slot } from "@radix-ui/react-slot" +import * as React from "react" +import { + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext, +} from "react-hook-form" + +import { Label } from "@/components/ui/label" +import { cn } from "@/lib/utils" + +const Form = FormProvider + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> +> = { + name: TName +} + +const FormFieldContext = React.createContext<FormFieldContextValue>( + {} as FormFieldContextValue +) + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> +>({ + ...props +}: ControllerProps<TFieldValues, TName>) => { + return ( + <FormFieldContext.Provider value={{ name: props.name }}> + <Controller {...props} /> + </FormFieldContext.Provider> + ) +} + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within <FormField>") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +} + +type FormItemContextValue = { + id: string +} + +const FormItemContext = React.createContext<FormItemContextValue>( + {} as FormItemContextValue +) + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes<HTMLDivElement> +>(({ className, ...props }, ref) => { + const id = React.useId() + + return ( + <FormItemContext.Provider value={{ id }}> + <div ref={ref} className={cn("space-y-2", className)} {...props} /> + </FormItemContext.Provider> + ) +}) +FormItem.displayName = "FormItem" + +const FormLabel = React.forwardRef< + React.ElementRef<typeof LabelPrimitive.Root>, + React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField() + + return ( + <Label + ref={ref} + className={cn(error && "text-destructive", className)} + htmlFor={formItemId} + {...props} + /> + ) +}) +FormLabel.displayName = "FormLabel" + +const FormControl = React.forwardRef< + React.ElementRef<typeof Slot>, + React.ComponentPropsWithoutRef<typeof Slot> +>(({ ...props }, ref) => { + const { error, formItemId, formDescriptionId, formMessageId } = useFormField() + + return ( + <Slot + ref={ref} + id={formItemId} + aria-describedby={ + !error + ? `${formDescriptionId}` + : `${formDescriptionId} ${formMessageId}` + } + aria-invalid={!!error} + {...props} + /> + ) +}) +FormControl.displayName = "FormControl" + +const FormDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes<HTMLParagraphElement> +>(({ className, ...props }, ref) => { + const { formDescriptionId } = useFormField() + + return ( + <p + ref={ref} + id={formDescriptionId} + className={cn("text-sm text-muted-foreground", className)} + {...props} + /> + ) +}) +FormDescription.displayName = "FormDescription" + +const FormMessage = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes<HTMLParagraphElement> +>(({ className, children, ...props }, ref) => { + const { error, formMessageId } = useFormField() + const body = error ? String(error?.message) : children + + if (!body) { + return null + } + + return ( + <p + ref={ref} + id={formMessageId} + className={cn("text-sm font-medium text-destructive", className)} + {...props} + > + {body} + </p> + ) +}) +FormMessage.displayName = "FormMessage" + +export { + useFormField, + Form, + FormItem, + FormLabel, + FormControl, + FormDescription, + FormMessage, + FormField, +} + diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4c5d6b5d3828cad6d423fb0140081ee0454ab7dc --- /dev/null +++ b/components/ui/textarea.tsx @@ -0,0 +1,24 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +export interface TextareaProps + extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {} + +const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>( + ({ className, ...props }, ref) => { + return ( + <textarea + className={cn( + "flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", + className + )} + ref={ref} + {...props} + /> + ) + } +) +Textarea.displayName = "Textarea" + +export { Textarea } diff --git a/components/user-avatar.tsx b/components/user-avatar.tsx index c627d497b5e18a469c8478332ccc1ddf3d7e0f81..c81c4c396de1664395d776e179c5fa37b0e1805b 100644 --- a/components/user-avatar.tsx +++ b/components/user-avatar.tsx @@ -16,7 +16,7 @@ export function UserAvatar({ user, ...props }: UserAvatarProps) { ) : ( <AvatarFallback> <span className="sr-only">{user.name}</span> - <Icons.user className="h-4 w-4" /> + <Icons.user className="h-3/5 w-3/5" /> </AvatarFallback> )} </Avatar> diff --git a/lib/config/dashboard.ts b/lib/config/dashboard.ts index 45cdb566792a88b218dffd61dc431d4dd6b3b40f..aaf550cb90b76e73ead26f91206d831dee3894a3 100644 --- a/lib/config/dashboard.ts +++ b/lib/config/dashboard.ts @@ -12,35 +12,35 @@ export const dashboardConfig: DashboardConfig = { href: "/games", icon: "gamepad2", }, - { - title: "Communities", - href: "/communities", - icon: "messagecircle", - }, - { - title: "Notifications", - href: "/notifications", - icon: "bellring", - }, - { - title: "Followers", - href: "/followers", - icon: "users", - }, + // { + // title: "Communities", + // href: "/communities", + // icon: "messagecircle", + // }, + // { + // title: "Notifications", + // href: "/notifications", + // icon: "bellring", + // }, + // { + // title: "Followers", + // href: "/followers", + // icon: "users", + // }, { title: "My Profile", href: "", icon: "user", }, - { - title: "Settings", - href: "/settings", - icon: "settings", - }, - { - title: "Help", - href: "/help", - icon: "help", - }, + // { + // title: "Settings", + // href: "/settings", + // icon: "settings", + // }, + // { + // title: "Help", + // href: "/help", + // icon: "help", + // }, ], } \ No newline at end of file diff --git a/lib/igdb.ts b/lib/igdb.ts index daa3d78b90c2b1686d5a1e6c10dba3804d225cbc..a3f26bf32d53791fe2751bf12773973b19714016 100644 --- a/lib/igdb.ts +++ b/lib/igdb.ts @@ -78,8 +78,8 @@ export async function getGame(id: number): Promise<IGame[]> { 'Authorization': `Bearer ${auth.access_token}` }, body: - `fields *, cover.image_id, screenshots.image_id, involved_companies.company.name; - where total_rating_count > 3 + `fields *, cover.image_id, screenshots.image_id, involved_companies.company.name, genres.name, platforms.name; + limit 1; where total_rating_count > 3 & cover != null & total_rating != null & rating != null & age_ratings != null & id = ${id};` }) diff --git a/lib/utils.ts b/lib/utils.ts index 3d7f8f667d0b0d0af854d15f1d695ec39f872763..a4563b1d39ecf754f6556c4d55a8ab1cb5cd0c74 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -16,4 +16,13 @@ export function getImageURL(hashId: string, size: string): string { // calculates the offset for the query export function calculateOffset(page: number, limit: number): number { return (page - 1) * limit +} + +export function formatDate(data: number) { + const date = new Date(data) + return date.toLocaleDateString('en-US', { + month: 'short', + day: 'numeric', + year: 'numeric' + }) } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 001892b66f10fbd42c7eaf42112fb808b8855921..4c363f412d49ba27721a1e350b0c2c5ce2a1f7d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@auth/prisma-adapter": "^1.0.0", "@hookform/resolvers": "^3.1.0", "@prisma/client": "^4.15.0", + "@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-avatar": "^1.0.3", "@radix-ui/react-dropdown-menu": "^2.0.5", "@radix-ui/react-label": "^2.0.2", @@ -594,6 +595,29 @@ } } }, + "node_modules/@radix-ui/react-aspect-ratio": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-aspect-ratio/-/react-aspect-ratio-1.0.3.tgz", + "integrity": "sha512-fXR5kbMan9oQqMuacfzlGG/SQMcmMlZ4wrvpckv8SgUulD0MMpspxJrxg/Gp/ISV3JfV1AeSWTYK9GvxA4ySwA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-avatar": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.0.3.tgz", diff --git a/package.json b/package.json index ef91fe612a04aeae7a0bb9cdd7e79cb4098cbd5b..ef93b2320bb4e31b6054c51b24610d6eb37b85d4 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "@auth/prisma-adapter": "^1.0.0", "@hookform/resolvers": "^3.1.0", "@prisma/client": "^4.15.0", + "@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-avatar": "^1.0.3", "@radix-ui/react-dropdown-menu": "^2.0.5", "@radix-ui/react-label": "^2.0.2", diff --git a/types/igdb-types.d.ts b/types/igdb-types.d.ts index c18bc051d3f376fbc97c5a8034b74818d99c6d87..9f2d9dbf114872154dcb48eb97128579f79605db 100644 --- a/types/igdb-types.d.ts +++ b/types/igdb-types.d.ts @@ -28,7 +28,7 @@ export interface IGame { game_engines: number[]; game_localizations: number[]; game_modes: number[]; - genres: number[]; + genres: IGenre[]; hypes: number; involved_companies: IInvolvedCompany[]; keywords: number[]; @@ -36,7 +36,7 @@ export interface IGame { multiplayer_modes: number[]; name: string; parent_game: string; - platforms: number[]; + platforms: IPlatform[]; player_perspectives: number[]; ports: number[]; rating: number; diff --git a/types/prisma-item.d.ts b/types/prisma-item.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..e281755f96d52a02d66ee99d7b1267165d33f7cd --- /dev/null +++ b/types/prisma-item.d.ts @@ -0,0 +1,9 @@ +import { Comment, Like, Post, User } from "@prisma/client"; + +export interface IPost { + user: Post & { + user: User; + Comment: Comment[]; + Like: Like[]; + } +} \ No newline at end of file