Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix updateName function #313

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Required Github OAuth environment variables for developing with a local Supabase instance
SUPABASE_AUTH_EXTERNAL_GITHUB_REDIRECT_URI="http://127.0.0.1:54321/auth/v1/callback"
SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID=
SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET=

# Optional OpenAI environment variable for generating SQL queries with Supabase AI
OPENAI_API_KEY=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ yarn-error.log*

# editors
.vscode
*.code-workspace

# certificates
certificates
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Should the automatic setup fail, please [create a Supabase account](https://app.

### Configure Auth

This template supports password signin, email magic link signin, and OAuth providers (e.g. GitHub). To control which signin types are enabled, simply toggle the boolean variables `allowPassword`, `allowEmail`, and `allowOAuth` in the `utils/auth-helpers/settings.ts` file.

Follow [this guide](https://supabase.com/docs/guides/auth/social-login/auth-github) to set up an OAuth app with GitHub and configure Supabase to use it as an auth provider.

In your Supabase project, navigate to [auth > URL configuration](https://app.supabase.com/project/_/auth/url-configuration) and set your main production URL (e.g. https://your-deployment-url.vercel.app) as the site url.
Expand Down Expand Up @@ -95,7 +97,7 @@ For example, you can create business models with different pricing tiers, e.g.:
- Price 1: 20 USD per month
- Price 2: 200 USD per year

Optionally, to speed up the setup, we have added a [fixtures file](fixtures/stripe-fixtures.json) to bootstrap test product and pricing data in your Stripe account. The [Stripe CLI](https://stripe.com/docs/stripe-cli#install) `fixtures` command executes a series of API requests defined in this JSON file. Simply run `stripe fixtures fixtures/stripe-fixtures.json`.
Optionally, to speed up the setup, we have added a [fixtures file](fixtures/stripe-fixtures.json) to bootstrap test product and pricing data in your Stripe account. The [Stripe CLI](https://stripe.com/docs/stripe-cli#install) `fixtures` command executes a series of API requests defined in this JSON file. Simply run `stripe fixtures fixtures/stripe-fixtures.json`. (Note the use of a numerical index in the product metadata to control display sequence in the UI).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

omg thank you for this note! You just helped me figure out how to sequence my products!


**Important:** Make sure that you've configured your Stripe webhook correctly and redeployed with all needed environment variables.

Expand Down Expand Up @@ -146,20 +148,19 @@ Running this command will create a new `.env.local` file in your project folder.

It's highly recommended to use a local Supabase instance for development and testing. We have provided a set of custom commands for this in `package.json`.

First, you will need to install [Docker](https://www.docker.com/get-started/). You should also copy or rename:
First, you will need to install [Docker](https://www.docker.com/get-started/). You must also copy or rename the `.env.example` file to `.env` and populate it with the required environment variables, or setup of your local Supabase instance will fail.

- `.env.local.example` -> `.env.local`
- `.env.example` -> `.env`
Follow the instructions [here](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/creating-an-oauth-app) to create a Github OAuth app. When you create the app, set the homepage URL to 'http://localhost:3000/' and the authorization callback URL to 'http://localhost:54321/auth/v1/callback'. Github will provide you Client ID and secret for your OAuth app, which you should copy and paste into `.env`. Remember never to commit your `.env` file to version control!

Next, run the following command to start a local Supabase instance and run the migrations to set up the database schema:
Next, run the following command to start a local Supabase instance and to run the migrations to set up the database schema:

```bash
pnpm supabase:start
```

The terminal output will provide you with URLs to access the different services within the Supabase stack. The Supabase Studio is where you can make changes to your local database instance.

Copy the value for the `service_role_key` and paste it as the value for the `SUPABASE_SERVICE_ROLE_KEY` in your `.env.local` file.
If you haven't done so already, you'll need to copy or rename the `.env.local.example` file to `.env.local`. Then copy the value for the `service_role_key` and paste it as the value for the `SUPABASE_SERVICE_ROLE_KEY` in your `.env.local` file.

You can print out these URLs at any time with the following command:

Expand Down Expand Up @@ -210,7 +211,9 @@ And push those changes to your remote database with:
pnpm supabase:push
```

Remember to test your changes thoroughly in your `local` and `staging` or `preview` environments before deploying them to `production`!
Remember to test your changes thoroughly in your `local` and `staging` or `preview` environments before deploying them to `production`.

Note that to add more OAuth providers, you will need to add new secrets to `.env` and then configure the `[auth.external.github]` section of `supabase/config.toml` to look for the new environment variables. See the Supabase docs on [managing config and secrets](https://supabase.com/docs/guides/cli/managing-config) and [CLI configuration](https://supabase.com/docs/guides/cli/config) for more information on configuring your local Supabase instance.

### Use the Stripe CLI to test webhooks

Expand Down
2 changes: 1 addition & 1 deletion app/account/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default async function Account() {
</div>
<div className="p-4">
<CustomerPortalForm subscription={subscription} />
<NameForm userName={userDetails?.full_name ?? ''} />
<NameForm userName={userDetails?.full_name ?? ''} userId={user?.id} />
<EmailForm userEmail={user.email} />
</div>
</section>
Expand Down
4 changes: 2 additions & 2 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Metadata } from 'next';
import Footer from '@/components/ui/Footer';
import Navbar from '@/components/ui/Navbar';
import Header from '@/components/ui/Header';
import { Toaster } from '@/components/ui/Toasts/toaster';
import { PropsWithChildren, Suspense } from 'react';
import { getURL } from '@/utils/helpers';
Expand Down Expand Up @@ -50,7 +50,7 @@ export default async function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body className="bg-black loading">
<Navbar />
<Header />
<main
id="skip"
className="min-h-[calc(100dvh-4rem)] md:min-h[calc(100dvh-5rem)]"
Expand Down
7 changes: 6 additions & 1 deletion components/ui/AccountForms/NameForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { handleRequest } from '@/utils/auth-helpers/client';
import { useRouter } from 'next/navigation';
import { useState } from 'react';

export default function NameForm({ userName }: { userName: string }) {
export default function NameForm({ userName, userId }: { userName: string, userId: string}) {
const router = useRouter();
const [isSubmitting, setIsSubmitting] = useState(false);

Expand Down Expand Up @@ -43,6 +43,11 @@ export default function NameForm({ userName }: { userName: string }) {
>
<div className="mt-8 mb-4 text-xl font-semibold">
<form id="nameForm" onSubmit={(e) => handleSubmit(e)}>
<input
type="hidden"
name="userId"
value={userId}
/>
<input
type="text"
name="fullName"
Expand Down
12 changes: 11 additions & 1 deletion components/ui/AuthForms/OauthSignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { signInWithOAuth } from '@/utils/auth-helpers/client';
import { type Provider } from '@supabase/supabase-js';
import { Github } from 'lucide-react';
import { useState } from 'react';
import { getErrorRedirect } from '@/utils/helpers';
import { useRouter } from 'next/navigation';

type OAuthProviders = {
name: Provider;
Expand All @@ -13,6 +15,7 @@ type OAuthProviders = {
};

export default function OauthSignIn() {
const router = useRouter();
const oAuthProviders: OAuthProviders[] = [
{
name: 'github',
Expand All @@ -25,7 +28,14 @@ export default function OauthSignIn() {

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
setIsSubmitting(true); // Disable the button while the request is being handled
await signInWithOAuth(e);
try{
await signInWithOAuth(e);
} catch (error) {
return router.push(getErrorRedirect(
`/`,
"Sorry, we weren't able to log you in. Please try again."
));
}
setIsSubmitting(false);
};

Expand Down
16 changes: 16 additions & 0 deletions components/ui/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use server';

import { createClient } from '@/utils/supabase/server';
import Navbar from './Navbar';

export default async function Header() {
const supabase = createClient();

const {
data: { user }
} = await supabase.auth.getUser();

return (
<Navbar user={user} />
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
.root {
@apply sticky top-0 bg-black z-40 transition-all duration-150 h-16 md:h-20;
@apply sticky top-0 bg-black z-40 transition-all duration-150 h-20;
}

.dropdownMenu {
@apply w-full text-xl bg-black border-t border-b border-white flex flex-col items-start lg:hidden;
}

.dropdownMenu > a, .dropdownMenu > form {
@apply w-full px-6 py-6 border-b border-zinc-400;
border-radius: 0;
}

.dropdownMenu > a:last-child, .dropdownMenu > form:last-child {
border-bottom: none;
}

.link {
Expand All @@ -12,8 +25,4 @@

.link:focus {
@apply outline-none text-zinc-100 ring-2 ring-pink-500 ring-opacity-50;
}

.logo {
@apply cursor-pointer rounded-full transform duration-100 ease-in-out;
}
}
93 changes: 93 additions & 0 deletions components/ui/Header/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
'use client';

import { useState, useEffect } from 'react';
import Hamburger from 'hamburger-react';
import Link from 'next/link';
import SignInOutLink from './SignInOutLink';
import Logo from '@/components/icons/Logo';
import s from './Navbar.module.css';
import { User } from '@supabase/supabase-js';

interface NavbarProps {
user: User | null;
}

export default function Navbar({user}: NavbarProps) {
const [isOpen, setOpen] = useState(false);

useEffect(() => {
const handleClickOutside = (event: MouseEvent | TouchEvent) => {
let path = event.composedPath ? event.composedPath() : [];
const hamburgerElement = document.querySelector(".hamburger-react");

if (hamburgerElement && path.includes(hamburgerElement)) {
return; // Click was inside the Hamburger, so do nothing
}

const dropdown = document.querySelector(`.${s.dropdownMenu}`) as HTMLElement;
if (dropdown && !dropdown.contains(event.target as Node) && isOpen) {
setOpen(false);
}
};

// Listen for mouse and touch events
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('touchstart', handleClickOutside);

return () => {
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('touchstart', handleClickOutside);
};
}, [isOpen]);

return (
<nav className={s.root}>
<a href="#skip" className="sr-only focus:not-sr-only">
Skip to content
</a>
<div className="max-w-6xl px-6 mx-auto">
<div className="relative flex flex-row justify-between py-4 align-center md:py-6">
<div className="flex items-center flex-1">
<Link href="/" className={s.logo} aria-label="Logo">
<Logo />
</Link>
<div className="hidden ml-6 space-x-2 lg:block">
<Link href="/" className={s.link}>
Pricing
</Link>
{user && (
<Link href="/account" className={s.link}>
Account
</Link>
)}
</div>
<div className="hidden lg:flex justify-end flex-1 space-x-8">
<SignInOutLink user={user} />
</div>
</div>
<div className="flex justify-end flex-1 lg:hidden">
<Hamburger
size={24}
color="#fff"
toggled={isOpen}
toggle={setOpen}
/>
</div>
</div>
</div>
{isOpen && (
<div className={s.dropdownMenu}>
<Link href="/" className={s.link}>
Pricing
</Link>
{user && (
<Link href="/account" className={s.link}>
Account
</Link>
)}
<SignInOutLink user={user} />
</div>
)}
</nav>
);
};
29 changes: 29 additions & 0 deletions components/ui/Header/SignInOutLink.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client';

import { usePathname, useRouter } from 'next/navigation';
import { SignOut } from '@/utils/auth-helpers/server';
import { handleRequest } from '@/utils/auth-helpers/client';
import s from './Navbar.module.css';
import Link from 'next/link';
import { User } from '@supabase/supabase-js';

interface SignInOutLinkProps {
user?: User | null;
}

export default function SignInOutLink({ user }: SignInOutLinkProps) {
const router = useRouter();

return user ? (
<form onSubmit={(e) => handleRequest(e, SignOut, router)}>
<input type="hidden" name="pathName" value={usePathname()} />
<button type="submit" className={s.link}>
Sign out
</button>
</form>
) : (
<Link href="/signin" className={s.link}>
Sign In
</Link>
);
};
1 change: 1 addition & 0 deletions components/ui/Header/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Header';
22 changes: 0 additions & 22 deletions components/ui/Navbar/Navbar.tsx

This file was deleted.

Loading