Routing Problem from sign in page to a users account

The Issues is routing a user after creating an account on the webapp platform to the users dashboard created for the user.

I can provide with the sign in and authcontext.js page which helps with this.

signin.js

import React, { useState, useEffect } from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../../../contexts/AuthContext';
import './Login.css';

const Login = () => {
  const [formData, setFormData] = useState({
    email: '',
    password: ''
  });
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);
  const { login, isAuthenticated } = useAuth();
  const navigate = useNavigate();
  const location = useLocation();

  // Redirect if already logged in
  useEffect(() => {
    if (isAuthenticated) {
      const from = location.state?.from?.pathname || '/';
      navigate(from, { replace: true });
    }
  }, [isAuthenticated, navigate, location]);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormData(prev => ({
      ...prev,
      [name]: value
    }));
    // Clear error when user starts typing
    if (error) setError('');
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError('');
    setLoading(true);
    
    try {
      const { email, password } = formData;
      const result = await login(email, password);
      
      if (result.success) {
        // Redirect to the dashboard or previous page
        const from = location.state?.from?.pathname || '/dashboard';
        navigate(from, { replace: true });
      } else {
        setError(result.error || 'Login failed. Please try again.');
      }
    } catch (err) {
      console.error('Login error:', err);
      setError('An unexpected error occurred. Please try again.');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="auth-page">
      <nav className="navbar">
        <div className="container">
          <div className="logo">EnergyAI</div>
          <div className="nav-links">
            <Link to="/">Home</Link>
            <Link to="/features">Features</Link>
            <Link to="/contact">Contact</Link>
            <div className="auth-buttons">
              <Link to="/login" className="btn btn-outline active">Sign In</Link>
              <Link to="/register" className="btn btn-primary">Sign Up</Link>
            </div>
          </div>
        </div>
      </nav>

      <div className="auth-container">
        <div className="auth-card">
          <div className="auth-header">
            <h1>Welcome Back</h1>
            <p>Sign in to your EnergyAI account</p>
          </div>

          {error && (
            <div className="alert alert-error">
              {error}
            </div>
          )}
          
          <form onSubmit={handleSubmit} className="auth-form">
            <div className="form-group">
              <label>Email Address</label>
              <input 
                type="email" 
                name="email" 
                value={formData.email}
                onChange={handleChange}
                placeholder="Enter your email"
                required
                disabled={loading}
              />
            </div>

            <div className="form-group">
              <div className="form-label-row">
                <label>Password</label>
                <Link to="/forgot-password" className="forgot-password">
                  Forgot password?
                </Link>
              </div>
              <input 
                type="password" 
                name="password" 
                value={formData.password}
                onChange={handleChange}
                placeholder="••••••••"
                required
                disabled={loading}
              />
            </div>

            <div className="form-options">
              <label className="checkbox-container">
                <input 
                  type="checkbox" 
                  disabled={loading}
                />
                <span className="checkmark"></span>
                Remember me
              </label>
            </div>

            <button 
              type="submit" 
              className="btn btn-primary btn-block"
              disabled={loading}
            >
              {loading ? (
                <>
                  <span className="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
                  Signing in...
                </>
              ) : 'Sign In'}
            </button>

            <div className="auth-footer">
              <p>Don't have an account? <Link to="/register">Sign up</Link></p>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

export default Login;

authcontext.js

import { createContext, useContext, useState, useEffect } from 'react';
import axios from 'axios';

const ROLES = {
  ADMIN: 'admin',
  ENERGY_MANAGER: 'energy_manager',
  FACILITY_MANAGER: 'facility_manager',
  IT_ADMIN: 'it_admin',
  VIEWER: 'viewer'
};

const PERMISSIONS = {
  VIEW_DASHBOARD: 'view_dashboard',
  MANAGE_ENERGY: 'manage_energy',
  CONFIGURE_SYSTEM: 'configure_system',
  MANAGE_USERS: 'manage_users',
  VIEW_REPORTS: 'view_reports',
  GENERATE_REPORTS: 'generate_reports'
};

const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [token, setToken] = useState(localStorage.getItem('token'));
  const [loading, setLoading] = useState(true);
  const [permissions, setPermissions] = useState([]);

  // Set axios default headers
  useEffect(() => {
    if (token) {
      axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
      localStorage.setItem('token', token);
    } else {
      delete axios.defaults.headers.common['Authorization'];
      localStorage.removeItem('token');
    }
  }, [token]);

  // Load user data on mount and when token changes
  useEffect(() => {
    let isMounted = true;
    const source = axios.CancelToken.source();

    const loadUser = async () => {
      if (!token) {
        setLoading(false);
        return;
      }

      // Skip if we already have user data
      if (user && user.id) {
        setLoading(false);
        return;
      }

      try {
        console.log('Loading user profile...');
        const response = await axios.get('/api/auth/profile/', {
          cancelToken: source.token,
          headers: {
            'Authorization': `Bearer ${token}`,
            'Accept': 'application/json'
          }
        });
        
        console.log('User profile loaded:', response.data);
        
        if (isMounted && response.data) {
          setUser(response.data);
          setPermissions(getPermissionsForRole(response.data.role || 'viewer'));
        }
      } catch (error) {
        if (axios.isCancel(error)) {
          console.log('Profile request canceled:', error.message);
        } else {
          console.error('Failed to load user profile:', error);
          
          // Log detailed error info
          if (error.response) {
            console.error('Response status:', error.response.status);
            console.error('Response data:', error.response.data);
            console.error('Response headers:', error.response.headers);
          } else if (error.request) {
            console.error('No response received:', error.request);
          } else {
            console.error('Error setting up request:', error.message);
          }
          
          // If token is invalid (401) or other auth error, clear it
          if (isMounted && (!error.response || error.response.status === 401)) {
            console.log('Clearing invalid token');
            setToken(null);
            setUser(null);
            localStorage.removeItem('token');
          }
        }
      } finally {
        if (isMounted) {
          setLoading(false);
        }
      }
    };

    // Only load user if we have a token
    if (token) {
      loadUser();
    } else {
      setLoading(false);
    }

    return () => {
      isMounted = false;
      source.cancel('Operation canceled by component unmount.');
    };
  }, [token]);

  // Helper function to get permissions for a role
  const getPermissionsForRole = (role) => {
    const rolePermissions = {
      [ROLES.ADMIN]: Object.values(PERMISSIONS),
      [ROLES.ENERGY_MANAGER]: [
        PERMISSIONS.VIEW_DASHBOARD,
        PERMISSIONS.MANAGE_ENERGY,
        PERMISSIONS.VIEW_REPORTS,
        PERMISSIONS.GENERATE_REPORTS
      ],
      [ROLES.FACILITY_MANAGER]: [
        PERMISSIONS.VIEW_DASHBOARD,
        PERMISSIONS.VIEW_REPORTS
      ],
      [ROLES.IT_ADMIN]: [
        PERMISSIONS.VIEW_DASHBOARD,
        PERMISSIONS.CONFIGURE_SYSTEM
      ],
      [ROLES.VIEWER]: [
        PERMISSIONS.VIEW_DASHBOARD,
        PERMISSIONS.VIEW_REPORTS
      ]
    };
    return rolePermissions[role] || [];
  };

  // Check if user has a specific permission
  const hasPermission = (permission) => {
    return permissions.includes(permission);
  };

  // Check if user has any of the given permissions
  const hasAnyPermission = (requiredPermissions) => {
    return requiredPermissions.some(permission => 
      permissions.includes(permission)
    );
  };

  // Check if user has all of the given permissions
  const hasAllPermissions = (requiredPermissions) => {
    return requiredPermissions.every(permission => 
      permissions.includes(permission)
    );
  };

  // Login function
  const login = async (email, password) => {
    // Prevent multiple login attempts
    if (loading) {
      return { 
        success: false, 
        error: 'Login in progress. Please wait...' 
      };
    }

    setLoading(true);
    
    try {
      console.log('Attempting login with email:', email);
      const response = await axios.post('/api/auth/login/', { 
        email: email.trim(), 
        password: password
      }, {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        },
        withCredentials: true
      });
      
      console.log('Login response received:', response.data);
      
      const { access, refresh, user: userData } = response.data;
      
      if (!access) {
        throw new Error('No access token received in login response');
      }
      
      console.log('Login successful, access token received');
      
      // Set the auth token for future requests
      const authHeader = `Bearer ${access}`;
      axios.defaults.headers.common['Authorization'] = authHeader;
      
      // Store tokens first
      localStorage.setItem('token', access);
      if (refresh) {
        localStorage.setItem('refresh_token', refresh);
      }
      
      // If we have user data in the response, use it
      if (userData) {
        console.log('Using user data from login response');
        setUser(userData);
        setPermissions(getPermissionsForRole(userData.role || 'viewer'));
      } else {
        console.log('No user data in login response, will load profile separately');
        // The profile will be loaded by the useEffect that watches the token
      }
      
      // Set the token last to trigger the profile load
      setToken(access);
      
      return { 
        success: true,
        user: userData
      };
      
    } catch (error) {
      console.error('Login failed:', error);
      
      // Clear any invalid tokens
      localStorage.removeItem('token');
      localStorage.removeItem('refresh_token');
      delete axios.defaults.headers.common['Authorization'];
      
      let errorMessage = 'Login failed. Please check your credentials and try again.';
      
      if (error.response) {
        console.error('Login error response:', {
          status: error.response.status,
          statusText: error.response.statusText,
          data: error.response.data,
          headers: error.response.headers
        });
        
        // Handle different error statuses
        if (error.response.status === 400) {
          errorMessage = 'Invalid request. Please check your input.';
        } else if (error.response.status === 401) {
          errorMessage = 'Invalid email or password. Please try again.';
        } else if (error.response.status === 403) {
          errorMessage = 'Access denied. Please contact support.';
        } else if (error.response.status >= 500) {
          errorMessage = 'Server error. Please try again later.';
        }
        
        // Use server-provided error message if available
        if (error.response.data?.detail) {
          errorMessage = error.response.data.detail;
        } else if (error.response.data?.message) {
          errorMessage = error.response.data.message;
        } else if (typeof error.response.data === 'string') {
          errorMessage = error.response.data;
        }
        
      } else if (error.request) {
        console.error('No response received from server:', error.request);
        errorMessage = 'No response from server. Please check your internet connection.';
      } else {
        console.error('Error setting up login request:', error.message);
        errorMessage = `Login failed: ${error.message}`;
      }
      
      return { 
        success: false, 
        error: errorMessage,
        status: error.response?.status
      };
      
    } finally {
      setLoading(false);
    }
  };

  // Register function
  const register = async (userData) => {
    try {
      // Create a new axios instance without the auth header for registration
      const registrationAxios = axios.create();
      
      console.log('Sending registration data:', userData);
      
      // Make the registration request
      const response = await registrationAxios.post('/api/auth/register/', userData);
      
      // If we get a 201 status, registration was successful
      if (response.status === 201) {
        console.log('Registration successful, response:', response.data);
        
        // If the response includes tokens and user data, use them directly
        if (response.data.tokens && response.data.user) {
          const { tokens, user } = response.data;
          
          // Set the auth token for future requests
          axios.defaults.headers.common['Authorization'] = `Bearer ${tokens.access}`;
          
          // Update auth state
          setToken(tokens.access);
          setUser(user);
          setPermissions(getPermissionsForRole(user.role || 'viewer'));
          
          // Store tokens in local storage
          localStorage.setItem('token', tokens.access);
          if (tokens.refresh) {
            localStorage.setItem('refresh_token', tokens.refresh);
          }
          
          return { 
            success: true,
            tokens,
            user,
            autoLoggedIn: true
          };
        }
        
        // If no tokens in response, try to log in the user automatically
        try {
          console.log('No tokens in response, attempting auto-login...');
          const loginResponse = await axios.post('/api/auth/login/', {
            email: userData.email,
            password: userData.password
          });
          
          if (loginResponse.data.token && loginResponse.data.user) {
            const { token, user } = loginResponse.data;
            
            // Update auth state
            setToken(token);
            setUser(user);
            setPermissions(getPermissionsForRole(user.role || 'viewer'));
            
            // Store token in local storage
            localStorage.setItem('token', token);
            
            return { 
              success: true,
              tokens: { access: token },
              user,
              autoLoggedIn: true
            };
          }
        } catch (loginError) {
          console.error('Auto-login after registration failed:', loginError);
          // Continue with normal flow - user will need to log in manually
        }
        
        // If auto-login fails, return success but indicate manual login is needed
        return { 
          success: true,
          autoLoggedIn: false
        };
      }
      
      // Handle other success cases if needed
      if (response.data) {
        console.log('Registration successful, but unexpected response format:', response.data);
        return { 
          success: true,
          ...response.data,
          autoLoggedIn: false
        };
      }
      
      // If we get here, the response didn't contain the expected data
      console.error('Unexpected registration response:', response);
      return {
        success: false,
        error: 'Invalid response from server. Please try again.'
      };
      
    } catch (error) {
      console.error('Registration failed:', {
        message: error.message,
        response: error.response?.data,
        status: error.response?.status
      });
      
      // Extract error details from the response if available
      let errorMessage = 'Registration failed. Please try again.';
      let errorDetails = {};
      const errorData = error.response?.data;
      
      if (errorData) {
        // Handle Django REST framework validation errors
        if (typeof errorData === 'object') {
          // Handle specific field errors
          if (errorData.details) {
            // Handle our custom error format
            errorMessage = errorData.error || errorMessage;
            errorDetails = errorData.details;
          } else if (errorData.error) {
            // Handle error object format
            errorMessage = errorData.error;
            if (errorData.message) {
              errorMessage += `: ${errorData.message}`;
            }
            errorDetails = errorData;
          } else {
            // Handle field validation errors
            const errorMessages = [];
            
            for (const [field, messages] of Object.entries(errorData)) {
              if (Array.isArray(messages)) {
                errorMessages.push(...messages);
                errorDetails[field] = messages;
              } else if (typeof messages === 'string') {
                errorMessages.push(messages);
                errorDetails[field] = [messages];
              } else if (typeof messages === 'object') {
                const flatMessages = Object.values(messages).flat();
                errorMessages.push(...flatMessages);
                errorDetails[field] = flatMessages;
              }
            }
            
            errorMessage = errorMessages.join(' ');
          }
        } else if (typeof errorData === 'string') {
          errorMessage = errorData;
        }
      }
      
      // Return the error message for display in the UI
      return { 
        success: false, 
        error: errorMessage,
        errorDetails: error.response?.data,
        autoLoggedIn: false
      };
    }
  };

  // Logout function
  const logout = () => {
    setToken(null);
    setUser(null);
    setPermissions([]);
    localStorage.removeItem('token');
  };

  // Value to be provided by context
  const value = {
    user,
    token,
    loading,
    permissions,
    login,
    register,
    logout,
    hasPermission,
    hasAnyPermission,
    hasAllPermissions,
    ROLES,
    PERMISSIONS
  };

  return (
    <AuthContext.Provider value={value}>
      {!loading && children}
    </AuthContext.Provider>
  );
};

// Custom hook to use the auth context
export const useAuth = () => {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
};

export default AuthContext;

please what might be the cause of this error it's just registering on my browser dev console showing the credentials I used for registering the user account and this response on my server terminal

HTTP GET /api/auth/profile/ 200 [0.08, 127.0.0.1:57736]

I tried changing the token hoping it would help with the redirection issues but whenever I do that it affects the signin.js page making it turn to a white screen page i.e. intended form to sign-in is not visible to users just a white screen.

Back to Top