Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Jay-byte389/AMS/llms.txt

Use this file to discover all available pages before exploring further.

AMS uses a fully local authentication system — there is no remote auth server. All user accounts are stored in device memory via React Native’s AsyncStorage, and sessions are persisted using the @logged_in_user key. Authentication state is managed globally through Redux Toolkit, exposing loading indicators and error messages to every screen.

Auth Flow

1

Register Screen

The app launches to the RegisterScreen (route name Register), which presents two buttons: Log In and Sign Up. This is the entry point of the AuthNavigator.
2

Sign Up

Tapping Sign Up navigates to SignUpScreen (route SignUp). The user fills in five fields — Full Name, Password, Email, Mobile Number, and Date of Birth — and submits. On success the signupUser thunk saves the account to @registered_users in AsyncStorage and also writes a session to @logged_in_user, then the screen navigates to Login.
3

Set Password (Forgot Password)

From LoginScreen the user can tap Forgot Password to reach the SetPassword screen (route SetPassword). They enter a new password and confirm it; updatePassword updates the stored record. On success the app navigates back to Login.
4

Login

LoginScreen (route Login) accepts an email or mobile number plus a password. The validateUser storage function looks up the record in @registered_users, compares credentials, and — if successful — calls saveLoggedInUser to write the session object to @logged_in_user. The user is then navigated to BottomTabs.
5

Session Check on Launch

Each time the app starts, the checkAuthSession thunk runs and reads @logged_in_user. If the key exists the Redux state is set to isAuthenticated: true and the user skips the auth stack entirely.

Registration

The SignUpScreen collects the following fields and dispatches signupUser:
const userData = {
  fullName,   // string — user's full name
  email,      // string — used as the login identifier
  password,   // string — stored as-is (see note below)
  mobile,     // string — alternative login identifier
  dob,        // string — "DD / MM / YYYY"
  createdAt: new Date().toISOString(),
};

dispatch(signupUser(userData));
Internally, signupUser calls two storage functions in sequence:
// src/services/storage.js
export const saveUser = async (userData) => {
  const existingUsers = await getAllUsers(); // reads @registered_users
  existingUsers.push(userData);
  await AsyncStorage.setItem(USERS_KEY, JSON.stringify(existingUsers));
  return { success: true };
};

export const saveLoggedInUser = async (userData) => {
  await AsyncStorage.setItem(SESSION_KEY, JSON.stringify(userData));
  return { success: true };
};

Login

LoginScreen validates the user directly (without Redux) by calling validateUser and saveLoggedInUser from src/services/storage.js:
const OnLoginPress = async () => {
  const result = await validateUser(email, password);
  if (result.success) {
    await saveLoggedInUser(result.user);
    navigation.replace('BottomTabs');
  }
};
The validateUser function in src/services/storage.js looks up the user by email or mobile and compares the plain-text password:
export const validateUser = async (emailOrPhone, password) => {
  const user = await getUser(emailOrPhone); // searches @registered_users
  if (!user) return { success: false, error: 'User not found. Please sign up first.' };
  if (user.password !== password) return { success: false, error: 'Incorrect password.' };
  return { success: true, user };
};
Alternatively the loginUser thunk wraps the same logic for Redux-driven flows:
// src/redux/thunk/authThunk.js
export const loginUser = createAsyncThunk(
  'auth/loginuser',
  async ({ emailOrPhone, password }, { rejectWithValue }) => {
    const result = await validateUser(emailOrPhone, password);
    if (!result.success) return rejectWithValue(result.error);
    await saveLoggedInUser(result.user);
    return result.user;
  }
);

Session Persistence

On every app launch, checkAuthSession restores the session from AsyncStorage:
// src/redux/thunk/authThunk.js
export const checkAuthSession = createAsyncThunk(
  'auth/checkAuthSession',
  async (_, { rejectWithValue }) => {
    const user = await getLoggedInUser(); // reads @logged_in_user
    return user; // null if not logged in
  }
);
The getLoggedInUser storage helper reads the @logged_in_user key and returns the parsed user object or null.

Logout

Logout dispatches the logoutUser thunk, which removes the @logged_in_user key from AsyncStorage and resets Redux state to isAuthenticated: false:
// src/redux/thunk/authThunk.js
export const logoutUser = createAsyncThunk(
  'auth/logoutUser',
  async (_, { rejectWithValue }) => {
    const result = await logoutUserStorage(); // removes @logged_in_user
    return true;
  }
);
After dispatching, ProfileMenuList calls navigation.replace('Auth', { screen: 'Login' }) to return the user to the auth stack.

Redux Auth State

The authSlice (src/redux/slices/authSlice.js) exposes the following state shape:
{
  user: null,             // object | null — the logged-in user record
  isAuthenticated: false, // boolean
  loading: true,          // boolean — true while checkAuthSession is pending
  error: null,            // string | null — set on rejected thunks
}
The slice also exports the synchronous clearAuthError action to reset error state without triggering a thunk:
import { clearAuthError } from '../redux/slices/authSlice';
dispatch(clearAuthError());

AsyncStorage Keys Reference

KeyPurpose
@registered_usersJSON array of all registered user objects
@logged_in_userJSON object of the currently active session
Passwords are stored as plain text in AsyncStorage. This is intentional for the current development build — do not ship this approach to production. Before releasing the app, hash passwords with a library such as bcrypt-react-native or delegate authentication to a secure backend service.

Build docs developers (and LLMs) love