Organize routes

This commit is contained in:
cte 2025-05-12 00:17:15 -07:00
parent b8bb21a5da
commit c1c7206525
17 changed files with 94 additions and 159 deletions

View file

@ -1,18 +0,0 @@
import { auth } from '@clerk/nextjs/server';
import { redirect } from 'next/navigation';
export default async function CenteredLayout(props: {
children: React.ReactNode;
}) {
const { userId } = await auth();
if (userId) {
redirect('/dashboard');
}
return (
<div className="flex min-h-screen items-center justify-center">
{props.children}
</div>
);
}

View file

@ -1,56 +0,0 @@
import { useTranslations } from 'next-intl';
import { MessageState } from '@/components/dashboard/MessageState';
import { TitleBar } from '@/components/dashboard/TitleBar';
const DashboardIndexPage = () => {
const t = useTranslations('DashboardIndex');
return (
<>
<TitleBar
title={t('title_bar')}
description={t('title_bar_description')}
/>
<MessageState
icon={
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M0 0h24v24H0z" stroke="none" />
<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3M12 12l8-4.5M12 12v9M12 12L4 7.5" />
</svg>
}
title={t('message_state_title')}
description={t.rich('message_state_description', {
code: (chunks) => (
<code className="bg-secondary text-secondary-foreground">
{chunks}
</code>
),
})}
button={
<div className="mt-2 text-xs font-light text-muted-foreground">
{t.rich('message_state_alternative', {
url: () => (
<a
className="text-blue-500 hover:text-blue-600"
href="https://nextjs-boilerplate.com/pro-saas-starter-kit"
>
Next.js Boilerplate SaaS
</a>
),
})}
</div>
}
/>
</>
);
};
export default DashboardIndexPage;

View file

@ -1,26 +0,0 @@
'use client';
import { enUS, frFR } from '@clerk/localizations';
import { ClerkProvider } from '@clerk/nextjs';
import { useLocale } from 'next-intl';
export default function AuthLayout({
children,
}: {
children: React.ReactNode;
}) {
const locale = useLocale();
return (
<ClerkProvider
localization={locale === 'fr' ? frFR : enUS}
signInUrl="/sign-in"
signUpUrl="/sign-up"
signInFallbackRedirectUrl="/dashboard"
signUpFallbackRedirectUrl="/dashboard"
afterSignOutUrl="/"
>
{children}
</ClerkProvider>
);
}

View file

