Skip to content

Conversation

@YousraElmag
Copy link
Collaborator

@YousraElmag YousraElmag commented Jun 6, 2025

Added pages for:

  • Login
  • Register
  • Forgot Password
  • Reset Password
  • OAuth callback handler
  • Integrated Supabase client with environment variables.
  • Created custom hooks for form handling (e.g., useRegister, useForgotPassword).
    ++++++++++++++++++++++++++++++++++++
    Added RoleSelection component:
  • This component allows the user to select their role after signing in (e.g., via Google OAuth).
  • The user can choose between "client" or "service provider" roles using radio buttons.
    -Upon submission, the selected role is saved to the user's metadata in Supabase using updateUser.
  • After successfully saving the role, the user is redirected to the homepage.

@Nimasaghi-dev Nimasaghi-dev self-requested a review June 7, 2025 11:03
Copy link
Collaborator

@Muatasim-Aswad Muatasim-Aswad left a comment

Choose a reason for hiding this comment

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

Thank you for the great work @YousraElmag. I left some comments and questions and maybe you can explain to us the whole flow in the meeting. Here are more general comments:

  • instead of using supabase directly in the pages, it's better to make an authService, so it become for example like this:
//resetPassword page
...
const {error} = await authService.resetPassowrd(email, "auth/resetpassword");
...
//services/authService/authService.ts
export default {
  resetPassword: (email, route) => {
    supabase.auth.resetPasswordForEmail(email, {
      redirectTo: `${baseUrl}/${route}`,
    });
  }
  login: ...

here it's easier to mock the auth in tests, or to change something in the auth service

  • Also as a suggestion we can use react-hook-form for better form management.

  • Final question about security: our pages are "use client" and we use supabase within them, doesn't this expose its credentials?

package.json Outdated
],
"dependencies": {
"@supabase/auth-helpers-nextjs": "^0.10.0",
"@supabase/auth-helpers-react": "^0.5.0"
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you have a specific reason for placing those in the parent package? Otherwise, they should be moved to web/package.json

export default function Home() {
return (
<main className="min-h-screen bg-gray-50 flex flex-col items-center justify-center p-8">
<RegisterForm />
Copy link
Collaborator

Choose a reason for hiding this comment

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

This page is the first thing rendered on the website. To organize the landing page files we have them in a hidden directory _landing/page.tsx and mapped it to here.

So I think this page should stay as it's (unmodified) and you can add temporary buttons in the _landing/page.tsx that leads to the login/register pages.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I forgot to update that.
I just changed page.tsx quickly to test my stuff since the landing page isn’t ready yet.
I’ll move everything to _landing/page.tsx soon, no worries!

import { useRouter } from "next/navigation";
import { supabase } from "@/lib/supabase/client";

export default function RoleSelection() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the design we made the role selection part of the register page and not an independent one to make the flow easier for the user (the user doesn't have to deal with a whole page just to select the role).

You can change this into a special component in the register page.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In my current form, when users register normally, they select their role directly.
But when signing up with Google, the role doesn’t get saved in the metadata automatically, that’s why I made a separate role selection page.
If you have any other suggestions or better ways to handle role assignment for Google sign-up, I’d love to hear them!

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh! I didn't see that. Here is some suggestions.

  • before the user clicks in the google button, role must be selected in the normal register form.
  • since we need the role info later we can store it temporarily until we finish the auth using one of these methods:
    in the client (e.g. local storage), or in the server (harder and complicate things), or in the url param of the callback (easy). Claude 4 suggested the following: state url param as a standard part of the oauth flow:
//register page
const stateData = {
  userType: userType
}
    
// Encode state as Base64 string
const state = btoa(JSON.stringify(stateData))

await supabase.auth.signInWithOAuth({
  provider: 'google',
  options: {
    redirectTo: `${window.location.origin}/auth/callback`,
    queryParams: {
      state: state // OAuth standard parameter
    }
  }
})
    
//callback after oauth
const stateData = JSON.parse(atob(state))
const userType = stateData.userType

const [message, setMessage] = useState("");
const router = useRouter();

useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice that you added a reset-password. I think we forgot it in the design. However I didn't understand why do we have to open a session here. Could you please explain it to me?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In the reset password page, the link sent to the user’s email contains tokens (access_token and refresh_token) in the URL hash. We use these tokens to open a temporary session with supabase.auth.setSession so the user can change their password without logging in again.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thank you for the explanation. I thought the reset password is done by passing the token with the new password.

className="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[#1a8cff] focus:border-transparent"
/>
</div>
<div>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Usually I prefer to separate components so it's easier to reuse and manage. Example: a component called <EmailField /> with its validation can be reused in (login page - register page - reset password page - edit profile page)

export default function AuthCallback() {
const router = useRouter();

useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you explain to me what is happening in this page?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This page checks if the user is signed in after Google login.
If the user has no role, it sends them to choose one.
If signed in with a role, it sends them to the home page (dashboard).
If not signed in, it sends them back to login.
After we finish building the dashboard pages, we will redirect the user to their dashboard instead of the login page.

Copy link
Collaborator

@Muatasim-Aswad Muatasim-Aswad Jun 10, 2025

Choose a reason for hiding this comment

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

Thanks for the explanation.

You can make a placeholder pages with only one text e.g. "Dashboard for Client" , "Dashboard for Provider"

also if the user is new instead of going to the dashboard we can send them to the profile page to complete the information. and maybe we can have in supabase a field (isOnboarded?) to decide this

@YousraElmag
Copy link
Collaborator Author

Thanks a lot for your feedback!

You're totally right — using an authService makes the code cleaner and easier to test. I’ll refactor that part soon.
I also agree that react-hook-form is a better choice for handling forms, and I’ll start using it in the next updates.
About using Supabase on the client side — yes, we're only exposing the anon key, which is designed for public use. We also have RLS enabled on all tables to keep the data secure

@YousraElmag YousraElmag reopened this Jun 13, 2025
@YousraElmag
Copy link
Collaborator Author

Changes in Authentication Code:
Moved all Supabase calls to a new file called authServices to keep the code clean.
Changed how user roles are set so it works without needing a new page.
Made login and role setup easier and better.

@YousraElmag
Copy link
Collaborator Author

What I Did:

  • Styled the Register and Login forms using Tailwind CSS
  • Structured layout with proper spacing and alignment
  • Updated shared components like Logo and BackButton for styling consistency
Screenshot 2025-06-15 at 22 33 00 Screenshot 2025-06-15 at 22 33 09

Muatasim-Aswad
Muatasim-Aswad previously approved these changes Aug 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants