Skip to content

Commit

Permalink
Merge branch 'main' into production
Browse files Browse the repository at this point in the history
  • Loading branch information
fahimmehraj committed Mar 2, 2024
2 parents c69b854 + 7f22959 commit 18ff187
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .env.development
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
BLOB_READ_WRITE_TOKEN="vercel_blob_rw_qvp4owlAyWnIY4PO_eWaDQ6ZN2tFbfsw2p6Fby355l6mAxd"
DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlfa2V5IjoiNTczM2JiODEtNGQwNS00Zjc4LTgyMTctMzEwMDgyOWM4MzRjIiwidGVuYW50X2lkIjoiZDA3N2I5OGJiOTQ2M2YxYWY0Y2NlYzAzZDQ3ZjhhMjJiNjQ0NzlkM2YxNTc4Nzk3MTBkZDExODU1NmVmN2YxYiIsImludGVybmFsX3NlY3JldCI6ImNiOTQ2MmUyLWYyOGQtNDg0OC1hMmJmLTEyODEyNDQ0NWExZSJ9.lvRegtdeT7CJzvYg_KA5V3zr147jstiU5feAZQEp1U4"
DATABASE_URL="mysql://be64bxj9rei05uiom8hw:pscale_pw_AkKRh9rEw2Jn9aBITBd7LBgiB0MLS8WoRwZsqUDthS8@aws.connect.psdb.cloud/atomhacks?sslaccept=strict&connection_limit=20"
DISCORD_ID="1208672085010812968"
DISCORD_SECRET="6hCBrsebOcIAIawK_RPHXA4mgetkx4ZD"
EMAIL_FROM="[email protected]"
Expand Down
2 changes: 1 addition & 1 deletion app/api/submission/edit/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from "@/lib/server";
import { NextResponse } from 'next/server';

const fields = ["name", "description", "tracks", "srcLink", "videoLink", "public", "icon", "media", "submitted", "public"] as const;
const fields = ["name", "description", "tracks", "srcLink", "videoLink", "public", "icon", "media", "submitted", "public", "librariesUsed"] as const;