@ -3,7 +3,7 @@ import { useTranslations } from 'next-intl';
import { TitleBar } from '@/components/dashboard/TitleBar';
const OrganizationProfilePage = () => {
export default function Page() {
const t = useTranslations('OrganizationProfile');
return (
@ -26,6 +26,4 @@ const OrganizationProfilePage = () => {
/>
</>
);
};
export default OrganizationProfilePage;
}

View file

@ -0,0 +1,37 @@
import { useTranslations } from 'next-intl';
import { TitleBar } from '@/components/dashboard/TitleBar';
const DashboardIndexPage = () => {
const t = useTranslations('DashboardIndex');
return (
<>
<TitleBar
title={t('title_bar')}
description={t('title_bar_description')}
/>
<div className="flex h-[600px] flex-col items-center justify-center rounded-md bg-card p-5">
<div className="size-16 rounded-full bg-muted p-3 [&_svg]:stroke-muted-foreground [&_svg]:stroke-2">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M0 0h24v24H0z" stroke="none" />
<path d="M12 3l8 4.5v9L12 21l-8-4.5v-9L12 3M12 12l8-4.5M12 12v9M12 12L4 7.5" />
</svg>
</div>
<div className="mt-3 text-center">
<div className="text-xl font-semibold">
{t('message_state_title')}
</div>
</div>
</div>
</>
);
};
export default DashboardIndexPage;

View file

@ -3,7 +3,7 @@ import { useTranslations } from 'next-intl';
import { TitleBar } from '@/components/dashboard/TitleBar';
const UserProfilePage = () => {
export default function Page() {
const t = useTranslations('UserProfile');
return (
@ -12,19 +12,11 @@ const UserProfilePage = () => {
title={t('title_bar')}
description={t('title_bar_description')}
/>
<UserProfile
routing="path"
path="/dashboard/user-profile"
appearance={{
elements: {
rootBox: 'w-full',
cardBox: 'w-full flex',
},
}}
appearance={{ elements: { rootBox: 'w-full', cardBox: 'w-full flex' } }}
/>
</>
);
};
export default UserProfilePage;
}

View file

@ -0,0 +1,16 @@
import { redirect } from 'next/navigation';
import { auth as clerkAuth } from '@clerk/nextjs/server';
export default async function CenteredLayout({
children,
}: {
children: React.ReactNode;
}) {
const auth = await clerkAuth();
if (!auth.userId) {
redirect('/');
}
return children;
}

View file

@ -3,6 +3,8 @@ import '@/styles/globals.css';
import type { Metadata } from 'next';
import { NextIntlClientProvider } from 'next-intl';
import { getLocale } from 'next-intl/server';
import { enUS, frFR } from '@clerk/localizations';
import { ClerkProvider } from '@clerk/nextjs';
import { ThemeProvider } from '@/components/ThemeProvider';
@ -45,7 +47,9 @@ export default async function RootLayout({
enableSystem
disableTransitionOnChange
>
{children}
<ClerkProvider localization={locale === 'fr' ? frFR : enUS}>
{children}
</ClerkProvider>
</ThemeProvider>
</NextIntlClientProvider>
</body>

View file

@ -1,9 +1,11 @@
import { auth as clerkAuth } from '@clerk/nextjs/server';
import { getLocale, getTranslations, setRequestLocale } from 'next-intl/server';
import { Features } from '@/components/templates/Features';
import { Footer } from '@/components/templates/Footer';
import { Hero } from '@/components/templates/Hero';
import { Navbar } from '@/components/templates/Navbar';
import { redirect } from 'next/navigation';
export async function generateMetadata() {
const locale = await getLocale();
@ -15,9 +17,14 @@ export async function generateMetadata() {
};
}
const IndexPage = async () => {
const locale = await getLocale();
setRequestLocale(locale);
export default async function Page() {
const auth = await clerkAuth();
if (auth.userId) {
redirect('/dashboard');
}
setRequestLocale(await getLocale());
return (
<>
@ -27,6 +34,4 @@ const IndexPage = async () => {
<Footer />
</>
);
};
export default IndexPage;
}

View file

@ -7,6 +7,10 @@ export async function generateMetadata() {
return { title: t('meta_title'), description: t('meta_description') };
}
const SignInPage = () => <SignIn path="/sign-in" />;
export default SignInPage;
export default function Page() {
return (
<div className="flex h-screen w-full items-center justify-center">
<SignIn />
</div>
);
}

View file

@ -7,6 +7,10 @@ export async function generateMetadata() {
return { title: t('meta_title'), description: t('meta_description') };
}
const SignUpPage = () => <SignUp path="/sign-up" />;
export default SignUpPage;
export default function Page() {
return (
<div className="flex h-screen w-full items-center justify-center">
<SignUp />
</div>
);
}

View file

@ -5,6 +5,7 @@ import Link from 'next/link';
import { ActiveLink } from '@/components/ActiveLink';
import { LocaleSwitcher } from '@/components/LocaleSwitcher';
import { ThemeSwitcher } from '@/components/ThemeSwitcher';
import { ToggleMenuButton } from '@/components/ToggleMenuButton';
import {
DropdownMenu,
@ -80,6 +81,9 @@ export const DashboardHeader = (props: DashboardHeaderProps) => (
<li data-fade>
<LocaleSwitcher />
</li>
<li data-fade>
<ThemeSwitcher />
</li>
<li>
<Separator orientation="vertical" className="h-4" />
</li>

View file

@ -1,23 +0,0 @@
import React from 'react';
export const MessageState = (props: {
icon: React.ReactNode;
title: React.ReactNode;
description: React.ReactNode;
button: React.ReactNode;
}) => (
<div className="flex h-[600px] flex-col items-center justify-center rounded-md bg-card p-5">
<div className="size-16 rounded-full bg-muted p-3 [&_svg]:stroke-muted-foreground [&_svg]:stroke-2">
{props.icon}
</div>
<div className="mt-3 text-center">
<div className="text-xl font-semibold">{props.title}</div>
<div className="mt-1 text-sm font-medium text-muted-foreground">
{props.description}
</div>
<div className="mt-5">{props.button}</div>
</div>
</div>
);

View file

@ -59,10 +59,7 @@
"DashboardIndex": {
"title_bar": "Dashboard",
"title_bar_description": "Welcome to your dashboard",
"message_state_title": "Let's get started",
"message_state_description": "You can customize this page by editing the file at <code>dashboard/page.tsx</code>",
"message_state_button": "Star on GitHub",
"message_state_alternative": "Want more features using the same stack? Try <url></url>."
"message_state_title": "Let's get started"
},
"UserProfile": {
"title_bar": "User Profile",

View file

@ -59,10 +59,7 @@
"DashboardIndex": {
"title_bar": "Tableau de bord",
"title_bar_description": "Bienvenue sur votre tableau de bord",
"message_state_title": "C'est parti",
"message_state_description": "Vous pouvez personnaliser cette page en modifiant le fichier dans <code>dashboard/page.tsx</code>",
"message_state_button": "Mettez une étoile sur GitHub",
"message_state_alternative": "Vous voulez plus de fonctionnalités en utilisant la même stack ? Essayez <url></url>."
"message_state_title": "C'est parti"
},
"UserProfile": {
"title_bar": "Profil utilisateur",