diff --git a/.env.example b/.env.example index bc7ec1c..1c81e6a 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,4 @@ NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY +DEV_GOOGLE_CLIENT_ID= # Get it from Google Cloud APIs & Services pages on the Credentials tab +DEV_GOOGLE_CLIENT_SECRET= # Get it from Google Cloud APIs & Services pages on the Credentials tab \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json index bffb357..744bb73 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,8 @@ { - "extends": "next/core-web-vitals" + "extends": "next/core-web-vitals", + "plugins": ["simple-import-sort"], + "rules": { + "simple-import-sort/imports": "warn", + "simple-import-sort/exports": "warn" + } } diff --git a/.gitignore b/.gitignore index 507c4bd..8adee52 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ yarn-debug.log* yarn-error.log* # local env files +.env .env*.local # vercel diff --git a/README.md b/README.md index f4da3c4..84a9fe5 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,30 @@ +# CHOOSELIFE + This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). -## Getting Started +## Local development + +First, setup the `.env` file. See [How to setup Google oAuth](#how-to-setup-google-oauth). -First, run the development server: +Then, run the development server: ```bash -npm run dev -# or +yarn install +npx supabase start yarn dev -# or -pnpm dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. - -This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. - -## Learn More - -To learn more about Next.js, take a look at the following resources: +### How to setup Google oAuth -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +You can follow [this tutorial](https://docs.retool.com/data-sources/guides/authentication/google-oauth) to get your Google oAuth credentials. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! +For local development: -## Deploy on Vercel +- Add `http://localhost:3000` to **Authorized JavaScript origins** +- Add `http://localhost:54321/auth/v1/callback` to **Authorized redirect URIs** -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +For prod: -Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. +- Add `https://${SUPABASE_PROJECT_ID}.supabase.co/auth/v1/callback` to **Authorized redirect URIs** diff --git a/app/[locale]/Providers.tsx b/app/[locale]/Providers.tsx index c6a6e79..ae7590b 100644 --- a/app/[locale]/Providers.tsx +++ b/app/[locale]/Providers.tsx @@ -2,15 +2,16 @@ import type { ReactNode } from "react"; import { ThemeProvider } from "next-themes"; -import { type AbstractIntlMessages, NextIntlClientProvider } from "next-intl"; +import { NextIntlClientProvider, type AbstractIntlMessages } from "next-intl"; import { ReactQueryProvider } from "@/components/ReactQueryProvider"; interface Props { locale: "en" | "pt"; - messages: AbstractIntlMessages; + messages: AbstractIntlMessages | undefined; children: ReactNode; } + function Providers({ locale, messages, children }: Props) { return ( diff --git a/app/[locale]/auth/callback/route.ts b/app/[locale]/auth/callback/route.ts new file mode 100644 index 0000000..6fbcaee --- /dev/null +++ b/app/[locale]/auth/callback/route.ts @@ -0,0 +1,27 @@ +import { Database } from "@/utils/database.types"; +import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs"; +import { cookies } from "next/headers"; +import { NextResponse } from "next/server"; + +export const dynamic = "force-dynamic"; + +export async function GET(request: Request) { + // The `/auth/callback` route is required for the server-side auth flow implemented + // by the Auth Helpers package. It exchanges an auth code for the user's session. + // https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-sign-in-with-code-exchange + const requestUrl = new URL(request.url); + const code = requestUrl.searchParams.get("code"); + + if (code) { + const supabase = createRouteHandlerClient({ cookies }); + const { data, error } = await supabase.auth.exchangeCodeForSession(code); + + // Redirect to profile page so the user can update it + if (!data.user?.user_metadata.age) { + return NextResponse.redirect(requestUrl.origin + "/profile"); + } + } + + // URL to redirect to after sign in process completes + return NextResponse.redirect(requestUrl.origin); +} diff --git a/app/[locale]/layout.tsx b/app/[locale]/layout.tsx index d6d949d..da18e8c 100644 --- a/app/[locale]/layout.tsx +++ b/app/[locale]/layout.tsx @@ -1,51 +1,54 @@ import "./globals.css"; -import { Inter } from "next/font/google"; + import { Analytics } from "@vercel/analytics/react"; +import { Inter } from "next/font/google"; import { notFound } from "next/navigation"; +import { useLocale, useMessages } from "next-intl"; -import Providers from "./Providers"; import Footer from "@/components/Footer"; import NavBar from "@/components/layout/navbar"; -const inter = Inter({ subsets: ["latin"] }); +import Providers from "./Providers"; + +const inter = Inter({ + subsets: ["latin"], + display: "swap", + variable: "--font-inter", +}); export const metadata = { title: "Festival Chooselife", description: "Site oficial do festival Chooselife", }; -export function generateStaticParams() { - return [{ locale: "en" }, { locale: "pt" }]; -} - -export default async function RootLayout({ +export default function RootLayout({ children, - params: { locale }, + params, }: { children: React.ReactNode; params: { locale: "en" | "pt" }; }) { - let messages; - try { - messages = (await import(`../../messages/${locale}.json`)).default; - } catch (error) { + const locale = useLocale(); + // Show a 404 error if the user requests an unknown locale + if (params.locale !== locale) { notFound(); } + const messages = useMessages(); + return ( // suppressHydrationWarning because of `next-themes` // refer to https://github.com/pacocoursey/next-themes#with-app - <> +
{children}
- +
diff --git a/app/[locale]/login/_components/google-oauth.tsx b/app/[locale]/login/_components/google-oauth.tsx new file mode 100644 index 0000000..a233250 --- /dev/null +++ b/app/[locale]/login/_components/google-oauth.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { createClientComponentClient } from "@supabase/auth-helpers-nextjs"; + +import type { Database } from "@/utils/database.types"; + +import { GoogleIcon } from "@/assets"; +import Button from "@/components/ui/Button"; + +export default function GoogleAuthLogin() { + const supabase = createClientComponentClient(); + + async function handleSignInWithGoogle() { + await supabase.auth.signInWithOAuth({ + provider: "google", + options: { + redirectTo: `${window.location.origin}/auth/callback`, + }, + }); + } + + return ( +