export async function POST(req: Request) {
if (req.method != "POST") {
Expand Down
74 changes: 53 additions & 21 deletions app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { getServerSession } from "next-auth";
import { authOptions, getUser } from "@/lib/server";
import { CheckCircleIcon, ExclamationCircleIcon, LinkIcon } from "@heroicons/react/24/outline";
import { redirect } from "next/navigation";
import OAuthButton from "../components/buttons/OAuthButton";

export const dynamic = "force-dynamic";

Expand All @@ -18,42 +17,75 @@ export default async function Dashboard() {
}

if (!user.formInfo) {
console.log("User has not completed form, redirecting.")
console.log("User has not completed form, redirecting.");
redirect("/dashboard/form");
}

console.log(session.user)
console.log(session.user);
console.log(user.formInfo);
return (
<>
<div className="flex items-center justify-center mb-8">
<span className="py-6 border-b-4 border-green-500 font-morro text-7xl md:text-5xl">DASHBOARD</span>
<div className="mb-8 flex items-center justify-center">
<span className="font-morro border-b-4 border-green-500 py-6 text-7xl md:text-5xl">DASHBOARD</span>
</div>
<h1 className="p-4 text-xl text-center md:text-base">
Please use the top bar to create a team and submission.
<h1 className="p-4 text-center text-xl md:text-base">
{user.role === "ADMIN"
? "Welcome, admin! You can access all projects (even private) and edit them."
: "Please use the top bar to create a team and submission."}
</h1>
<div className="flex flex-col items-center justify-around gap-4">
<OAuthButton
provider="discord"
callbackUrl="/dashboard"
className={`flex w-2/5 flex-row items-center rounded-lg border-2 bg-transparent p-4 md:w-4/5 ${!user.accounts.find((account) => account.provider === "discord") ? "border-red-500" : "border-green-500"
}`}
<div
className={`flex w-2/5 flex-row items-center rounded-lg border-2 bg-transparent p-4 md:w-4/5 ${
user.teamId == null ? "border-red-500" : "border-green-500"
}`}
>
{" "}
<div className="object-contain w-10 h-10 md:h-5 md:w-5">
<div className="h-10 w-10 object-contain md:h-5 md:w-5">
{" "}
<LinkIcon />
</div>
<h1 className="mx-4 text-2xl text-left grow md:text-sm">Link Discord account</h1>
<div className="object-contain w-10 h-10 md:h-5 md:w-5">
<h1 className="mx-4 grow text-left text-2xl md:text-sm">Create a Team</h1>
<div className="h-10 w-10 object-contain md:h-5 md:w-5">
{" "}
{!user.accounts.find((account) => account.provider === "discord") ? (
<ExclamationCircleIcon />
) : (
<CheckCircleIcon />
)}
{user.teamId == null ? <ExclamationCircleIcon /> : <CheckCircleIcon />}
</div>
</OAuthButton>
</div>
</div>
<div className="mt-8 flex flex-col items-center justify-around gap-4">
<div
className={`flex w-2/5 flex-row items-center rounded-lg border-2 bg-transparent p-4 md:w-4/5 ${
!user.team?.submission ? "border-red-500" : "border-green-500"
}`}
>
{" "}
<div className="h-10 w-10 object-contain md:h-5 md:w-5">
{" "}
<LinkIcon />
</div>
<h1 className="mx-4 grow text-left text-2xl md:text-sm">Create a Submission</h1>
<div className="h-10 w-10 object-contain md:h-5 md:w-5">
{" "}
{!user.team?.submission ? <ExclamationCircleIcon /> : <CheckCircleIcon />}
</div>
</div>
</div>
<div className="mt-8 flex flex-col items-center justify-around gap-4">
<div
className={`flex w-2/5 flex-row items-center rounded-lg border-2 bg-transparent p-4 md:w-4/5 ${
!user.team?.submission?.public ? "border-red-500" : "border-green-500"
}`}
>
{" "}
<div className="h-10 w-10 object-contain md:h-5 md:w-5">
{" "}
<LinkIcon />
</div>
<h1 className="mx-4 grow text-left text-2xl md:text-sm">Mark your Project as Ready for Submission</h1>
<div className="h-10 w-10 object-contain md:h-5 md:w-5">
{" "}
{!user.team?.submission?.public ? <ExclamationCircleIcon /> : <CheckCircleIcon />}
</div>
</div>
</div>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,23 @@ type Props = {
}>;
};

function getYouTubeId(url: string) {
var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
var match = url.match(regExp);

if (match && match[2].length == 11) {
return match[2];
} else {
return "error";
}
}

export default function EditableSubmission({ submission }: Props) {
const router = useRouter();
const [name, setName] = useState(submission.name);
const [description, setDescription] = useState(submission.description);
const [description, setDescription] = useState(submission.description as string);
const [srcLink, setSrcLink] = useState<string>(submission.srcLink as string);
const [librariesUsed, setLibrariesUsed] = useState<string>(submission.librariesUsed as string);
const [videoLink, setVideoLink] = useState<string>(submission.videoLink as string);
const [submitting, setSubmitting] = useState(false);
const [currentImage, _setCurrentImage] = useState(0);
Expand All @@ -38,7 +50,6 @@ export default function EditableSubmission({ submission }: Props) {
const [newImages, setNewImages] = useState<File[]>([]);
const [selectedImages, setSelectedImages] = useState<string[]>(submission.media.map((sub) => sub.url));
// public is reserved keyword
const [published, setPublished] = useState(submission.public);
const [submitted, setSubmitted] = useState(submission.submitted);
const [error, setError] = useState(false);
const inputFileElement = useRef<null | HTMLInputElement>(null);
Expand Down Expand Up @@ -76,16 +87,16 @@ export default function EditableSubmission({ submission }: Props) {
setError(false);
console.log(selectedImages);
console.log(selectedIcon);
console.log(published);
console.log(submitted);

let body: any = {
name,
description,
srcLink,
librariesUsed,
videoLink,
submitted,
public: published,
public: submitted,
};

try {
Expand Down Expand Up @@ -147,28 +158,23 @@ export default function EditableSubmission({ submission }: Props) {

return (
<>
<div className="flex h-96 w-full items-center justify-center bg-ocean-100 py-8 sm:h-80">
<div className="flex w-full items-center justify-center bg-ocean-100 p-8">
<button>
<ArrowLongLeftIcon className="mr-8 h-8 w-8 text-white" onClick={() => setCurrentImage(currentImage - 1)} />
</button>
<div className="relative flex h-full w-2/6 min-w-[600px] flex-col items-center justify-center rounded-xl bg-neutral-900">
<div className="relative flex aspect-video w-2/6 items-center justify-center rounded-xl bg-neutral-900">
<>
<div className="absolute z-10 flex flex-col items-center justify-center space-y-2">
<button
className="rounded-2xl bg-ocean-500 px-4 py-2 transition duration-200 hover:bg-neutral-600"
onClick={() => inputFileElement.current!.click()}
>
Replace Images
Add Images
</button>
</div>
<>
{selectedImages && selectedImages[currentImage] && (
<Image
className="absolute rounded-xl object-cover"
src={selectedImages[currentImage]}
fill
alt="image"
></Image>
<Image className="rounded-xl object-cover" src={selectedImages[currentImage]} fill alt="image"></Image>
)}
</>
</>
Expand All @@ -191,7 +197,7 @@ export default function EditableSubmission({ submission }: Props) {
onChange={onSelectImages}
></input>
<label className="block text-base text-neutral-400" htmlFor="name">
Name * (Required)
Name* (A unique and innovative name can make the difference.)
</label>
<input
className="mb-4 block w-full rounded-md bg-ocean-500 p-2 text-5xl font-bold shadow-lg focus:border-teal-600 focus:outline-none focus:ring focus:ring-green-500"
Expand All @@ -203,7 +209,7 @@ export default function EditableSubmission({ submission }: Props) {
onInput={(e) => setName((e.target as HTMLInputElement).value)}
/>
<label className="block text-base text-neutral-400" htmlFor="description">
Description * (Required)
Description* (Describe your project to everyone.)
</label>
<textarea
className="text-m mb-4 mt-1 block w-full rounded-lg bg-ocean-500 p-2 shadow-lg focus:border-teal-600 focus:outline-none focus:ring focus:ring-green-500"
Expand All @@ -216,7 +222,7 @@ export default function EditableSubmission({ submission }: Props) {
onInput={(e) => setDescription((e.target as HTMLInputElement).value)}
/>
<label className="block text-base text-neutral-400" htmlFor="image">
Icon (Optional, the preview image shown in Submission Gallery. For best results, image should be a square)
Icon (The preview image shown in the Submission Gallery. For best results, the image should be a square.)
</label>
<input
type="file"
Expand All @@ -226,7 +232,7 @@ export default function EditableSubmission({ submission }: Props) {
onChange={onSelectIcon}
></input>
<label className="mt-4 block text-base text-neutral-400" htmlFor="name">
Source Code (Google Drive Link, GitHub repository, etc)
Project Link (A link to your project: Replit deployment, Scratch game, etc.)
</label>
<input
className="mb-4 block w-full rounded-md bg-ocean-500 p-2 text-lg shadow-lg focus:border-teal-600 focus:outline-none focus:ring focus:ring-green-500"
Expand All @@ -237,8 +243,20 @@ export default function EditableSubmission({ submission }: Props) {
value={srcLink}
onInput={(e) => setSrcLink((e.target as HTMLInputElement).value)}
/>
<label className="mt-4 block text-base text-neutral-400" htmlFor="name">
Libraries/APIs/Resources Used (Ex: W3Schools, Discord.py, React, OpenAI API, ChatGPT)
</label>
<input
className="mb-4 block w-full rounded-md bg-ocean-500 p-2 text-lg shadow-lg focus:border-teal-600 focus:outline-none focus:ring focus:ring-green-500"
type="text"
id="src"
name="src"
autoComplete="off"
value={librariesUsed}
onInput={(e) => setLibrariesUsed((e.target as HTMLInputElement).value)}
/>
<label className="block text-base text-neutral-400" htmlFor="name">
Video Link (YouTube)
Video Link (Must be a YouTube video.)
</label>
<input
className="mb-6 block w-full rounded-md bg-ocean-500 p-2 text-lg shadow-lg focus:border-teal-600 focus:outline-none focus:ring focus:ring-green-500"
Expand All @@ -250,28 +268,12 @@ export default function EditableSubmission({ submission }: Props) {
onInput={(e) => setVideoLink((e.target as HTMLInputElement).value)}
/>
{videoLink != "" && videoLink != null ? (
<iframe className="rounded-3xl" src={videoLink.replace("watch?v=", "embed/")} width={1000} height={500} />
<iframe
className="aspect-video w-full rounded-md"
src={"https://www.youtube.com/embed/" + getYouTubeId(videoLink)}
width="100%"
/>
) : null}
<Switch.Group>
<Switch.Label className="mb-1 block text-base text-neutral-400">Make Public</Switch.Label>
<Switch.Description className="mb-2 block text-base text-neutral-400">
This will make your project viewable in the submission gallery, but it is not required for your project to
be judged and receive a prize.
</Switch.Description>
<Switch
checked={published}
onChange={setPublished}
className={`${published ? "bg-green-500" : "bg-ocean-500"}
relative inline-flex h-[28.5px] w-[55.5px] shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75`}
>
<span className="sr-only">Use setting</span>
<span
aria-hidden="true"
className={`${published ? "translate-x-7" : "translate-x-0"}
pointer-events-none inline-block h-[26px] w-[26px] transform rounded-full bg-white shadow-lg ring-0 transition duration-200 ease-in-out`}
/>
</Switch>
</Switch.Group>
<Switch.Group>
<Switch.Label className="mb-1 mt-8 block text-base text-cyan-500">Ready for Submission </Switch.Label>
<Switch.Description className="mb-2 mt-2 text-base text-neutral-400">
Expand Down
7 changes: 4 additions & 3 deletions app/dashboard/submissions/[id]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,18 @@ export default async function SubmissionPage({ params }: { params: { id: string
notFound();
}

const isMine = submission.team.users.map((member) => member.id).some((id) => id == user.id) ?? false;
const isMine =
(submission.team.users.map((user) => user.id).some((id) => id == user?.id) ?? false) || user?.role === "ADMIN";

return (
<>
{!isMine ? (
<>
<h1>Access Denied Buddy</h1>
<h1>Access Denied (you thought you were onto something)</h1>
</>
) : (
<EditableSubmission submission={submission} />
)}
</>
);
}
}
Loading

0 comments on commit 18ff187

Please sign in to comment.