Can navigate to landing page from authed pages
This commit is contained in:
@@ -2,7 +2,8 @@ import type { Children } from "@utils/types/props";
|
||||
import { useState, useEffect } from "react";
|
||||
import { cva, cx } from "class-variance-authority";
|
||||
import { Button } from "@components/Button";
|
||||
import { signIn } from "next-auth/react";
|
||||
import { signIn, useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
export const HomeLayout: React.FC<Children> = ({ children }) => {
|
||||
return (
|
||||
@@ -33,7 +34,7 @@ const Header: React.FC = () => {
|
||||
|
||||
// Scroll Listener
|
||||
useEffect(() => {
|
||||
const listenScrollEvent = () => {
|
||||
const listenScrollEvent: () => void = () => {
|
||||
const threshold = 25;
|
||||
setIsLargeBar(
|
||||
document.body.scrollTop < threshold &&
|
||||
@@ -47,18 +48,6 @@ const Header: React.FC = () => {
|
||||
};
|
||||
});
|
||||
|
||||
const FlexDivider = () => <span className="text-r-2xl text-fg/25">||</span>;
|
||||
|
||||
const Background = () => (
|
||||
<div
|
||||
className={cx(
|
||||
"absolute inset-0 -z-10",
|
||||
"bg-gradient-to-b from-bg via-bg/60 to-transparent",
|
||||
"backdrop-blur [mask:linear-gradient(black_75%,transparent)]"
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<header
|
||||
className={header({
|
||||
@@ -79,19 +68,57 @@ const Header: React.FC = () => {
|
||||
Premium
|
||||
</a>
|
||||
</div>
|
||||
<CTAButton />
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
const FlexDivider: React.FC = () => (
|
||||
<span className="text-r-2xl text-fg/25">||</span>
|
||||
);
|
||||
|
||||
const Background: React.FC = () => (
|
||||
<div
|
||||
className={cx(
|
||||
"absolute inset-0 -z-10",
|
||||
"bg-gradient-to-b from-bg via-bg/60 to-transparent",
|
||||
"backdrop-blur [mask:linear-gradient(black_75%,transparent)]"
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
||||
const CTAButton: React.FC = () => {
|
||||
const session = useSession();
|
||||
const router = useRouter();
|
||||
|
||||
if (session.status === "authenticated") {
|
||||
const username = session.data.user.username ?? "";
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant={{ size: "small" }}
|
||||
onClick={() =>
|
||||
onClick={() => {
|
||||
void signIn(undefined, {
|
||||
callbackUrl: "/projects",
|
||||
callbackUrl: `/profile/${username}`,
|
||||
redirect: false,
|
||||
})
|
||||
});
|
||||
}}
|
||||
>
|
||||
{username}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant={{ size: "small" }}
|
||||
onClick={() => {
|
||||
void router.push(`/projects`);
|
||||
}}
|
||||
>
|
||||
Sign In
|
||||
</Button>
|
||||
</nav>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
FiUser,
|
||||
FiLogOut,
|
||||
FiSettings,
|
||||
FiExternalLink,
|
||||
} from "react-icons/fi";
|
||||
import type { IconType } from "react-icons/lib";
|
||||
import { Button } from "@components/Button";
|
||||
@@ -220,6 +221,7 @@ const MoreMenu: React.FC = () => {
|
||||
className="min-w-[250px] rounded-md bg-bg-700 p-3 data-[side=top]:animate-slideUpAndFade"
|
||||
sideOffset={10}
|
||||
>
|
||||
{/* Settings */}
|
||||
<DropdownMenu.Item>
|
||||
<Link
|
||||
href="/settings"
|
||||
@@ -229,6 +231,19 @@ const MoreMenu: React.FC = () => {
|
||||
<FiSettings />
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
|
||||
{/* Landing page */}
|
||||
<DropdownMenu.Item>
|
||||
<Link
|
||||
href="/"
|
||||
className="flex w-full select-none items-center justify-between px-[5px] pl-[25px] outline-none"
|
||||
>
|
||||
<p className="text-r-lg">Parallel Homepage</p>
|
||||
<FiExternalLink />
|
||||
</Link>
|
||||
</DropdownMenu.Item>
|
||||
|
||||
{/* Sign out */}
|
||||
<DropdownMenu.Item>
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -31,13 +31,7 @@ export const getServerSideProps: GetServerSideProps = async (
|
||||
) => {
|
||||
const session = await getServerAuthSession(ctx);
|
||||
|
||||
if (session && session.user) {
|
||||
return {
|
||||
redirect: { destination: "/projects", permanent: false },
|
||||
};
|
||||
}
|
||||
|
||||
return { props: { session } };
|
||||
return { props: { session: session } };
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
||||
@@ -1,17 +1,79 @@
|
||||
import Button from "@components/Button";
|
||||
import { requireAuth } from "@components/HOC/requireAuth";
|
||||
import { MainLayout } from "@components/layouts";
|
||||
import { ProjectLifecycle } from "@prisma/client";
|
||||
import { api } from "@utils/api";
|
||||
import { formatDate } from "@utils/filters";
|
||||
import type { InferGetServerSidePropsType, NextPage } from "next";
|
||||
|
||||
const StateOrder: ProjectLifecycle[] = Object.values(ProjectLifecycle);
|
||||
|
||||
const SpecificProject: NextPage<
|
||||
InferGetServerSidePropsType<typeof getServerSideProps>
|
||||
> = ({ projectId }) => {
|
||||
const ctx = api.useContext();
|
||||
|
||||
const { data, isRefetching } = api.projects.getProjectById.useQuery({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { data } = api.projects.getProjectById.useQuery({ projectId });
|
||||
projectId,
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||
const { mutate, isLoading: isUpdatingState } =
|
||||
api.projects.updateState.useMutation({
|
||||
onSuccess: () => {
|
||||
void ctx.projects.getProjectById.invalidate();
|
||||
},
|
||||
});
|
||||
|
||||
const changeState = (diff: -1 | 1) => {
|
||||
if (!data) return;
|
||||
|
||||
const newState =
|
||||
StateOrder[
|
||||
StateOrder.findIndex((state) => state === data.state) + diff
|
||||
] ?? data.state;
|
||||
|
||||
if (newState !== data.state) {
|
||||
mutate({
|
||||
projectId: data.id,
|
||||
state: newState,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<MainLayout>
|
||||
<p>{data?.id}</p>
|
||||
{!data ? (
|
||||
<p>Loading...</p>
|
||||
) : (
|
||||
<>
|
||||
<p>{data.title}</p>
|
||||
<p>{formatDate(data.createdAt)}</p>
|
||||
<p>{data.description}</p>
|
||||
<p>ID: {data.id}</p>
|
||||
<p>State: {data.state}</p>
|
||||
<div className="flex flex-row gap-x-4">
|
||||
<Button
|
||||
variant={{ size: "small" }}
|
||||
disabled={
|
||||
data.state === "PROPOSAL" || isUpdatingState || isRefetching
|
||||
}
|
||||
onClick={() => changeState(-1)}
|
||||
>
|
||||
Prev State
|
||||
</Button>
|
||||
<Button
|
||||
variant={{ size: "small" }}
|
||||
disabled={
|
||||
data.state === "COMPLETE" || isUpdatingState || isRefetching
|
||||
}
|
||||
onClick={() => changeState(1)}
|
||||
>
|
||||
Next State
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</MainLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,6 +40,7 @@ export const projectsRouter = createTRPCRouter({
|
||||
const projects = await ctx.prisma.project.findMany({
|
||||
where: { state: input.state },
|
||||
select: {
|
||||
id: true,
|
||||
author: true,
|
||||
members: true,
|
||||
bannerImageUrl: true,
|
||||
@@ -51,11 +52,15 @@ export const projectsRouter = createTRPCRouter({
|
||||
take: 100,
|
||||
orderBy: [{ createdAt: "desc" }],
|
||||
});
|
||||
projects.map((p) => ({
|
||||
|
||||
return projects.map((p) => ({
|
||||
members: (() => {
|
||||
p.members.push(p.author);
|
||||
return p.members.map((m) => m.username);
|
||||
return p.members
|
||||
.map((m) => m.username)
|
||||
.filter((username) => !!username) as string[];
|
||||
})(),
|
||||
id: p.id,
|
||||
createdAt: p.createdAt,
|
||||
title: p.title,
|
||||
description: p.description,
|
||||
@@ -85,4 +90,18 @@ export const projectsRouter = createTRPCRouter({
|
||||
|
||||
return proposal;
|
||||
}),
|
||||
updateState: protectedProcedure
|
||||
.input(
|
||||
z.object({
|
||||
state: z.nativeEnum(ProjectLifecycle),
|
||||
projectId: z.string(),
|
||||
})
|
||||
)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
const { projectId, state } = input;
|
||||
await ctx.prisma.project.update({
|
||||
where: { id: projectId },
|
||||
data: { state },
|
||||
});
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user