Skip to content

Commit

Permalink
move application structure to /app route
Browse files Browse the repository at this point in the history
  • Loading branch information
d-ivashchuk committed Apr 7, 2024
1 parent 12abb43 commit c4df4e9
Show file tree
Hide file tree
Showing 14 changed files with 80 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/app/(landing)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export default function Home() {
</h2>
</div>
<div className="flex gap-2 self-center align-middle">
<Link href="/login">
<Link href="/app/login">
<Button>Try demo</Button>
</Link>
<Link target="_blank" href="https://github.com/d-ivashchuk/cascade">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ const Subscriptions = () => {
{userSubscriptionsQuery.data?.subscription ? (
<h1>
You are already subscribed. View your subscription{" "}
<Link href="/billing" className="underline">
<Link href="/app/billing" className="underline">
here
</Link>
</h1>
Expand Down
35 changes: 35 additions & 0 deletions src/app/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"use client";

import { useSession } from "next-auth/react";
import { usePathname, redirect } from "next/navigation";
import { useEffect } from "react";
import SplashScreen from "~/components/patterns/splash-screen";

const ProtectedRoutes = ({ children }: { children: React.ReactNode }) => {
const { status } = useSession();
const pathname = usePathname();

useEffect(() => {
const allowedUnauthenticatedPaths = ["/app/login", "/"];

if (
status !== "loading" &&
status !== "authenticated" &&
!allowedUnauthenticatedPaths.includes(pathname)
) {
redirect("/app/login");
}
}, [status, pathname]);

if (status === "loading" && pathname.includes("/app"))
return <SplashScreen />;
return <>{children}</>;
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return <ProtectedRoutes>{children}</ProtectedRoutes>;
}
21 changes: 21 additions & 0 deletions src/app/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

import { redirect } from "next/navigation";
import { LoginScreen } from "~/components/patterns/login-screen";
import { getServerAuthSession } from "~/server/auth";

const LoginPage = async () => {
const session = await getServerAuthSession();

if (session?.user) {
redirect("/app/usage");
}

return (
<div>
<LoginScreen />
</div>
);
};

export default LoginPage;
32 changes: 3 additions & 29 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import { Inter } from "next/font/google";

import { Layout } from "~/components/patterns/layout";
import Providers from "~/components/providers";
import { Suspense, useEffect } from "react";
import { Suspense } from "react";
import Script from "next/script";
import { useSession } from "next-auth/react";
import { redirect, usePathname } from "next/navigation";
import SplashScreen from "~/components/patterns/splash-screen";

import { Toaster } from "~/components/ui/sonner";
import { TailwindIndicator } from "~/components/patterns/tailwind-indicator";

Expand All @@ -19,28 +17,6 @@ const inter = Inter({
variable: "--font-sans",
});



const ProtectedRoutes = ({ children }: { children: React.ReactNode }) => {
const { status } = useSession();
const pathname = usePathname();

useEffect(() => {
const allowedUnauthenticatedPaths = ["/login", "/"];

if (
status !== "loading" &&
status !== "authenticated" &&
!allowedUnauthenticatedPaths.includes(pathname)
) {
redirect("/login");
}
}, [status, pathname]);

if (status === "loading" && pathname !== "/") return <SplashScreen />;
return <>{children}</>;
};

export default function RootLayout({
children,
}: {
Expand All @@ -55,9 +31,7 @@ export default function RootLayout({
/>
<Suspense>
<Providers>
<ProtectedRoutes>
<Layout>{children}</Layout>
</ProtectedRoutes>
<Layout>{children}</Layout>
</Providers>
</Suspense>
<Toaster />
Expand Down
12 changes: 0 additions & 12 deletions src/app/login/page.tsx

This file was deleted.

25 changes: 14 additions & 11 deletions src/components/patterns/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import { usePathname } from "next/navigation";

export async function Layout({ children }: { children: React.ReactNode }) {
const pathname = usePathname();

const isInApplicationRoute = pathname.includes("/app");

return (
<div className="flex min-h-screen w-full flex-col">
<header className="sticky top-0 z-30 flex h-16 items-center gap-4 border-b bg-background px-4 md:px-6">
Expand All @@ -33,28 +36,28 @@ export async function Layout({ children }: { children: React.ReactNode }) {
/>
</Link>
<nav className="hidden flex-col gap-6 text-lg font-medium md:flex md:flex-row md:items-center md:gap-5 md:text-sm lg:gap-6">
{pathname !== "/" && (
{isInApplicationRoute && (
<>
<Link
href="/subscriptions"
href="/app/subscriptions"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Subscriptions
</Link>
<Link
href="/billing"
href="/app/billing"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Billing
</Link>
<Link
href="/usage"
href="/app/usage"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Usage
</Link>
<Link
href="/user-management"
href="/app/user-management"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Management
Expand All @@ -64,7 +67,7 @@ export async function Layout({ children }: { children: React.ReactNode }) {
</nav>
<Sheet>
<SheetTrigger asChild>
{pathname === "/" ? (
{isInApplicationRoute ? (
<Image
src="/cd.svg"
width={40}
Expand All @@ -85,28 +88,28 @@ export async function Layout({ children }: { children: React.ReactNode }) {
</SheetTrigger>
<SheetContent side="left">
<nav className="grid gap-6 text-lg font-medium">
{pathname !== "/" && (
{isInApplicationRoute && (
<>
<Link
href="/subscriptions"
href="/app/subscriptions"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Subscriptions
</Link>
<Link
href="/billing"
href="/app/billing"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Billing
</Link>
<Link
href="/usage"
href="/app/usage"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Usage
</Link>
<Link
href="/user-management"
href="/app/user-management"
className="text-muted-foreground transition-colors hover:text-foreground"
>
Management
Expand Down
2 changes: 1 addition & 1 deletion src/components/patterns/login-logout-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const LoginLogoutButton = () => {

return (
<DropdownMenuItem
onClick={() => (isAuthenticated ? signOut() : router.push("/login"))}
onClick={() => (isAuthenticated ? signOut() : router.push("/app/login"))}
>
{isAuthenticated ? "Logout" : "Login"}
</DropdownMenuItem>
Expand Down
4 changes: 2 additions & 2 deletions src/components/patterns/login-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function LoginScreen() {
<Button
onClick={() =>
signIn("discord", {
callbackUrl: "/subscriptions/?loginState=signedIn",
callbackUrl: "/app/subscriptions/?loginState=signedIn",
})
}
variant="outline"
Expand All @@ -36,7 +36,7 @@ export function LoginScreen() {
<Button
onClick={() =>
signIn("google", {
callbackUrl: "/subscriptions/?loginState=signedIn",
callbackUrl: "/app/subscriptions/?loginState=signedIn",
})
}
variant="outline"
Expand Down
13 changes: 2 additions & 11 deletions src/components/patterns/splash-screen.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import { Loader2 } from "lucide-react";
import React from "react";
import Image from "next/image";

const SplashScreen = () => {
return (
<div className="flex h-screen w-screen flex-col items-center justify-center gap-4 ">
<div className="-mt-5 flex h-screen flex-col items-center justify-center gap-8">
<div className="text-center">
<Image
src="./cd.svg"
width={100}
height={100}
alt="cascade logo"
className="mx-auto mb-4 rounded-md"
/>
<h1 className="text-4xl">Cascade</h1>
<h2 className="text-xl text-muted-foreground">
<h2 className="text-wrap text-xl text-muted-foreground">
Production grade SaaS bootstrapped in minutes
</h2>
<p className=" text-xl text-muted-foreground"></p>
</div>
<Loader2 className="h-8 w-8 animate-spin" />
</div>
Expand Down

0 comments on commit c4df4e9

Please sign in to comment.