Skip to content

Commit

Permalink
Adding profile upload page
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-jamming-reilly committed Feb 17, 2024
1 parent e71316b commit d1aed6a
Show file tree
Hide file tree
Showing 19 changed files with 277 additions and 84 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
"embla-carousel-react": "^8.0.0-rc22",
"nanoid": "^5.0.5",
"next": "^14.1.0",
"next-auth": "^4.22.1",
"p-retry": "^6.2.0",
Expand Down
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function RootLayout({
<title>parasocial</title>
<meta name="twitter:card" content={description} />
</head>
<body className="relative flex min-h-screen flex-grow flex-col bg-rose-900 text-zinc-100">
<body className="relative flex min-h-screen h-fit flex-1 flex-col bg-rose-900 text-zinc-100">
<AuthProvider>
<TRPCReactProvider cookies={cookies().toString()}>
<main className="flex flex-1 flex-col space-y-4 p-4">
Expand Down
2 changes: 1 addition & 1 deletion src/app/p/[name]/SearchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export async function SearchPage({ author, query }: SearchPageProps) {
const results = await api.video.search.query({ author, query });

return (
<div className="z-0 mx-auto flex h-full flex-1 flex-wrap justify-around gap-2 overflow-scroll pb-4 sm:min-w-[550px]">
<div className="z-0 mx-auto flex h-min-full flex-1 flex-wrap justify-around overflow-x-hidden gap-2 pb-4 sm:min-w-[550px]">
{results &&
results.map((result) => (
<SearchItem
Expand Down
2 changes: 1 addition & 1 deletion src/app/p/[name]/UploadList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function UploadItem({ doc, mobile }: UploadItemProps) {
alt={`Thumbnail for ${doc.title}`}
/>
<div className="flex-1 flex-col-reverse">
<p className="line-clamp-2 flex-1 text-justify tracking-wider text-white">
<p className="line-clamp-2 flex-1 tracking-wider text-white">
{doc.title}
</p>
<p className="text-xs text-neutral-400">
Expand Down
2 changes: 1 addition & 1 deletion src/app/p/[name]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default async function Page({ params, searchParams }: PageProps) {
initQuery={query}
placeholder={`find a moment from ${author}`}
></SearchBar>
<div className="flex h-[93vh] flex-row">
<div className="flex min-h-[93vh] flex-row">
{query ? (
<Suspense fallback={<DummyPage />}>
<SearchPage author={author} query={query} />
Expand Down
30 changes: 14 additions & 16 deletions src/app/profile/SearchQueries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function UploadItem({ doc, mobile }: UploadItemProps) {
className="text flex flex-row gap-2 border-4 border-black bg-black px-3 hover:underline"
>
<div className="flex-1 flex-col-reverse">
<p className="line-clamp-2 flex-1 text-justify tracking-wider text-white">
<p className="line-clamp-2 text-justify tracking-wider text-white">
{doc.query}
</p>
<p className="text-xs text-neutral-400">
Expand All @@ -46,21 +46,19 @@ interface UploadListProps {

export function SearchQueryList({ queries: queries }: UploadListProps) {
return (
<>
<div className="">
<div className="mb-3 px-3">
<h3 className="max-w-fit bg-black px-3 font-bold tracking-widest text-white">
previous queries
</h3>
</div>
<ScrollArea className="h-[50vh] w-[24rem] ">
<div className="flex flex-col gap-3 text-white">
{queries.map((search) => (
<UploadItem key={search.id} mobile={false} doc={search} />
))}
</div>
</ScrollArea>
<div className="">
<div className="mb-3 px-3">
<h3 className="max-w-fit bg-black px-3 font-bold tracking-widest text-white">
previous queries
</h3>
</div>
</>
<ScrollArea className="h-[50vh] w-[16] md:w-[20rem] ">
<div className="flex flex-col gap-3 text-white">
{queries.map((search) => (
<UploadItem key={search.id} mobile={false} doc={search} />
))}
</div>
</ScrollArea>
</div>
);
}
36 changes: 24 additions & 12 deletions src/app/profile/UploadForm.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { FormEvent } from "react";
import Image from "next/image";
import {
Form,
Expand All @@ -12,10 +11,9 @@ import {
FormLabel,
FormMessage,
} from "~/components/ui/form";
import { Button } from "~/components/ui/button";
import { Input } from "~/components/ui/input";
import { cn } from "~/lib/utils";
import useInput from "~/hooks/useInput";
import { useToast } from "~/components/ui/use-toast";
import { api } from "~/trpc/react";
import * as z from "zod";

Expand All @@ -39,23 +37,34 @@ export function UploadForm({ placeholder, className }: UploadFormProps) {
},
});

const { data, mutate, isLoading } = api.video.upload.useMutation({
const { toast } = useToast();

const { mutate, isLoading } = api.video.upload.useMutation({
onSuccess(data, variables, context) {
//
toast({
title: "success: you uploaded a video 🚀",
description: data.url,
});
},
onError(err) {
console.log("HERE", err);
toast({
title: "error",
description: err.message,
});
},
});

function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values);
mutate({ url: values.url });
}
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className={cn("mb-4 w-full max-w-sm justify-start", className)}
className={cn("mb-4 w-full justify-start", className)}
>
<div className="flex flex-1 flex-row gap-2 text-sm font-bold">
<div className="flex flex-1 flex-row gap-2 text-xs font-bold">
<Image
src="/icons/youtube.svg"
width="35"
Expand All @@ -71,7 +80,7 @@ export function UploadForm({ placeholder, className }: UploadFormProps) {
<FormLabel>Upload a youtube video</FormLabel>
<FormControl className="rounded-none border-0 border-b-2 border-black bg-transparent px-0 text-black focus-visible:ring-0">
<Input
placeholder="ex. https://www.youtube.com/watch?v=2dQ4-VNaG3s"
placeholder="ex. https://www.youtube.com/watch?v=dQw4w9WgXcQ"
{...field}
/>
</FormControl>
Expand All @@ -84,9 +93,12 @@ export function UploadForm({ placeholder, className }: UploadFormProps) {
/>
</div>
<div className="flex flex-row-reverse">
<Button className=" bg-black" type="submit">
{isLoading ? "..." : "Upload"}
</Button>
<button
className="relative text-xs tracking-wider flex max-w-[10rem] items-center border-4 border-black bg-black font-bold shadow-[8px_8px_0_0_#000] transition hover:shadow-none focus:outline-none focus:ring"
type="submit"
>
{isLoading ? "..." : "upload"}
</button>
</div>
</form>
</Form>
Expand Down
87 changes: 87 additions & 0 deletions src/app/profile/UploadList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"use client";
import Link from "next/link";
import Image from "next/image";
import { useState } from "react";

import { YoutubeVideo } from "~/server/video-query";
import type { VideoUpload } from "@prisma/client";
import { ScrollArea } from "~/components/ui/scroll-area";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "~/components/ui/accordion";
import Youtube from "~/components/Youtube";

function displayDate(dateString: string) {
const date = new Date(dateString);
return date.toLocaleDateString();
}

interface UploadItemProps {
mobile: boolean;
doc: VideoUpload;
}

function UploadItem({ doc, mobile }: UploadItemProps) {
return (
<Link
href={doc.url}
className="text flex flex-row gap-2 border-4 border-black bg-black px-3 hover:underline"
>
<div className="flex-1 flex-col-reverse">
<p className="line-clamp-2 flex-1 tracking-wider text-white">
{doc.url}
</p>
<p className="text-xs text-neutral-400">
{doc.create_date.toDateString()}
</p>
</div>
</Link>
);
}

interface UploadListProps {
documents: VideoUpload[];
}

export function UploadList({ documents }: UploadListProps) {
return (
<>
{/* Mobile View */}
<Accordion className="block sm:hidden w-full" type="single" collapsible>
<AccordionItem className="border-none" value="item-1">
<AccordionTrigger className="flex flex-1 flex-row bg-black px-3 py-1 font-bold tracking-widest text-white">
uploads
</AccordionTrigger>
<AccordionContent className="mt-2">
<ScrollArea className="max-h-[40vh] gap-3 ">
<div className="flex flex-col gap-3 text-white">
{documents.map((doc) => (
<UploadItem key={doc.url} mobile={true} doc={doc} />
))}
</div>
</ScrollArea>
</AccordionContent>
</AccordionItem>
</Accordion>

{/* Desktop View */}
<div className="hidden sm:block">
<div className="mb-3 px-3">
<h3 className="max-w-fit bg-black px-3 font-bold tracking-widest text-white">
uploads
</h3>
</div>
<ScrollArea className="h-[50vh] ">
<div className="flex flex-col gap-3 text-sm text-white lg:text-base">
{documents.map((doc) => (
<UploadItem key={doc.url} mobile={false} doc={doc} />
))}
</div>
</ScrollArea>
</div>
</>
);
}
44 changes: 30 additions & 14 deletions src/app/profile/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { SearchQuery } from "@prisma/client";
import { SearchQueryList } from "./SearchQueries";
import { ProfileImage } from "~/components/ProfileImage";
import { UploadForm } from "./UploadForm";
import { UploadList } from "./UploadList";

export default function ProfilePage() {
const { data, status } = useSession();
Expand All @@ -23,21 +24,36 @@ export default function ProfilePage() {

const { data: searchQueries } = api.user.searchHistory.useQuery();

const { data: uploads } = api.user.uploads.useQuery(undefined, {});

return (
<main className="flex min-h-screen flex-col items-center gap-4 pt-4">
<ProfileImage
height={170}
width={170}
label={data?.user.name!}
src={data?.user.image!}
/>

<Button className="text-black" variant={"link"} onClick={() => signOut()}>
Sign out
</Button>
<UploadForm placeholder="" />

{searchQueries && <SearchQueryList queries={searchQueries} />}
<main className="grid sm:grid-cols-2 gap-4 pt-4 max-w-6xl mx-auto">
<div className="flex flex-col gap-2 items-center">
<div className="relative">
<div className="-left-1/2 h-full absolute items-center flex justify-center my-auto">
<Button
className="text-black"
variant={"link"}
onClick={() => signOut()}
>
Sign out
</Button>
</div>

<ProfileImage
height={150}
width={150}
label={data?.user.name!}
src={data?.user.image!}
/>
</div>

<UploadForm placeholder="" />
<UploadList documents={uploads || []} />
</div>
<div className="flex flex-col items-center">
{searchQueries && <SearchQueryList queries={searchQueries} />}
</div>
</main>
);
}
24 changes: 24 additions & 0 deletions src/components/Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use client";
import { useSession } from "next-auth/react";
type BannerProps = {
messages: string[];
};

export function Banner({ messages }: BannerProps) {
const { data, status } = useSession();
if (data || status === "loading") return null;

return (
<div className="overflow-hidden whitespace-nowrap min-w-10 ">
<div className="text-black tracking-wider items-center text-sm flex flex-row ">
<div className="z-30 bg-inherit font-bold">[</div>
<div className=" animate-banner-scroll my-auto ">
{messages.map((message) => (
<div className="-z-10">{message}</div>
))}
</div>
<div className="z-30 bg-inherit overflow-hidden font-bold">]</div>
</div>
</div>
);
}
6 changes: 5 additions & 1 deletion src/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import Link from "next/link";
import SignInBtn from "~/components/UserButton";
import { Banner } from "./Banner";

export function Navbar() {
return (
<div className="flex w-full flex-row justify-between">
<div className="flex w-full flex-row justify-between items-center">
<Link href="/">
<h1 className="outline-text-3 text-2xl tracking-widest">parasocial</h1>
</Link>
<Banner
messages={["btw, you can upload up to 3 videos a day when you sign in"]}
/>
<SignInBtn />
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/ProfileImage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type ProfileImageProps = {

export function ProfileImage({ src, height, width, label }: ProfileImageProps) {
return (
<div className="relative">
<div className="relative h-fit w-fit">
<Image
src={src}
height={height}
Expand Down
Loading

0 comments on commit d1aed6a

Please sign in to comment.