mirror of
https://github.com/Ategon/Jamjar.git
synced 2025-02-12 06:16:21 +00:00
Create new site design
This commit is contained in:
parent
e908237d84
commit
a3870224fa
29 changed files with 718 additions and 616 deletions
public/images
src
app
components
announcements
footer
jam-header
link-components
navbar
MobileNavbar.tsxMobileNavbarUser.tsxNavbarButtonAction.tsxNavbarButtonLink.tsxNavbarIconLink.tsxNavbarLink.tsxNavbarSearchbar.tsxPCNavbar.tsxPCNavbarUser.tsxindex.tsx
posts
user
BIN
public/images/d2jam.png
Normal file
BIN
public/images/d2jam.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 25 KiB |
3
src/app/about/page.tsx
Normal file
3
src/app/about/page.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function AboutPage() {
|
||||||
|
return <p>About page coming soon</p>;
|
||||||
|
}
|
3
src/app/games/page.tsx
Normal file
3
src/app/games/page.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export default function GamesPage() {
|
||||||
|
return <p>Games page coming soon</p>;
|
||||||
|
}
|
|
@ -4,6 +4,8 @@ import "./globals.css";
|
||||||
import Navbar from "../components/navbar";
|
import Navbar from "../components/navbar";
|
||||||
import Providers from "./providers";
|
import Providers from "./providers";
|
||||||
import { ToastContainer } from "react-toastify";
|
import { ToastContainer } from "react-toastify";
|
||||||
|
import { Spacer } from "@nextui-org/react";
|
||||||
|
import Footer from "@/components/footer";
|
||||||
|
|
||||||
const inter = Inter({ subsets: ["latin"] });
|
const inter = Inter({ subsets: ["latin"] });
|
||||||
|
|
||||||
|
@ -22,9 +24,13 @@ export default function RootLayout({
|
||||||
<body className={inter.className}>
|
<body className={inter.className}>
|
||||||
<Providers>
|
<Providers>
|
||||||
<div className="dark">
|
<div className="dark">
|
||||||
<div className="bg-zinc-100 dark:bg-zinc-950 min-h-screen">
|
<div className="bg-gradient-to-br from-[#181818] to-[#222] min-h-screen flex flex-col">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<div className="max-w-8xl mx-auto">{children}</div>
|
<Spacer y={5} />
|
||||||
|
<div className="max-w-8xl mx-auto flex-grow w-full">
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
<Footer />
|
||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,6 +48,7 @@ export default function UserPage() {
|
||||||
body: JSON.stringify({ username: username, password: password }),
|
body: JSON.stringify({ username: username, password: password }),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
|
credentials: "include",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -57,7 +58,15 @@ export default function UserPage() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { token, user } = await response.json();
|
const { user } = await response.json();
|
||||||
|
const token = response.headers.get("Authorization");
|
||||||
|
console.log(response.headers);
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
toast.error("Failed to retreive access token");
|
||||||
|
setPassword("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
document.cookie = `token=${token}`;
|
document.cookie = `token=${token}`;
|
||||||
document.cookie = `user=${user.slug}`;
|
document.cookie = `user=${user.slug}`;
|
||||||
|
|
|
@ -1,46 +1,16 @@
|
||||||
import { Image } from "@nextui-org/image";
|
|
||||||
import { Button } from "@nextui-org/button";
|
|
||||||
import { SiDiscord } from "@icons-pack/react-simple-icons";
|
|
||||||
import { Link } from "@nextui-org/react";
|
|
||||||
import Posts from "@/components/posts";
|
import Posts from "@/components/posts";
|
||||||
import Timers from "@/components/timers";
|
import Timers from "@/components/timers";
|
||||||
|
import JamHeader from "@/components/jam-header";
|
||||||
|
|
||||||
export default async function Home() {
|
export default async function Home() {
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="flex justify-between flex-wrap">
|
||||||
<div className="fixed left-0 top-0 w-full h-full z-0">
|
<div className="md:w-2/3">
|
||||||
<Image
|
<JamHeader />
|
||||||
src="/images/bg.jpg"
|
<Posts />
|
||||||
alt="Home background"
|
|
||||||
className="object-cover w-full h-full"
|
|
||||||
radius="none"
|
|
||||||
loading="eager"
|
|
||||||
removeWrapper
|
|
||||||
/>
|
|
||||||
<div className="absolute left-0 top-0 w-full h-full bg-gradient-to-r from-black/50 to-transparent z-10" />
|
|
||||||
</div>
|
</div>
|
||||||
<div className="z-10 relative flex w-full flex-wrap">
|
<div>
|
||||||
<div>
|
<Timers />
|
||||||
<div className="flex flex-col gap-4 py-4 sm:py-8 md:py-12 pl-16">
|
|
||||||
<h1 className="text-3xl sm:text-4xl md:text-5xl">Dare2Jam</h1>
|
|
||||||
<p className="text-lg sm:text-xl">April 4th - 7th</p>
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<Link href="https://discord.gg/rfmKzM6ASw" target="_blank">
|
|
||||||
<Button
|
|
||||||
variant="bordered"
|
|
||||||
className="border-white/50 text-white"
|
|
||||||
startContent={<SiDiscord />}
|
|
||||||
>
|
|
||||||
Join the Discord
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Posts />
|
|
||||||
</div>
|
|
||||||
<div className="w-1/3 flex justify-end py-4 sm:py-8 md:py-12 flex-grow">
|
|
||||||
<Timers />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -28,6 +28,7 @@ export default function UserPage() {
|
||||||
: `http://localhost:3005/api/v1/self?username=${getCookie("user")}`,
|
: `http://localhost:3005/api/v1/self?username=${getCookie("user")}`,
|
||||||
{
|
{
|
||||||
headers: { authorization: `Bearer ${getCookie("token")}` },
|
headers: { authorization: `Bearer ${getCookie("token")}` },
|
||||||
|
credentials: "include",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Button, Form, Input } from "@nextui-org/react";
|
import { Button, Form, Input } from "@nextui-org/react";
|
||||||
import { redirect } from "next/navigation";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { toast } from "react-toastify";
|
|
||||||
|
|
||||||
export default function UserPage() {
|
export default function UserPage() {
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
|
@ -83,13 +81,13 @@ export default function UserPage() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { token, user } = await response.json();
|
// const { token, user } = await response.json();
|
||||||
document.cookie = `token=${token}`;
|
// document.cookie = `token=${token}`;
|
||||||
document.cookie = `user=${user.slug}`;
|
// document.cookie = `user=${user.slug}`;
|
||||||
|
|
||||||
toast.success("Successfully signed up");
|
// toast.success("Successfully signed up");
|
||||||
|
|
||||||
redirect("/");
|
// redirect("/");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
|
|
|
@ -1,9 +1,34 @@
|
||||||
import User from "../../../components/user";
|
"use client";
|
||||||
|
|
||||||
|
import { UserType } from "@/types/UserType";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
export default function UserPage() {
|
export default function UserPage() {
|
||||||
|
const [user, setUser] = useState<UserType>();
|
||||||
|
const { slug } = useParams();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchUser = async () => {
|
||||||
|
const response = await fetch(
|
||||||
|
process.env.NEXT_PUBLIC_MODE === "PROD"
|
||||||
|
? `https://d2jam.com/api/v1/user?slug=${slug}`
|
||||||
|
: `http://localhost:3005/api/v1/user?slug=${slug}`
|
||||||
|
);
|
||||||
|
setUser(await response.json());
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchUser();
|
||||||
|
}, [slug]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<User />
|
{user && (
|
||||||
|
<div>
|
||||||
|
<p>{user.name}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
return <div></div>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
export default function Announcements() {
|
|
||||||
return (
|
|
||||||
<div></div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
20
src/components/footer/index.tsx
Normal file
20
src/components/footer/index.tsx
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import IconLink from "../link-components/IconLink";
|
||||||
|
import { SiDiscord, SiForgejo, SiGithub } from "@icons-pack/react-simple-icons";
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
return (
|
||||||
|
<div className="p-8 bg-[#222] mt-8 border-t-2 border-white/15">
|
||||||
|
<div className="flex justify-between">
|
||||||
|
<div></div>
|
||||||
|
<div className="flex gap-3">
|
||||||
|
<IconLink icon={<SiGithub />} href="https://github.com/Dare2Jam" />
|
||||||
|
<IconLink
|
||||||
|
icon={<SiForgejo />}
|
||||||
|
href="https://git.edikoyo.com/Ategon/Jamjar"
|
||||||
|
/>
|
||||||
|
<IconLink icon={<SiDiscord />} href="https://discord.d2jam.com" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
15
src/components/jam-header/index.tsx
Normal file
15
src/components/jam-header/index.tsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { Calendar } from "lucide-react";
|
||||||
|
|
||||||
|
export default function JamHeader() {
|
||||||
|
return (
|
||||||
|
<div className="bg-[#124a88] flex rounded-2xl overflow-hidden">
|
||||||
|
<div className="bg-[#1892b3] p-4 px-6 flex items-center gap-2 font-bold">
|
||||||
|
<Calendar />
|
||||||
|
<p>Dare2Jam 1</p>
|
||||||
|
</div>
|
||||||
|
<div className="p-4 px-6 font-bold">
|
||||||
|
<p>April 4th - 7th</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
25
src/components/link-components/ButtonAction.tsx
Normal file
25
src/components/link-components/ButtonAction.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { Button } from "@nextui-org/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface ButtonActionProps {
|
||||||
|
icon?: ReactNode;
|
||||||
|
onPress: () => void;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ButtonAction({
|
||||||
|
icon,
|
||||||
|
onPress,
|
||||||
|
name,
|
||||||
|
}: ButtonActionProps) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
endContent={icon}
|
||||||
|
className="text-white border-white/50 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
||||||
|
variant="bordered"
|
||||||
|
onPress={onPress}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
25
src/components/link-components/ButtonLink.tsx
Normal file
25
src/components/link-components/ButtonLink.tsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import { Button, Link } from "@nextui-org/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface ButtonLinkProps {
|
||||||
|
icon?: ReactNode;
|
||||||
|
href: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ButtonLink({ icon, href, name }: ButtonLinkProps) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-110 ease-in-out"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
endContent={icon}
|
||||||
|
className="text-white border-white/50 transition-all transform duration-500 ease-in-out"
|
||||||
|
variant="bordered"
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
18
src/components/link-components/IconLink.tsx
Normal file
18
src/components/link-components/IconLink.tsx
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { Link } from "@nextui-org/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
|
||||||
|
interface IconLinkProps {
|
||||||
|
icon: ReactNode;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function IconLink({ icon, href }: IconLinkProps) {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
href={href}
|
||||||
|
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125"
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
}
|
17
src/components/link-components/Link.tsx
Normal file
17
src/components/link-components/Link.tsx
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
import { Link as BaseLink } from "@nextui-org/react";
|
||||||
|
|
||||||
|
interface LinkProps {
|
||||||
|
name: string;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Link({ name, href }: LinkProps) {
|
||||||
|
return (
|
||||||
|
<BaseLink
|
||||||
|
href={href}
|
||||||
|
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-110"
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</BaseLink>
|
||||||
|
);
|
||||||
|
}
|
111
src/components/navbar/MobileNavbar.tsx
Normal file
111
src/components/navbar/MobileNavbar.tsx
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Image,
|
||||||
|
Link,
|
||||||
|
NavbarBrand,
|
||||||
|
Navbar as NavbarBase,
|
||||||
|
NavbarContent,
|
||||||
|
} from "@nextui-org/react";
|
||||||
|
import NavbarButtonLink from "./NavbarButtonLink";
|
||||||
|
import { LogInIcon, NotebookPen } from "lucide-react";
|
||||||
|
import NextImage from "next/image";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import { getCookie, hasCookie } from "@/helpers/cookie";
|
||||||
|
import { getCurrentJam } from "@/helpers/jam";
|
||||||
|
import { JamType } from "@/types/JamType";
|
||||||
|
import { UserType } from "@/types/UserType";
|
||||||
|
import MobileNavbarUser from "./MobileNavbarUser";
|
||||||
|
|
||||||
|
export default function MobileNavbar() {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const [jam, setJam] = useState<JamType | null>();
|
||||||
|
const [isInJam, setIsInJam] = useState<boolean>();
|
||||||
|
const [user, setUser] = useState<UserType>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadUser();
|
||||||
|
async function loadUser() {
|
||||||
|
const currentJam = await getCurrentJam();
|
||||||
|
setJam(currentJam);
|
||||||
|
|
||||||
|
if (!hasCookie("token")) {
|
||||||
|
setUser(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
process.env.NEXT_PUBLIC_MODE === "PROD"
|
||||||
|
? `https://d2jam.com/api/v1/self?username=${getCookie("user")}`
|
||||||
|
: `http://localhost:3005/api/v1/self?username=${getCookie("user")}`,
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${getCookie("token")}` },
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const user = await response.json();
|
||||||
|
|
||||||
|
if (
|
||||||
|
currentJam &&
|
||||||
|
user.jams.filter((jam: JamType) => jam.id == currentJam.id).length > 0
|
||||||
|
) {
|
||||||
|
setIsInJam(true);
|
||||||
|
} else {
|
||||||
|
setIsInJam(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.status == 200) {
|
||||||
|
setUser(user);
|
||||||
|
} else {
|
||||||
|
setUser(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavbarBase maxWidth="2xl" className="bg-[#222] p-1" isBordered height={80}>
|
||||||
|
{/* Left side navbar items */}
|
||||||
|
<NavbarContent justify="start" className="gap-10">
|
||||||
|
<NavbarBrand className="flex-grow-0">
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="duration-500 ease-in-out transition-all transform hover:scale-110"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
as={NextImage}
|
||||||
|
src="/images/d2jam.png"
|
||||||
|
className="min-w-[70px]"
|
||||||
|
alt="Dare2Jam logo"
|
||||||
|
width={70}
|
||||||
|
height={59.7}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</NavbarBrand>
|
||||||
|
</NavbarContent>
|
||||||
|
|
||||||
|
{/* Right side navbar items */}
|
||||||
|
<NavbarContent justify="end" className="gap-4">
|
||||||
|
{!user && (
|
||||||
|
<NavbarButtonLink icon={<LogInIcon />} name="Log In" href="/login" />
|
||||||
|
)}
|
||||||
|
{!user && (
|
||||||
|
<NavbarButtonLink
|
||||||
|
icon={<NotebookPen />}
|
||||||
|
name="Sign Up"
|
||||||
|
href="/signup"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{user && (
|
||||||
|
<MobileNavbarUser
|
||||||
|
user={user}
|
||||||
|
isInJam={isInJam}
|
||||||
|
setIsInJam={setIsInJam}
|
||||||
|
jam={jam}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</NavbarContent>
|
||||||
|
</NavbarBase>
|
||||||
|
);
|
||||||
|
}
|
102
src/components/navbar/MobileNavbarUser.tsx
Normal file
102
src/components/navbar/MobileNavbarUser.tsx
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Dropdown,
|
||||||
|
DropdownItem,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownTrigger,
|
||||||
|
NavbarItem,
|
||||||
|
} from "@nextui-org/react";
|
||||||
|
import { UserType } from "@/types/UserType";
|
||||||
|
import { getCurrentJam, joinJam } from "@/helpers/jam";
|
||||||
|
import { JamType } from "@/types/JamType";
|
||||||
|
import { Dispatch, SetStateAction } from "react";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
interface NavbarUserProps {
|
||||||
|
user: UserType;
|
||||||
|
jam?: JamType | null;
|
||||||
|
setIsInJam: Dispatch<SetStateAction<boolean | undefined>>;
|
||||||
|
isInJam?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function MobileNavbarUser({
|
||||||
|
user,
|
||||||
|
jam,
|
||||||
|
setIsInJam,
|
||||||
|
isInJam,
|
||||||
|
}: NavbarUserProps) {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<Dropdown>
|
||||||
|
<DropdownTrigger>
|
||||||
|
<Avatar src={user.profilePicture} className="cursor-pointer" />
|
||||||
|
</DropdownTrigger>
|
||||||
|
<DropdownMenu>
|
||||||
|
{jam && isInJam ? (
|
||||||
|
<DropdownItem
|
||||||
|
key="create-game"
|
||||||
|
href="/create-game"
|
||||||
|
className="text-black"
|
||||||
|
>
|
||||||
|
Create Game
|
||||||
|
</DropdownItem>
|
||||||
|
) : null}
|
||||||
|
{jam && !isInJam ? (
|
||||||
|
<DropdownItem
|
||||||
|
key="join-event"
|
||||||
|
className="text-black"
|
||||||
|
onPress={async () => {
|
||||||
|
try {
|
||||||
|
const currentJam = await getCurrentJam();
|
||||||
|
|
||||||
|
if (!currentJam) {
|
||||||
|
toast.error("There is no jam to join");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (await joinJam(currentJam.id)) {
|
||||||
|
setIsInJam(true);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during join process:", error);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Join Event
|
||||||
|
</DropdownItem>
|
||||||
|
) : null}
|
||||||
|
<DropdownItem
|
||||||
|
key="create-post"
|
||||||
|
href="/create-post"
|
||||||
|
className="text-black"
|
||||||
|
>
|
||||||
|
Create Post
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
key="profile"
|
||||||
|
className="text-black"
|
||||||
|
href={`/u/${user.slug}`}
|
||||||
|
>
|
||||||
|
Profile
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
showDivider
|
||||||
|
key="settings"
|
||||||
|
className="text-black"
|
||||||
|
href="/settings"
|
||||||
|
>
|
||||||
|
Settings
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
key="logout"
|
||||||
|
color="danger"
|
||||||
|
className="text-danger"
|
||||||
|
href="/logout"
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
21
src/components/navbar/NavbarButtonAction.tsx
Normal file
21
src/components/navbar/NavbarButtonAction.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { NavbarItem } from "@nextui-org/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import ButtonAction from "../link-components/ButtonAction";
|
||||||
|
|
||||||
|
interface NavbarButtonActionProps {
|
||||||
|
icon?: ReactNode;
|
||||||
|
onPress: () => void;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NavbarButtonAction({
|
||||||
|
icon,
|
||||||
|
onPress,
|
||||||
|
name,
|
||||||
|
}: NavbarButtonActionProps) {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<ButtonAction icon={icon} onPress={onPress} name={name} />
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
21
src/components/navbar/NavbarButtonLink.tsx
Normal file
21
src/components/navbar/NavbarButtonLink.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { NavbarItem } from "@nextui-org/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import ButtonLink from "../link-components/ButtonLink";
|
||||||
|
|
||||||
|
interface NavbarButtonLinkProps {
|
||||||
|
icon?: ReactNode;
|
||||||
|
href: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NavbarButtonLink({
|
||||||
|
icon,
|
||||||
|
href,
|
||||||
|
name,
|
||||||
|
}: NavbarButtonLinkProps) {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<ButtonLink icon={icon} href={href} name={name} />
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
16
src/components/navbar/NavbarIconLink.tsx
Normal file
16
src/components/navbar/NavbarIconLink.tsx
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { NavbarItem } from "@nextui-org/react";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import IconLink from "../link-components/IconLink";
|
||||||
|
|
||||||
|
interface NavbarIconLinkProps {
|
||||||
|
icon: ReactNode;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NavbarIconLink({ icon, href }: NavbarIconLinkProps) {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<IconLink icon={icon} href={href} />
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
15
src/components/navbar/NavbarLink.tsx
Normal file
15
src/components/navbar/NavbarLink.tsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { NavbarItem } from "@nextui-org/react";
|
||||||
|
import Link from "../link-components/Link";
|
||||||
|
|
||||||
|
interface NavbarLinkProps {
|
||||||
|
name: string;
|
||||||
|
href: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function NavbarLink({ name, href }: NavbarLinkProps) {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<Link name={name} href={href} />
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
9
src/components/navbar/NavbarSearchbar.tsx
Normal file
9
src/components/navbar/NavbarSearchbar.tsx
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { Input, NavbarItem } from "@nextui-org/react";
|
||||||
|
|
||||||
|
export default function NavbarSearchbar() {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<Input placeholder="Search" />
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
152
src/components/navbar/PCNavbar.tsx
Normal file
152
src/components/navbar/PCNavbar.tsx
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
Image,
|
||||||
|
Link,
|
||||||
|
NavbarBrand,
|
||||||
|
Navbar as NavbarBase,
|
||||||
|
NavbarContent,
|
||||||
|
Divider,
|
||||||
|
} from "@nextui-org/react";
|
||||||
|
import NavbarLink from "./NavbarLink";
|
||||||
|
import NavbarSearchbar from "./NavbarSearchbar";
|
||||||
|
import NavbarButtonLink from "./NavbarButtonLink";
|
||||||
|
import {
|
||||||
|
CalendarPlus,
|
||||||
|
Gamepad2,
|
||||||
|
LogInIcon,
|
||||||
|
NotebookPen,
|
||||||
|
SquarePen,
|
||||||
|
} from "lucide-react";
|
||||||
|
import NextImage from "next/image";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { usePathname } from "next/navigation";
|
||||||
|
import { getCookie, hasCookie } from "@/helpers/cookie";
|
||||||
|
import { getCurrentJam, joinJam } from "@/helpers/jam";
|
||||||
|
import { JamType } from "@/types/JamType";
|
||||||
|
import { UserType } from "@/types/UserType";
|
||||||
|
import NavbarUser from "./PCNavbarUser";
|
||||||
|
import NavbarButtonAction from "./NavbarButtonAction";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
|
||||||
|
export default function PCNavbar() {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const [jam, setJam] = useState<JamType | null>();
|
||||||
|
const [isInJam, setIsInJam] = useState<boolean>();
|
||||||
|
const [user, setUser] = useState<UserType>();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadUser();
|
||||||
|
async function loadUser() {
|
||||||
|
const currentJam = await getCurrentJam();
|
||||||
|
setJam(currentJam);
|
||||||
|
|
||||||
|
if (!hasCookie("token")) {
|
||||||
|
setUser(undefined);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
process.env.NEXT_PUBLIC_MODE === "PROD"
|
||||||
|
? `https://d2jam.com/api/v1/self?username=${getCookie("user")}`
|
||||||
|
: `http://localhost:3005/api/v1/self?username=${getCookie("user")}`,
|
||||||
|
{
|
||||||
|
headers: { authorization: `Bearer ${getCookie("token")}` },
|
||||||
|
credentials: "include",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const user = await response.json();
|
||||||
|
|
||||||
|
if (
|
||||||
|
currentJam &&
|
||||||
|
user.jams.filter((jam: JamType) => jam.id == currentJam.id).length > 0
|
||||||
|
) {
|
||||||
|
setIsInJam(true);
|
||||||
|
} else {
|
||||||
|
setIsInJam(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.status == 200) {
|
||||||
|
setUser(user);
|
||||||
|
} else {
|
||||||
|
setUser(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [pathname]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavbarBase maxWidth="2xl" className="bg-[#222] p-1" isBordered height={80}>
|
||||||
|
{/* Left side navbar items */}
|
||||||
|
<NavbarContent justify="start" className="gap-10">
|
||||||
|
<NavbarBrand className="flex-grow-0">
|
||||||
|
<Link
|
||||||
|
href="/"
|
||||||
|
className="duration-500 ease-in-out transition-all transform hover:scale-110"
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
as={NextImage}
|
||||||
|
src="/images/d2jam.png"
|
||||||
|
className="min-w-[70px]"
|
||||||
|
alt="Dare2Jam logo"
|
||||||
|
width={70}
|
||||||
|
height={59.7}
|
||||||
|
/>
|
||||||
|
</Link>
|
||||||
|
</NavbarBrand>
|
||||||
|
|
||||||
|
<NavbarLink href="/about" name="About" />
|
||||||
|
<NavbarLink href="/games" name="Games" />
|
||||||
|
</NavbarContent>
|
||||||
|
|
||||||
|
{/* Right side navbar items */}
|
||||||
|
<NavbarContent justify="end" className="gap-4">
|
||||||
|
<NavbarSearchbar />
|
||||||
|
{user && <Divider orientation="vertical" className="h-1/2" />}
|
||||||
|
{user && jam && isInJam && (
|
||||||
|
<NavbarButtonLink
|
||||||
|
icon={<Gamepad2 />}
|
||||||
|
name="Create Game"
|
||||||
|
href="/create-game"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{user && jam && !isInJam && (
|
||||||
|
<NavbarButtonAction
|
||||||
|
icon={<CalendarPlus />}
|
||||||
|
name="Join jam"
|
||||||
|
onPress={async () => {
|
||||||
|
const currentJam = await getCurrentJam();
|
||||||
|
|
||||||
|
if (!currentJam) {
|
||||||
|
toast.error("There is no jam to join");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (await joinJam(currentJam.id)) {
|
||||||
|
setIsInJam(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{user && (
|
||||||
|
<NavbarButtonLink
|
||||||
|
icon={<SquarePen />}
|
||||||
|
name="Create Post"
|
||||||
|
href="/create-post"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Divider orientation="vertical" className="h-1/2" />
|
||||||
|
{!user && (
|
||||||
|
<NavbarButtonLink icon={<LogInIcon />} name="Log In" href="/login" />
|
||||||
|
)}
|
||||||
|
{!user && (
|
||||||
|
<NavbarButtonLink
|
||||||
|
icon={<NotebookPen />}
|
||||||
|
name="Sign Up"
|
||||||
|
href="/signup"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{user && <NavbarUser user={user} />}
|
||||||
|
</NavbarContent>
|
||||||
|
</NavbarBase>
|
||||||
|
);
|
||||||
|
}
|
50
src/components/navbar/PCNavbarUser.tsx
Normal file
50
src/components/navbar/PCNavbarUser.tsx
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
import {
|
||||||
|
Avatar,
|
||||||
|
Dropdown,
|
||||||
|
DropdownItem,
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownTrigger,
|
||||||
|
NavbarItem,
|
||||||
|
} from "@nextui-org/react";
|
||||||
|
import { UserType } from "@/types/UserType";
|
||||||
|
|
||||||
|
interface NavbarUserProps {
|
||||||
|
user: UserType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function PCNavbarUser({ user }: NavbarUserProps) {
|
||||||
|
return (
|
||||||
|
<NavbarItem>
|
||||||
|
<Dropdown>
|
||||||
|
<DropdownTrigger>
|
||||||
|
<Avatar src={user.profilePicture} className="cursor-pointer" />
|
||||||
|
</DropdownTrigger>
|
||||||
|
<DropdownMenu>
|
||||||
|
<DropdownItem
|
||||||
|
key="profile"
|
||||||
|
className="text-black"
|
||||||
|
href={`/u/${user.slug}`}
|
||||||
|
>
|
||||||
|
Profile
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
showDivider
|
||||||
|
key="settings"
|
||||||
|
className="text-black"
|
||||||
|
href="/settings"
|
||||||
|
>
|
||||||
|
Settings
|
||||||
|
</DropdownItem>
|
||||||
|
<DropdownItem
|
||||||
|
key="logout"
|
||||||
|
color="danger"
|
||||||
|
className="text-danger"
|
||||||
|
href="/logout"
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</DropdownItem>
|
||||||
|
</DropdownMenu>
|
||||||
|
</Dropdown>
|
||||||
|
</NavbarItem>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,531 +1,20 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import {
|
|
||||||
Navbar as NavbarBase,
|
|
||||||
NavbarBrand,
|
|
||||||
NavbarContent,
|
|
||||||
NavbarItem,
|
|
||||||
} from "@nextui-org/navbar";
|
|
||||||
import { Link } from "@nextui-org/link";
|
|
||||||
import { Divider } from "@nextui-org/divider";
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
Button,
|
|
||||||
Dropdown,
|
|
||||||
DropdownItem,
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownTrigger,
|
|
||||||
Image,
|
|
||||||
Tooltip,
|
|
||||||
} from "@nextui-org/react";
|
|
||||||
import { SiDiscord, SiForgejo, SiGithub } from "@icons-pack/react-simple-icons";
|
|
||||||
import {
|
|
||||||
CalendarPlus,
|
|
||||||
Gamepad2,
|
|
||||||
LogInIcon,
|
|
||||||
Menu,
|
|
||||||
NotebookPen,
|
|
||||||
SquarePen,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { hasCookie, getCookie } from "@/helpers/cookie";
|
import PCNavbar from "./PCNavbar";
|
||||||
import { usePathname } from "next/navigation";
|
import MobileNavbar from "./MobileNavbar";
|
||||||
import { UserType } from "@/types/UserType";
|
|
||||||
import { getCurrentJam, joinJam } from "@/helpers/jam";
|
|
||||||
import { toast } from "react-toastify";
|
|
||||||
import { JamType } from "@/types/JamType";
|
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
const [user, setUser] = useState<UserType>();
|
const [isMobile, setIsMobile] = useState<boolean>(false);
|
||||||
const pathname = usePathname();
|
|
||||||
const [isMobile, setIsMobile] = useState(false);
|
|
||||||
const [jam, setJam] = useState<JamType | null>();
|
|
||||||
const [isInJam, setIsInJam] = useState<boolean>();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
loadUser();
|
|
||||||
async function loadUser() {
|
|
||||||
const currentJam = await getCurrentJam();
|
|
||||||
setJam(currentJam);
|
|
||||||
|
|
||||||
if (!hasCookie("token")) {
|
|
||||||
setUser(undefined);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(
|
|
||||||
process.env.NEXT_PUBLIC_MODE === "PROD"
|
|
||||||
? `https://d2jam.com/api/v1/self?username=${getCookie("user")}`
|
|
||||||
: `http://localhost:3005/api/v1/self?username=${getCookie("user")}`,
|
|
||||||
{
|
|
||||||
headers: { authorization: `Bearer ${getCookie("token")}` },
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const user = await response.json();
|
|
||||||
|
|
||||||
if (
|
|
||||||
currentJam &&
|
|
||||||
user.jams.filter((jam: JamType) => jam.id == currentJam.id).length > 0
|
|
||||||
) {
|
|
||||||
setIsInJam(true);
|
|
||||||
} else {
|
|
||||||
setIsInJam(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (response.status == 200) {
|
|
||||||
setUser(user);
|
|
||||||
} else {
|
|
||||||
setUser(undefined);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [pathname]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleResize = () => {
|
const handleResize = () => {
|
||||||
setIsMobile(window.innerWidth <= 768); // Adjust breakpoint as needed
|
setIsMobile(window.innerWidth <= 768);
|
||||||
};
|
};
|
||||||
handleResize();
|
handleResize();
|
||||||
window.addEventListener("resize", handleResize);
|
window.addEventListener("resize", handleResize);
|
||||||
return () => window.removeEventListener("resize", handleResize);
|
return () => window.removeEventListener("resize", handleResize);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return isMobile ? <MobileNavbar /> : <PCNavbar />;
|
||||||
<NavbarBase
|
|
||||||
shouldHideOnScroll
|
|
||||||
maxWidth="2xl"
|
|
||||||
className="bg-transparent p-1"
|
|
||||||
>
|
|
||||||
<NavbarBrand>
|
|
||||||
<Link
|
|
||||||
href="/"
|
|
||||||
className="duration-500 ease-in-out transition-all transform hover:scale-110"
|
|
||||||
>
|
|
||||||
<Image src="/images/dare2jam.png" alt="Dare2Jam logo" width={80} />
|
|
||||||
</Link>
|
|
||||||
</NavbarBrand>
|
|
||||||
<NavbarContent justify="end">
|
|
||||||
{isMobile ? (
|
|
||||||
user ? (
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownTrigger>
|
|
||||||
<Avatar src={user.profilePicture} />
|
|
||||||
</DropdownTrigger>
|
|
||||||
<DropdownMenu className="text-black">
|
|
||||||
{jam && isInJam ? (
|
|
||||||
<DropdownItem key="create-game" href="/create-game">
|
|
||||||
Create Game
|
|
||||||
</DropdownItem>
|
|
||||||
) : null}
|
|
||||||
{jam && !isInJam ? (
|
|
||||||
<DropdownItem
|
|
||||||
key="join-event"
|
|
||||||
onPress={async () => {
|
|
||||||
try {
|
|
||||||
const currentJam = await getCurrentJam();
|
|
||||||
|
|
||||||
if (!currentJam) {
|
|
||||||
toast.error("There is no jam to join");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (await joinJam(currentJam.id)) {
|
|
||||||
setIsInJam(true);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error during join process:", error);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Join Event
|
|
||||||
</DropdownItem>
|
|
||||||
) : null}
|
|
||||||
<DropdownItem key="create-post" href="/create-post">
|
|
||||||
Create Post
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="profile"
|
|
||||||
className="text-black"
|
|
||||||
href={`/u/${user.slug}`}
|
|
||||||
>
|
|
||||||
Profile
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
showDivider
|
|
||||||
key="settings"
|
|
||||||
className="text-black"
|
|
||||||
href="/settings"
|
|
||||||
>
|
|
||||||
Settings
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="github"
|
|
||||||
href="https://github.com/Ategon/Jamjar"
|
|
||||||
>
|
|
||||||
GitHub
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="forgejo"
|
|
||||||
href="https://git.edikoyo.com/Ategon/Jamjar"
|
|
||||||
>
|
|
||||||
Forgejo
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="discord"
|
|
||||||
href="https://discord.gg/rfmKzM6ASw"
|
|
||||||
>
|
|
||||||
Discord
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="logout" color="danger" href="/logout">
|
|
||||||
Logout
|
|
||||||
</DropdownItem>
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
) : (
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownTrigger>
|
|
||||||
<Menu />
|
|
||||||
</DropdownTrigger>
|
|
||||||
<DropdownMenu className="text-black">
|
|
||||||
<DropdownItem
|
|
||||||
key="github"
|
|
||||||
href="https://github.com/Ategon/Jamjar"
|
|
||||||
>
|
|
||||||
GitHub
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="forgejo"
|
|
||||||
href="https://git.edikoyo.com/Ategon/Jamjar"
|
|
||||||
>
|
|
||||||
Forgejo
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="discord"
|
|
||||||
href="https://discord.gg/rfmKzM6ASw"
|
|
||||||
>
|
|
||||||
Discord
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="login" href="/login">
|
|
||||||
Log In
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="signup" href="/signup">
|
|
||||||
Sign Up
|
|
||||||
</DropdownItem>
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<div className="flex gap-3 items-center">
|
|
||||||
{user && jam && isInJam && (
|
|
||||||
<NavbarItem>
|
|
||||||
<Link href="/create-game">
|
|
||||||
<Button
|
|
||||||
endContent={<Gamepad2 />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Create Game
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
)}
|
|
||||||
{user && jam && !isInJam && (
|
|
||||||
<NavbarItem>
|
|
||||||
<Button
|
|
||||||
endContent={<CalendarPlus />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
onPress={async () => {
|
|
||||||
const currentJam = await getCurrentJam();
|
|
||||||
|
|
||||||
if (!currentJam) {
|
|
||||||
toast.error("There is no jam to join");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (await joinJam(currentJam.id)) {
|
|
||||||
setIsInJam(true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Join Jam
|
|
||||||
</Button>
|
|
||||||
</NavbarItem>
|
|
||||||
)}
|
|
||||||
{user && (
|
|
||||||
<NavbarItem className="flex items-center">
|
|
||||||
<Link href="/create-post">
|
|
||||||
<Button
|
|
||||||
endContent={<SquarePen />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Create Post
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
)}
|
|
||||||
<NavbarItem>
|
|
||||||
<Tooltip
|
|
||||||
delay={1000}
|
|
||||||
content={
|
|
||||||
<div className="px-1 py-2 text-black text-center">
|
|
||||||
<div className="text-small font-bold">GitHub</div>
|
|
||||||
<div className="text-tiny">Source Code</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
href="https://github.com/Dare2Jam/"
|
|
||||||
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125 hover:text-red-100"
|
|
||||||
isExternal
|
|
||||||
>
|
|
||||||
<SiGithub title="" />
|
|
||||||
</Link>
|
|
||||||
</Tooltip>
|
|
||||||
</NavbarItem>
|
|
||||||
<NavbarItem>
|
|
||||||
<Tooltip
|
|
||||||
delay={1000}
|
|
||||||
content={
|
|
||||||
<div className="px-1 py-2 text-black text-center">
|
|
||||||
<div className="text-small font-bold">Forgejo</div>
|
|
||||||
<div className="text-tiny">Source Code</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
href="https://git.edikoyo.com/Ategon/Jamjar"
|
|
||||||
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125 hover:text-red-100"
|
|
||||||
isExternal
|
|
||||||
>
|
|
||||||
<SiForgejo title="" />
|
|
||||||
</Link>
|
|
||||||
</Tooltip>
|
|
||||||
</NavbarItem>
|
|
||||||
<NavbarItem>
|
|
||||||
<Link
|
|
||||||
href="https://discord.gg/rfmKzM6ASw"
|
|
||||||
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125 hover:text-indigo-100"
|
|
||||||
isExternal
|
|
||||||
>
|
|
||||||
<SiDiscord />
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
<Divider orientation="vertical" className="h-1/2" />
|
|
||||||
{!user ? (
|
|
||||||
<div className="flex gap-3 items-center">
|
|
||||||
<NavbarItem>
|
|
||||||
<Link href="/login">
|
|
||||||
<Button
|
|
||||||
endContent={<LogInIcon />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Log In
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
<NavbarItem>
|
|
||||||
<Link href="/signup">
|
|
||||||
<Button
|
|
||||||
endContent={<NotebookPen />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Sign up
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownTrigger>
|
|
||||||
<Avatar src={user.profilePicture} />
|
|
||||||
</DropdownTrigger>
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownItem
|
|
||||||
key="profile"
|
|
||||||
className="text-black"
|
|
||||||
href={`/u/${user.slug}`}
|
|
||||||
>
|
|
||||||
Profile
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
showDivider
|
|
||||||
key="settings"
|
|
||||||
className="text-black"
|
|
||||||
href="/settings"
|
|
||||||
>
|
|
||||||
Settings
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem
|
|
||||||
key="logout"
|
|
||||||
color="danger"
|
|
||||||
className="text-danger"
|
|
||||||
href="/logout"
|
|
||||||
>
|
|
||||||
Logout
|
|
||||||
</DropdownItem>
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</NavbarContent>
|
|
||||||
</NavbarBase>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
|
|
||||||
{isMobile ? (
|
|
||||||
// Mobile view
|
|
||||||
user ? (
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownTrigger>
|
|
||||||
<Avatar src={user.profilePicture} />
|
|
||||||
</DropdownTrigger>
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownItem key="create-post" href="/create-post">
|
|
||||||
Create Post
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="logout" color="danger" href="/logout">
|
|
||||||
Logout
|
|
||||||
</DropdownItem>
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
) : (
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownTrigger>
|
|
||||||
<Button auto flat className="text-white">
|
|
||||||
☰
|
|
||||||
</Button>
|
|
||||||
</DropdownTrigger>
|
|
||||||
<DropdownMenu>
|
|
||||||
<DropdownItem key="github" href="https://github.com/Ategon/Jamjar" isExternal>
|
|
||||||
GitHub
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="forgejo" href="https://git.edikoyo.com/Ategon/Jamjar" isExternal>
|
|
||||||
Forgejo
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="discord" href="https://discord.gg/rfmKzM6ASw" isExternal>
|
|
||||||
Discord
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="login" href="/login">
|
|
||||||
Log In
|
|
||||||
</DropdownItem>
|
|
||||||
<DropdownItem key="signup" href="/signup">
|
|
||||||
Sign Up
|
|
||||||
</DropdownItem>
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
)
|
|
||||||
) : (
|
|
||||||
|
|
||||||
|
|
||||||
user && (
|
|
||||||
<NavbarItem>
|
|
||||||
<Link href="/create-post">
|
|
||||||
<Button
|
|
||||||
endContent={<SquarePen />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Create Post
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
<Spacer x={32} />
|
|
||||||
</NavbarItem>
|
|
||||||
)
|
|
||||||
<NavbarItem>
|
|
||||||
<Tooltip
|
|
||||||
delay={1000}
|
|
||||||
content={
|
|
||||||
<div className="px-1 py-2 text-black text-center">
|
|
||||||
<div className="text-small font-bold">GitHub</div>
|
|
||||||
<div className="text-tiny">Source Code</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
href="https://github.com/Dare2Jam/"
|
|
||||||
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125 hover:text-red-100"
|
|
||||||
isExternal
|
|
||||||
>
|
|
||||||
<SiGithub title="" />
|
|
||||||
</Link>
|
|
||||||
</Tooltip>
|
|
||||||
</NavbarItem>
|
|
||||||
<NavbarItem>
|
|
||||||
<Tooltip
|
|
||||||
delay={1000}
|
|
||||||
content={
|
|
||||||
<div className="px-1 py-2 text-black text-center">
|
|
||||||
<div className="text-small font-bold">Forgejo</div>
|
|
||||||
<div className="text-tiny">Source Code</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Link
|
|
||||||
href="https://git.edikoyo.com/Ategon/Jamjar"
|
|
||||||
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125 hover:text-red-100"
|
|
||||||
isExternal
|
|
||||||
>
|
|
||||||
<SiForgejo title="" />
|
|
||||||
</Link>
|
|
||||||
</Tooltip>
|
|
||||||
</NavbarItem>
|
|
||||||
<NavbarItem>
|
|
||||||
<Link
|
|
||||||
href="https://discord.gg/rfmKzM6ASw"
|
|
||||||
className="text-white flex justify-center duration-500 ease-in-out transition-all transform hover:scale-125 hover:text-indigo-100"
|
|
||||||
isExternal
|
|
||||||
>
|
|
||||||
<SiDiscord />
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
<Divider orientation="vertical" className="h-1/2" />
|
|
||||||
{!user ? (
|
|
||||||
<div className="flex gap-3 items-center">
|
|
||||||
<NavbarItem>
|
|
||||||
<Link href="/login">
|
|
||||||
<Button
|
|
||||||
endContent={<LogInIcon />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Log In
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
<NavbarItem>
|
|
||||||
<Link href="/signup">
|
|
||||||
<Button
|
|
||||||
endContent={<NotebookPen />}
|
|
||||||
className="text-white border-white/50 hover:border-green-100/50 hover:text-green-100 hover:scale-110 transition-all transform duration-500 ease-in-out"
|
|
||||||
variant="bordered"
|
|
||||||
>
|
|
||||||
Sign up
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</NavbarItem>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<Dropdown>
|
|
||||||
<DropdownTrigger>
|
|
||||||
<Avatar src={user.profilePicture} />
|
|
||||||
</DropdownTrigger>
|
|
||||||
<DropdownMenu>
|
|
||||||
|
|
||||||
<DropdownItem
|
|
||||||
key="logout"
|
|
||||||
color="danger"
|
|
||||||
className="text-danger"
|
|
||||||
href="/logout"
|
|
||||||
>
|
|
||||||
Logout
|
|
||||||
</DropdownItem>
|
|
||||||
</DropdownMenu>
|
|
||||||
</Dropdown>
|
|
||||||
)}
|
|
||||||
)
|
|
||||||
</NavbarContent> */
|
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
import { Avatar, Card, CardBody, Spacer } from "@nextui-org/react";
|
import { Avatar, Button, Card, CardBody, Spacer } from "@nextui-org/react";
|
||||||
import { formatDistance } from "date-fns";
|
import { formatDistance } from "date-fns";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { PostType } from "@/types/PostType";
|
import { PostType } from "@/types/PostType";
|
||||||
|
import { Heart, MessageCircle } from "lucide-react";
|
||||||
|
|
||||||
export default function PostCard({ post }: { post: PostType }) {
|
export default function PostCard({ post }: { post: PostType }) {
|
||||||
return (
|
return (
|
||||||
<Card className="bg-opacity-60">
|
<Card className="bg-opacity-60">
|
||||||
<CardBody>
|
<CardBody className="p-5">
|
||||||
<p className="text-2xl">{post.title}</p>
|
<p className="text-2xl">{post.title}</p>
|
||||||
|
|
||||||
<div className="flex items-center gap-3 text-xs text-default-500 pt-1">
|
<div className="flex items-center gap-3 text-xs text-default-500 pt-1">
|
||||||
|
@ -35,14 +36,14 @@ export default function PostCard({ post }: { post: PostType }) {
|
||||||
|
|
||||||
<Spacer y={4} />
|
<Spacer y={4} />
|
||||||
|
|
||||||
{/* <div className="flex gap-3">
|
<div className="flex gap-3">
|
||||||
<Button size="sm">
|
<Button size="sm" variant="bordered">
|
||||||
<Heart size={16} /> {post.likers.length}
|
<Heart size={16} /> {post.likers.length}
|
||||||
</Button>
|
</Button>
|
||||||
<Button size="sm">
|
<Button size="sm" variant="bordered">
|
||||||
<MessageCircle size={16} /> {0}
|
<MessageCircle size={16} /> {0}
|
||||||
</Button>
|
</Button>
|
||||||
</div> */}
|
</div>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import PostCard from "./PostCard";
|
import PostCard from "./PostCard";
|
||||||
import { PostType } from "@/types/PostType";
|
import { PostType } from "@/types/PostType";
|
||||||
|
import { Button } from "@nextui-org/react";
|
||||||
|
|
||||||
export default function Posts() {
|
export default function Posts() {
|
||||||
const [posts, setPosts] = useState<PostType[]>();
|
const [posts, setPosts] = useState<PostType[]>();
|
||||||
|
@ -21,13 +22,30 @@ export default function Posts() {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-3 p-4">
|
<div>
|
||||||
{posts &&
|
<div className="flex justify-between p-4 pb-0">
|
||||||
posts.map((post) => (
|
<div className="flex gap-2">
|
||||||
<div key={post.id}>
|
<Button size="sm" className="text-xs" variant="faded">
|
||||||
<PostCard post={post} />
|
Newest
|
||||||
</div>
|
</Button>
|
||||||
))}
|
<Button size="sm" className="text-xs" variant="faded">
|
||||||
|
All Tags
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Button size="sm" className="text-xs" variant="faded">
|
||||||
|
Cozy
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-3 p-4">
|
||||||
|
{posts &&
|
||||||
|
posts.map((post) => (
|
||||||
|
<div key={post.id}>
|
||||||
|
<PostCard post={post} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
"use client";
|
|
||||||
|
|
||||||
// import { useEffect, useState } from "react";
|
|
||||||
// import { useParams } from "next/navigation";
|
|
||||||
|
|
||||||
export default function User() {
|
|
||||||
// const [user, setUser] = useState();
|
|
||||||
// const { slug } = useParams();
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// const fetchUser = async () => {
|
|
||||||
// const response = await fetch(`http://localhost:3005/api/v1/user?slug=${slug}`)
|
|
||||||
// setUser(await response.json());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fetchUser();
|
|
||||||
// }, [])
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <div>
|
|
||||||
// {user && (
|
|
||||||
// <div>
|
|
||||||
// <p>{user.name}</p>
|
|
||||||
// <p>{user.bio}</p>
|
|
||||||
// </div>
|
|
||||||
// )}
|
|
||||||
// </div>
|
|
||||||
// );
|
|
||||||
return <div></div>;
|
|
||||||
}
|
|
Loading…
Reference in a new issue