safetrustcr / Frontend

Interface for a decentralized platform enabling secure and trusted P2P transactions with cryptocurrency.
https://safetrust.vercel.app/
5 stars 16 forks source link

Tenant Flow - Implement user registration flow #70

Open rvalenciano opened 2 days ago

rvalenciano commented 2 days ago

[Frontend] Tenant Flow - Implement user registration flow

Implement the tenant registration process using Firebase Auth and Hasura to store role information.

Problem

We need to:

Solution

GraphQL Operations

# After Firebase creates the user, assign tenant role
mutation AssignTenantRole($userId: String!) {
  insert_user_roles_one(object: {
    user_id: $userId,
    role_id: 2  # Assuming 2 is tenant role id
  }) {
    user_id
    role {
      name
    }
  }
}

# Create initial user record
mutation CreateUserRecord($user: users_insert_input!) {
  insert_users_one(object: $user) {
    id
    email
    last_seen
  }
}

React Implementation

// src/features/auth/TenantRegistration.tsx
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { 
  getAuth, 
  createUserWithEmailAndPassword, 
  sendEmailVerification 
} from 'firebase/auth';
import { useMutation } from '@apollo/client';
import { ASSIGN_TENANT_ROLE, CREATE_USER_RECORD } from './graphql';

export const TenantRegistration: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState<string | null>(null);
  const navigate = useNavigate();

  const [assignRole] = useMutation(ASSIGN_TENANT_ROLE);
  const [createUser] = useMutation(CREATE_USER_RECORD);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);

    try {
      // 1. Create Firebase user
      const auth = getAuth();
      const { user } = await createUserWithEmailAndPassword(
        auth,
        email,
        password
      );

      // 2. Send email verification
      await sendEmailVerification(user);

      // 3. Create user record in our database
      await createUser({
        variables: {
          user: {
            id: user.uid,
            email: user.email,
          }
        }
      });

      // 4. Assign tenant role
      await assignRole({
        variables: {
          userId: user.uid
        }
      });

      // 5. Redirect to verification page
      navigate('/verify-email');

    } catch (error) {
      setError(getErrorMessage(error));
    }
  };

  return (
    <div className="max-w-md mx-auto p-6">
      <h1 className="text-2xl font-bold mb-6">
        Register as Tenant
      </h1>

      {error && (
        <div className="bg-red-50 text-red-500 p-3 rounded mb-4">
          {error}
        </div>
      )}

      <form onSubmit={handleSubmit} className="space-y-4">
        <div>
          <label className="block mb-1">Email</label>
          <input
            type="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            className="w-full p-2 border rounded"
            required
          />
        </div>

        <div>
          <label className="block mb-1">Password</label>
          <input
            type="password"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
            className="w-full p-2 border rounded"
            minLength={6}
            required
          />
        </div>

        <button
          type="submit"
          className="w-full bg-blue-500 text-white p-2 rounded"
        >
          Register
        </button>
      </form>
    </div>
  );
};

// Helper function to parse Firebase errors
const getErrorMessage = (error: any): string => {
  switch (error.code) {
    case 'auth/email-already-in-use':
      return 'This email is already registered';
    case 'auth/invalid-email':
      return 'Invalid email address';
    case 'auth/operation-not-allowed':
      return 'Email/password accounts are not enabled';
    case 'auth/weak-password':
      return 'Password should be at least 6 characters';
    default:
      return 'An error occurred during registration';
  }
};

Email Verification Component

// src/features/auth/EmailVerification.tsx
import { useEffect, useState } from 'react';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { useNavigate } from 'react-router-dom';

export const EmailVerification: React.FC = () => {
  const [isVerified, setIsVerified] = useState(false);
  const navigate = useNavigate();

  useEffect(() => {
    const auth = getAuth();
    const unsubscribe = onAuthStateChanged(auth, async (user) => {
      if (user) {
        // Reload user to get latest email verification status
        await user.reload();
        if (user.emailVerified) {
          setIsVerified(true);
          // Wait a moment then redirect
          setTimeout(() => {
            navigate('/dashboard');
          }, 2000);
        }
      }
    });

    return () => unsubscribe();
  }, [navigate]);

  return (
    <div className="max-w-md mx-auto p-6 text-center">
      <h1 className="text-2xl font-bold mb-4">
        Verify Your Email
      </h1>

      {isVerified ? (
        <div className="text-green-500">
          Email verified! Redirecting...
        </div>
      ) : (
        <div className="space-y-4">
          <p>
            Please check your email and click the verification link.
          </p>
          <p className="text-sm text-gray-500">
            Don't see the email? Check your spam folder.
          </p>
        </div>
      )}
    </div>
  );
};

Success Flow

  1. User enters email and password
  2. Firebase creates authentication record
  3. Verification email is sent
  4. User record is created in our database
  5. Tenant role is assigned
  6. User is redirected to verification page
  7. After verification, user accesses dashboard

Error Handling

Testing Scenarios

  1. Successful registration flow
  2. Email verification flow
  3. Invalid email/password combinations
  4. Network error handling
  5. Database error handling
  6. Navigation flows
  7. Protected route access

Prerequisites

Success Criteria

Additional Notes

Related Issues

- Firebase Auth Integration

Benjtalkshow commented 1 day ago

I'd like to handle this task. I am a Full Stack Developer with a strong background in blockchain and extensive experience in Next.js/React, TypeScript, and Rust. I’ve made over 45 contributions to over 15 projects in the OnlyDust ecosystem, solving complex issues and delivering efficient, scalable solutions.

MY ETA is 48hrs. Thanks

Yunusabdul38 commented 1 day ago

I'd love to work on this issue. and make sure it meets the requirements

ShantelPeters commented 1 day ago

May I try my hand at this?

lauchaves commented 1 day ago

Hey! I'm Lau Chaves, and I would like to contribute to this issue!

I have over 5 years of experience working with JavaScript, React, and TypeScript, ruby... Im also part of Dojo Coding Costa Rica!

My primary role has been as a front-end developer, and I have a keen eye for detail and a strong focus on mobile-first approaches. I ensure the quality of my work through rigorous self- QA processes. I have a solid knowledge of CSS, Sass, and styled-components. I have worked with figma and zeplin

Feel free to check my onlydust profile here and github profile: lauchaves!

Id follow the steps mentioned in the issue, so we can register new users through Firebase, assign the 'tenant' role in the database, handle email verification and create proper onboarding flow. Id make sure I follow all the suggestions mentioned!

btw this is by far the best detailed issue I ever see haha thanks for that!

Michaelkingsdev commented 1 day ago

Is this issue still available?

System625 commented 1 day ago

Let me handle this issue! I would love to implement this I will create a draft PR 12 hours after completion

Tzienom commented 1 day ago

Hi, I'm Gabriel and I'll be working on issue #70. I am able to complete this task of registering new users and assigning the Tenant role to them. All operations shall be completed earnestly whilst ensuring that the application remains responsive across all devices.

rvalenciano commented 1 day ago

@lauchaves feel free to work on this one.