#
tokens: 48535/50000 68/75 files (page 1/2)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 of 2. Use http://codebase.md/lallen30/mcp-remote-server?lines=false&page={x} to view the full context.

# Directory Structure

```
├── .gitignore
├── build
│   └── index.js
├── package-lock.json
├── package.json
├── README.md
├── resources
│   ├── code-examples
│   │   └── react-native
│   │       ├── assets
│   │       │   └── images
│   │       │       ├── event.png
│   │       │       ├── qr-codeeee13.png
│   │       │       └── [email protected]
│   │       ├── components
│   │       │   ├── Button.tsx
│   │       │   ├── ErrorBoundary.tsx
│   │       │   ├── LoadingSpinner.tsx
│   │       │   └── UpdateModal.tsx
│   │       ├── config
│   │       │   ├── apiConfig.ts
│   │       │   └── environment.ts
│   │       ├── hooks
│   │       │   ├── useAppUpdate.ts
│   │       │   └── useForm.ts
│   │       ├── navigation
│   │       │   ├── AppNavigator.tsx
│   │       │   ├── DrawerNavigator.tsx
│   │       │   ├── NavigationWrapper.tsx
│   │       │   └── TabNavigator.tsx
│   │       ├── screens
│   │       │   ├── AboutUs.tsx
│   │       │   ├── HomeScreen.js
│   │       │   ├── HomeScreen.tsx
│   │       │   ├── PostLogin
│   │       │   │   ├── AboutUs
│   │       │   │   │   ├── AboutUsScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── BluestoneAppsAI
│   │       │   │   │   ├── BluestoneAppsAIScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── Calendar
│   │       │   │   │   ├── CalendarScreen.tsx
│   │       │   │   │   ├── EventDetails.tsx
│   │       │   │   │   ├── EventDetailsStyles.ts
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── ChangePassword
│   │       │   │   │   ├── ChangePasswordScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── Contact
│   │       │   │   │   ├── ContactScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── CustomerSupport
│   │       │   │   │   ├── CustomerSupportScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── EditProfile
│   │       │   │   │   ├── EditProfileScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   ├── Home
│   │       │   │   │   └── HomeScreen.tsx
│   │       │   │   ├── MyProfile
│   │       │   │   │   ├── MyProfileScreen.tsx
│   │       │   │   │   └── Styles.ts
│   │       │   │   └── Posts
│   │       │   │       ├── PostScreen.tsx
│   │       │   │       ├── PostsScreen.tsx
│   │       │   │       ├── PostStyles.ts
│   │       │   │       └── Styles.ts
│   │       │   └── PreLogin
│   │       │       ├── ForgotPassword
│   │       │       │   ├── ForgotPasswordScreen.tsx
│   │       │       │   └── Styles.ts
│   │       │       ├── Legal
│   │       │       │   ├── PrivacyPolicyScreen.tsx
│   │       │       │   └── TermsAndConditionsScreen.tsx
│   │       │       ├── Login
│   │       │       │   ├── LoginScreen.tsx
│   │       │       │   └── Styles.tsx
│   │       │       ├── SignUp
│   │       │       │   ├── SignUpScreen.tsx
│   │       │       │   └── Styles.ts
│   │       │       └── VerifyEmail
│   │       │           ├── Styles.ts
│   │       │           └── VerifyEmailScreen.tsx
│   │       ├── services
│   │       │   ├── apiService.ts
│   │       │   ├── authService.ts
│   │       │   ├── axiosRequest.ts
│   │       │   ├── config.ts
│   │       │   ├── NavigationMonitorService.ts
│   │       │   ├── storageService.ts
│   │       │   ├── types.ts
│   │       │   ├── UpdateService.ts
│   │       │   └── userService.ts
│   │       ├── theme
│   │       │   ├── colors_original.ts
│   │       │   ├── colors.ts
│   │       │   ├── README.md
│   │       │   ├── theme.ts
│   │       │   └── typography.ts
│   │       ├── tsconfig.json
│   │       ├── types
│   │       │   └── react-native.d.ts
│   │       └── utils
│   │           ├── axiosUtils.ts
│   │           └── LogSuppressor.ts
│   └── standards
│       ├── api_communication.md
│       ├── component_design.md
│       ├── project_structure.md
│       └── state_management.md
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependencies
node_modules/

# Build output
build/
dist/

# Environment variables
.env
.env.local
.env.*.local

# Logs
logs/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea/
.vscode/
*.swp
*.swo
.DS_Store

# Testing
coverage/

# Temporary files
.tmp/
.temp/

# Debug
.node-version
.npm/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# MCP Remote Server (Node.js Version)

This is a Node.js implementation of the BluestoneApps Coding Standards and Examples MCP server.

## Overview

This MCP server provides access to React Native coding standards and code examples through the Model Context Protocol (MCP). It can be used with MCP clients like Windsurf IDE.

## Features

- Access to React Native coding standards
- Component, hook, screen, service, and theme code examples
- Fuzzy matching for finding examples by name
- Full integration with the MCP protocol

## Installation

1. Clone this repository
2. Install dependencies:
   ```bash
   npm install
   ```
3. Build the project:
   ```bash
   npm run build
   ```

## Usage

Start the server:

```bash
npm start
```

To use with MCP clients, configure them to connect to this server.

## Tools

The server provides the following tools:

- `get_project_structure`: Get project structure standards
- `get_api_communication`: Get API communication standards 
- `get_component_design`: Get component design standards
- `get_state_management`: Get state management standards
- `get_component_example`: Get a specific component example
- `get_hook_example`: Get a specific hook example
- `get_service_example`: Get a specific service example 
- `get_screen_example`: Get a specific screen example
- `get_theme_example`: Get a specific theme example
- `list_available_examples`: List all available code examples

## Configuring with MCP Clients

For Windsurf IDE, update the `mcp_config.json` with:

```json
{
  "servers": {
    "bluestoneapps": {
      "command": "node",
      "args": ["/path/to/build/index.js"],
      "description": "BluestoneApps Coding Standards and Examples",
      "displayName": "BluestoneApps MCP Server",
      "timeout": 30000
    }
  }
}

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/theme/README.md:
--------------------------------------------------------------------------------

```markdown
# React Native Theme System

This directory contains the TypeScript theme files for React Native applications. The theme system provides a consistent design language across the application.

## Standards

- All theme files are written in TypeScript (.ts) for better type safety and developer experience
- Theme files export both the values and TypeScript types for proper type checking
- The theme system is modular and composable, with separate files for different aspects of the design system

## Files

- `colors.ts` - Color palette definitions and utility functions
- `typography.ts` - Typography styles, font families, sizes, and text styles
- `theme.ts` - Main theme configuration that combines all theme elements

## Usage

Import the theme elements in your components:

```tsx
import { colors } from './theme/colors';
import typography from './theme/typography';
import theme from './theme/theme';

// Using colors
const styles = StyleSheet.create({
  container: {
    backgroundColor: colors.background,
  },
  text: {
    ...typography.body,
    color: colors.textPrimary,
  },
  button: {
    padding: theme.spacing.md,
    borderRadius: theme.borderRadius.md,
  },
});
```

## Type Support

The theme files export TypeScript types to provide autocompletion and type checking:

```tsx
import { ColorKey } from './theme/colors';
import { TypographyStyleKey } from './theme/typography';
import { SpacingKey, BorderRadiusKey } from './theme/theme';

// Type-safe usage
const color: ColorKey = 'primary';
const textStyle: TypographyStyleKey = 'body';
const spacing: SpacingKey = 'md';
```

## Extending the Theme

When extending the theme, follow these guidelines:

1. Add new values to the appropriate theme file
2. Ensure all values are properly typed
3. Use consistent naming conventions
4. Document any complex values or usage patterns
5. Update the theme.ts file if necessary to expose new theme elements

## Migration from JavaScript

This theme system has been migrated from JavaScript to TypeScript. All theme files now use the `.ts` extension and include proper type definitions.

```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "outDir": "./build",
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/CustomerSupport/CustomerSupportScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react';
import { View, Text } from 'react-native';
import { styles } from './Styles';

const CustomerSupportScreen = () => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Customer Support</Text>
      <Text style={styles.subtitle}>Coming Soon</Text>
    </View>
  );
};

export default CustomerSupportScreen; 
```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/theme/colors.ts:
--------------------------------------------------------------------------------

```typescript
export const colors = {
  primary: '#412DA5',
  secondary: '#6032FF',
  tertiary: '#29243F',
  success: '#23AD51',
  warning: '#EF7F18',
  danger: '#E02D47',
  white: '#FFFFFF',
  light: '#EEF1F7',
  medium: '#747D8B',
  dark: '#2D3035',
  black: '#070707',
  headerBg: '#29243F',
  headerFont: '#FFFFFF',
  footerBg: '#FFFFFF',
  footerFont: '#747D8B',
} as const;
```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/config/environment.ts:
--------------------------------------------------------------------------------

```typescript
export const environment = {
  server: 'wordpress.betaplanets.com',
  production: false,
  baseURL: 'https://wordpress.betaplanets.com',
  apiURL: 'https://wordpress.betaplanets.com/wp-json'
  // server: 'laravelapi2.betaplanets.com/api',
  // production: false,
  // baseURL: 'https://laravelapi2.betaplanets.com/api',
  // apiURL: 'https://laravelapi2.betaplanets.com/api/wp-json'
};

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/components/LoadingSpinner.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react';
import { View, ActivityIndicator, StyleSheet } from 'react-native';

export const LoadingSpinner = () => (
  <View style={styles.container}>
    <ActivityIndicator size="large" color="#007AFF" />
  </View>
);

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff'
  }
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/types.ts:
--------------------------------------------------------------------------------

```typescript
export interface LoginResponse {
  loginInfo: {
    token: string;
    user_email: string;
    user_nicename: string;
    user_display_name: string;
    [key: string]: any;
  };
}

export interface LoginCredentials {
  email: string;
  password: string;
}

export interface AuthError {
  response?: {
    data?: {
      message?: string;
    };
    status?: number;
  };
  message?: string;
}

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/CustomerSupport/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create<Styles>({
container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
  },
});

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "mcp-remote-server",
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node build/index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "BluestoneApps Coding Standards and Examples MCP Server",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.1.0",
    "glob": "^10.3.10",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/node": "^22.10.5",
    "typescript": "^5.7.2"
  }
}

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "es2020",
    "module": "esnext",
    "moduleResolution": "node",
    "jsx": "react-native",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "baseUrl": ".",
    "paths": {
      "*": ["types/*"]
    },
    "typeRoots": ["./types", "./node_modules/@types"]
  },
  "include": [
    "**/*.ts",
    "**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/theme/colors_original.ts:
--------------------------------------------------------------------------------

```typescript
export const colors = {
  primary: '#007AFF',
  secondary: '#50cebb',
  tertiary: '#F0A225',
  Success: '#2FD36F',
  Warning: '#FDC40C',
  Danger: '#EC445A',
  White: '#FFFFFF',
  ultraLight: '#F9F9FC',
  light: '#EBEBEB',
  mediumLight: '#BEC6C8',
  mediumDark: '#707070',
  dark: '#222428',
  black: '#000000',
  text: {
    primary: '#2c3e50',
    secondary: '#999',
    error: '#dc3545',
    white: '#fff',
    header: '#FFFFFF',
    footer: '#96A1A5',
  },
  background: {
    primary: '#fff',
    secondary: '#f8f9fa',
    header: '#3B00FF',
    footer: '#F9F9FC',
  },
  border: {
    primary: '#e9ecef',
    error: '#dc3545',
  },
} as const;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/AboutUs/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet } from 'react-native';
import { colors } from '../../../theme/colors';

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.primary,
  },
  header: {
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: colors.light,
    backgroundColor: colors.white,
    marginBottom: 0
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: colors.primary,
  },
  webViewContainer: {
    flex: 1,
    backgroundColor: colors.white,
  },
  webView: {
    flex: 1,
    backgroundColor: colors.white,
    opacity: 0.99 // Fix for iOS WebView rendering
  },
  noContent: {
    fontSize: 16,
    color: colors.dark,
    textAlign: 'center',
    marginTop: 20
  }
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Posts/PostStyles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, Dimensions } from 'react-native';
import { colors } from '../../../theme/colors';

const { width } = Dimensions.get('window');

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.white,
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: colors.white,
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 32,
    backgroundColor: colors.white,
  },
  errorText: {
    fontSize: 16,
    color: colors.danger,
    textAlign: 'center',
  },
  featuredImage: {
    width: width,
    height: width * 0.6,
    backgroundColor: colors.secondary,
  },
  content: {
    padding: 16,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: colors.primary,
    marginBottom: 8,
  },
  date: {
    fontSize: 14,
    color: colors.dark,
    marginBottom: 16,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Calendar/EventDetailsStyles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet } from 'react-native';
import { colors } from '../../../theme/colors';

export const styles = StyleSheet.create({
  
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  content: {
    flex: 1,
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: colors.black,
    marginBottom: 10,
  },
  date: {
    fontSize: 18,
    color: colors.secondary,
    marginBottom: 5,
  },
  time: {
    fontSize: 18,
    color: colors.secondary,
    marginBottom: 20,
  },
  section: {
    marginBottom: 25,
    borderTopWidth: 1,
    borderTopColor: colors.light,
    paddingTop: 20,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    color: colors.black,
    marginBottom: 10,
  },
  location: {
    fontSize: 16,
    color: colors.dark,
    lineHeight: 24,
  },
  description: {
    fontSize: 16,
    color: colors.dark,
    lineHeight: 24,
  },
  price: {
    fontSize: 18,
    color: colors.secondary,
    fontWeight: '500',
    marginTop: 5,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/utils/LogSuppressor.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * This file contains utilities to suppress specific console warnings
 * that are not relevant to the application's functionality.
 */

// Original console.warn function
const originalWarn = console.warn;

// List of warning messages to suppress
const suppressedWarnings = [
  'TRenderEngineProvider: Support for defaultProps will be removed from function components',
  'MemoizedTNodeRenderer: Support for defaultProps will be removed from memo components',
  'TNodeChildrenRenderer: Support for defaultProps will be removed from function components',
];

// Override console.warn to filter out specific warnings
console.warn = function (message: any, ...optionalParams: any[]) {
  // Check if this is a warning we want to suppress
  if (typeof message === 'string') {
    for (const warningText of suppressedWarnings) {
      if (message.includes(warningText)) {
        // Skip this warning
        return;
      }
    }
  }
  
  // Pass through to the original console.warn for all other warnings
  originalWarn(message, ...optionalParams);
};

export {}; // Make this a module

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/components/Button.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react';
import {
  TouchableOpacity,
  Text,
  StyleSheet,
  ViewStyle,
  TextStyle,
  ActivityIndicator,
} from 'react-native';

interface ButtonProps {
  title: string;
  onPress: () => void;
  style?: ViewStyle;
  textStyle?: TextStyle;
  loading?: boolean;
  disabled?: boolean;
}

export const Button: React.FC<ButtonProps> = ({
  title,
  onPress,
  style,
  textStyle,
  loading = false,
  disabled = false,
}) => {
  return (
    <TouchableOpacity
      style={[
        styles.button,
        style,
        disabled && styles.disabledButton,
      ]}
      onPress={onPress}
      disabled={disabled || loading}
    >
      {loading ? (
        <ActivityIndicator color="#fff" />
      ) : (
        <Text style={[styles.text, textStyle]}>{title}</Text>
      )}
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  button: {
    backgroundColor: '#007AFF',
    paddingVertical: 12,
    paddingHorizontal: 24,
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  disabledButton: {
    opacity: 0.6,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/VerifyEmail/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create<Styles>({
container: {
    flex: 1,
    backgroundColor: '#fff',
    padding: 20,
  },
  header: {
    marginTop: 40,
    marginBottom: 30,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#000',
    textAlign: 'center',
    marginBottom: 10,
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
    textAlign: 'center',
    marginBottom: 30,
  },
  otpContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginBottom: 30,
  },
  otpInput: {
    width: 50,
    height: 50,
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    textAlign: 'center',
    fontSize: 20,
    color: '#000',
  },
  button: {
    backgroundColor: '#007AFF',
    height: 50,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
    marginTop: 20,
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
  backButton: {
    marginTop: 20,
    alignItems: 'center',
  },
  backButtonText: {
    color: '#007AFF',
    fontSize: 16,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/ForgotPassword/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, Dimensions, ViewStyle, TextStyle, ImageStyle } from 'react-native';
import { colors } from '../../../theme/colors';

const { width } = Dimensions.get('window');

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.white,
    padding: 20,
    justifyContent: 'center' as const,
  },
  logoContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  logo: {
    width: width * 0.6,
    height: 200,
    resizeMode: 'contain',
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    color: colors.primary,
    marginBottom: 10,
    textAlign: 'center',
  },
  subtitle: {
    fontSize: 16,
    color: colors.secondary,
    marginBottom: 30,
    textAlign: 'center',
  },
  input: {
    backgroundColor: colors.light,
    borderRadius: 8,
    padding: 15,
    marginBottom: 15,
    color: colors.black,
  },
  button: {
    backgroundColor: colors.primary,
    borderRadius: 8,
    padding: 15,
    alignItems: 'center',
    marginBottom: 15,
  },
  buttonText: {
    color: colors.white,
    fontSize: 16,
    fontWeight: 'bold',
  },
  backButton: {
    alignItems: 'center',
    marginTop: 10,
  },
  backButtonText: {
    color: colors.primary,
    fontSize: 16,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Posts/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet } from 'react-native';
import { colors } from '../../../theme/colors';

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.light,
  },
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: colors.white,
  },
  header: {
    padding: 16,
    backgroundColor: colors.headerBg,
    borderBottomWidth: 1,
    borderBottomColor: colors.primary,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: colors.headerFont,
  },
  postsContainer: {
    padding: 16,
  },
  categorySection: {
    marginBottom: 24,
  },
  categoryTitle: {
    fontSize: 20,
    fontWeight: '600',
    color: colors.primary,
    marginBottom: 12,
  },
  postCard: {
    backgroundColor: colors.white,
    borderRadius: 8,
    padding: 16,
    marginBottom: 12,
    shadowColor: colors.black,
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  postTitle: {
    fontSize: 18,
    fontWeight: '500',
    color: colors.black,
    marginBottom: 8,
  },
  postDate: {
    fontSize: 14,
    color: colors.secondary,
  },
  emptyContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 32,
  },
  emptyText: {
    fontSize: 16,
    color: colors.secondary,
    textAlign: 'center',
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/axiosRequest.ts:
--------------------------------------------------------------------------------

```typescript
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { API } from './config';

const axiosRequest = axios.create({
  baseURL: API.BASE_URL,
  timeout: 30000,
  headers: {
    'Accept': 'application/json'
  },
  transformRequest: [(data, headers) => {
    // Don't transform FormData
    if (data instanceof FormData) {
      return data;
    }
    
    // For regular objects, transform to form-urlencoded
    if (data && typeof data === 'object') {
      headers['Content-Type'] = 'application/x-www-form-urlencoded';
      return Object.entries(data)
        .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
        .join('&');
    }
    return data;
  }]
});

// Request interceptor
axiosRequest.interceptors.request.use(
  async (config) => {
    console.log('Making request to:', config.url);
    console.log('Request data:', config.data);
    console.log('Request headers:', config.headers);
    console.log('Request method:', config.method);
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Response interceptor
axiosRequest.interceptors.response.use(
  (response) => {
    console.log('API Response:', response.data);
    return response;
  },
  (error) => {
    console.error('API Error:', error.response?.data || error.message);
    return Promise.reject(error);
  }
);

export default axiosRequest;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/utils/axiosUtils.ts:
--------------------------------------------------------------------------------

```typescript
import axios from 'axios';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { API } from '../config/apiConfig';

const axiosRequest = axios.create({
  baseURL: API.BASE_URL,
  timeout: 30000,
  headers: {
    'Accept': 'application/json'
  },
  transformRequest: [(data, headers) => {
    // Don't transform FormData
    if (data instanceof FormData) {
      return data;
    }
    
    // For regular objects, transform to form-urlencoded
    if (data && typeof data === 'object') {
      headers['Content-Type'] = 'application/x-www-form-urlencoded';
      return Object.entries(data)
        .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
        .join('&');
    }
    return data;
  }]
});

// Request interceptor
axiosRequest.interceptors.request.use(
  async (config) => {
    console.log('Making request to:', config.url);
    console.log('Request data:', config.data);
    console.log('Request headers:', config.headers);
    console.log('Request method:', config.method);
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// Response interceptor
axiosRequest.interceptors.response.use(
  (response) => {
    console.log('API Response:', response.data);
    return response;
  },
  (error) => {
    console.error('API Error:', error.response?.data || error.message);
    return Promise.reject(error);
  }
);

export default axiosRequest;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/ChangePassword/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
import { colors } from '../../../theme/colors';

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create<Styles>({
container: {
    flex: 1,
    backgroundColor: colors.white,
  },
  header: {
    padding: 20,
    paddingTop: 40,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  backButton: {
    color: colors.white,
  },
  subtitle: {
    fontSize: 16,
    color: colors.dark,
    marginBottom: 20,
  },
  formContainer: {
    padding: 20,
  },
  inputGroup: {
    marginBottom: 20,
  },
  label: {
    fontSize: 16,
    marginBottom: 8,
    color: colors.dark,
  },
  inputContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    borderWidth: 1,
    borderColor: colors.dark,
    borderRadius: 8,
    paddingHorizontal: 12,
    backgroundColor: colors.light,
  },
  inputIcon: {
    marginRight: 10,
  },
  input: {
    flex: 1,
    height: 48,
    fontSize: 16,
    color: colors.dark,
  },
  errorText: {
    color: colors.danger,
    fontSize: 14,
    marginTop: 5,
  },
  button: {
    backgroundColor: colors.primary,
    borderRadius: 8,
    height: 48,
    justifyContent: 'center',
    alignItems: 'center',
    marginTop: 20,
  },
  disabledButton: {
    opacity: 0.7,
  },
  buttonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Contact/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, Dimensions, ViewStyle, TextStyle, ImageStyle, Platform } from 'react-native';
import { colors } from '../../../theme/colors';

const { width } = Dimensions.get('window');

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create({
  safeArea: {
    flex: 1,
    backgroundColor: colors.white,
  },
  keyboardAvoidingView: {
    flex: 1,
  },
  contentContainer: {
    flex: 1,
    backgroundColor: colors.white,
  },
  scrollView: {
    flex: 1,
  },
  scrollViewContent: {
    padding: 20,
  },
  formContainer: {
    flex: 1,
  },
  buttonWrapper: {
    backgroundColor: colors.white,
    padding: 16,
    paddingBottom: Platform.OS === 'ios' ? 0 : 16,
    borderTopWidth: 1,
    borderTopColor: colors.light,
  },
  label: {
    fontSize: 16,
    fontWeight: '600',
    marginBottom: 5,
    color: colors.dark,
  },
  input: {
    height: 50,
    borderWidth: 1,
    borderColor: colors.dark,
    borderRadius: 8,
    paddingHorizontal: 15,
    marginBottom: 15,
    fontSize: 16,
    color: colors.dark,
    backgroundColor: colors.light,
  },
  messageInput: {
    height: 120,
    textAlignVertical: 'top',
    paddingTop: 12,
    paddingBottom: 12,
  },
  submitButton: {
    backgroundColor: colors.primary,
    height: 50,
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
  },
  submitButtonDisabled: {
    opacity: 0.7,
  },
  submitButtonText: {
    color: colors.white,
    fontSize: 16,
    fontWeight: '600',
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/BluestoneAppsAI/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create<Styles>({
container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  header: {
    padding: 16,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
  },
  content: {
    flex: 1,
    padding: 16,
  },
  messageContainer: {
    marginBottom: 16,
    padding: 16,
    backgroundColor: '#f9f9f9',
    borderRadius: 8,
    borderWidth: 1,
    borderColor: '#eee',
  },
  inputContainer: {
    marginTop: 16,
  },
  input: {
    borderWidth: 1,
    borderColor: '#ddd',
    borderRadius: 8,
    padding: 12,
    marginBottom: 12,
    minHeight: 100,
    textAlignVertical: 'top',
  },
  submitButton: {
    backgroundColor: '#007AFF',
    padding: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  submitButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: '600',
  },
  loadingText: {
    color: '#666',
    fontSize: 16,
    textAlign: 'center',
    padding: 16,
  },
  // HTML content styles
  htmlContent: {
    color: '#333',
    fontSize: 16,
    lineHeight: 24,
  },
  paragraph: {
    marginVertical: 8,
    color: '#333',
    fontSize: 16,
    lineHeight: 24,
  },
  heading1: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#333',
    marginVertical: 12,
  },
  heading2: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#333',
    marginVertical: 10,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Calendar/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet } from 'react-native';
import { colors } from '../../../theme/colors';

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.white,
  },
  calendar: {
    marginBottom: 0,
  },
  contentContainer: {
    flex: 1,
    backgroundColor: colors.white,
  },
  sectionHeader: {
    backgroundColor: colors.white,
    borderBottomWidth: 1,
    borderTopWidth: 1,
    borderColor: colors.light,
  },
  sectionTitle: {
    color: colors.black,
    textAlign: 'center',
  },
  titleContainer: {
    backgroundColor: colors.light,
    margin: 15,
    borderRadius: 8,
    shadowColor: colors.black,
    shadowOffset: {
      width: 0,
      height: 1,
    },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    elevation: 2,
  },
  eventsContainer: {
    flex: 1,
    paddingHorizontal: 15,
  },
  eventCard: {
    backgroundColor: colors.white,
    padding: 15,
    marginBottom: 12,
    borderRadius: 10,
    shadowColor: colors.black,
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.1,
    shadowRadius: 3,
    elevation: 3,
    borderWidth: 1,
    borderColor: colors.light,
  },
  eventTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: colors.black,
    marginBottom: 8,
  },
  eventTime: {
    fontSize: 14,
    color: colors.secondary,
    marginBottom: 8,
    fontWeight: '500',
  },
  eventLocation: {
    fontSize: 14,
    color: colors.dark,
    lineHeight: 20,
  },
  noEventsText: {
    textAlign: 'center',
    color: colors.dark,
    fontSize: 15,
    paddingVertical: 20,
    fontStyle: 'italic',
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Home/HomeScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useRef, useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import useAppUpdate from '../../../hooks/useAppUpdate';
import { useFocusEffect } from '@react-navigation/native';

const HomeScreen = () => {
  // Get the checkForUpdates function from the useAppUpdate hook
  // Use a shorter interval for the home screen (30 minutes)
  const { checkForUpdates } = useAppUpdate(false, 30 * 60 * 1000);
  
  // Use a ref to track if we're already checking for updates
  const isCheckingRef = useRef(false);
  
  // Track if this is the first render
  const [hasCheckedOnMount, setHasCheckedOnMount] = useState(false);

  // Check for updates once when the component mounts
  useEffect(() => {
    if (!hasCheckedOnMount && !isCheckingRef.current) {
      isCheckingRef.current = true;
      
      // Run the update check silently and forced
      checkForUpdates(true, true).finally(() => {
        isCheckingRef.current = false;
        setHasCheckedOnMount(true);
      });
    }
  }, [checkForUpdates, hasCheckedOnMount]);

  // We're not using useFocusEffect anymore to prevent multiple checks
  // when the screen is repeatedly focused

  return (
    <View style={styles.container}>
      <Text style={styles.welcomeText}>Welcome to the Bluestone Apps Home screen</Text>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#fff',
    padding: 20,
  },
  welcomeText: {
    fontSize: 24,
    fontWeight: '600',
    color: '#333',
    textAlign: 'center',
  },
});

export default HomeScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/config/apiConfig.ts:
--------------------------------------------------------------------------------

```typescript
import { environment } from './environment';

interface AppConstType {
  APP_NAME: string;
  VERSION: string;
}

interface APIEndpoints {
  LOGIN: string;
  MOBILEAPI: string;
  GET_PROFILE: string;
  UPDATE_PROFILE: string;
  CHANGE_PASSWORD: string;
  GET_ABOUTUS: string;
  DELETE_USER: string;
  GET_EVENTS: string;
  GET_AI_API_URL: string;
  GET_AI_WELCOME: string;
  SAVE_AI_QNA: string;
  ASK_BLUESTONEAI: string;
  GET_AI_CREDENTIALS: string;
  GET_TERMS_DATE: string;
  GET_PRIVACY_DATE: string;
  GET_TERMS_PAGE: string;
  GET_PRIVACY_PAGE: string;
  APP_VERSION: string;
}

interface APIConfig {
  BASE_URL: string;
  ENDPOINTS: APIEndpoints;
}

export const AppConst: AppConstType = {
  APP_NAME: 'LA React Native',
  VERSION: '1.5.0',
};

export const API: APIConfig = {
  BASE_URL: environment.baseURL,
  ENDPOINTS: {
    LOGIN: 'wp-json/jwt-auth/v1/token',
    MOBILEAPI: 'wp-json/mobileapi/v1',
    GET_PROFILE: 'wp-json/mobileapi/v1/getProfile',
    UPDATE_PROFILE: 'wp-json/mobileapi/v1/updateProfile',
    CHANGE_PASSWORD: 'updatePassword',
    GET_ABOUTUS: 'get_aboutus',
    DELETE_USER: 'delete_user',
    GET_EVENTS: 'wp-json/mobileapi/v1/getEvents',
    GET_AI_API_URL: 'get_ai_api_url',
    GET_AI_WELCOME: 'get_ai_welcome',
    SAVE_AI_QNA: 'save_ai_qna',
    ASK_BLUESTONEAI: 'ask_bluestoneai',
    GET_AI_CREDENTIALS: 'get_ai_credentials',
    GET_TERMS_DATE: 'wp-json/mobileapi/v1/getTermsPublishedDate',
    GET_PRIVACY_DATE: 'wp-json/mobileapi/v1/getPrivacyPublishedDate',
    GET_TERMS_PAGE: 'wp-json/mobileapi/v1/getTermsPage',
    GET_PRIVACY_PAGE: 'wp-json/mobileapi/v1/getPrivacyPage',
    APP_VERSION: 'wp-json/mobileapi/v1/app_version'
  }
};

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/config.ts:
--------------------------------------------------------------------------------

```typescript
import { environment } from '../config/environment';

interface AppConstType {
  APP_NAME: string;
  VERSION: string;
}

interface APIEndpoints {
  LOGIN: string;
  MOBILEAPI: string;
  GET_PROFILE: string;
  UPDATE_PROFILE: string;
  CHANGE_PASSWORD: string;
  GET_ABOUTUS: string;
  DELETE_USER: string;
  GET_EVENTS: string;
  GET_AI_API_URL: string;
  GET_AI_WELCOME: string;
  SAVE_AI_QNA: string;
  ASK_BLUESTONEAI: string;
  GET_AI_CREDENTIALS: string;
  GET_TERMS_DATE: string;
  GET_PRIVACY_DATE: string;
  GET_TERMS_PAGE: string;
  GET_PRIVACY_PAGE: string;
  APP_VERSION: string;
}

interface APIConfig {
  BASE_URL: string;
  ENDPOINTS: APIEndpoints;
}

export const AppConst: AppConstType = {
  APP_NAME: 'LA React Native',
  VERSION: '1.5.0',
};

export const API: APIConfig = {
  BASE_URL: environment.baseURL,
  ENDPOINTS: {
    LOGIN: 'wp-json/jwt-auth/v1/token',
    MOBILEAPI: 'wp-json/mobileapi/v1',
    GET_PROFILE: 'wp-json/mobileapi/v1/getProfile',
    UPDATE_PROFILE: 'wp-json/mobileapi/v1/updateProfile',
    CHANGE_PASSWORD: 'updatePassword',
    GET_ABOUTUS: 'get_aboutus',
    DELETE_USER: 'delete_user',
    GET_EVENTS: 'wp-json/mobileapi/v1/getEvents',
    GET_AI_API_URL: 'get_ai_api_url',
    GET_AI_WELCOME: 'get_ai_welcome',
    SAVE_AI_QNA: 'save_ai_qna',
    ASK_BLUESTONEAI: 'ask_bluestoneai',
    GET_AI_CREDENTIALS: 'get_ai_credentials',
    GET_TERMS_DATE: 'wp-json/mobileapi/v1/getTermsPublishedDate',
    GET_PRIVACY_DATE: 'wp-json/mobileapi/v1/getPrivacyPublishedDate',
    GET_TERMS_PAGE: 'wp-json/mobileapi/v1/getTermsPage',
    GET_PRIVACY_PAGE: 'wp-json/mobileapi/v1/getPrivacyPage',
    APP_VERSION: 'wp-json/mobileapi/v1/app_version'
  }
};

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/Login/Styles.tsx:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, Dimensions } from 'react-native';
import { colors } from '../../../theme/colors';

const { width } = Dimensions.get('window');

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.white,
    padding: 20,
    justifyContent: 'center',
  },
  logoContainer: {
    alignItems: 'center',
    marginBottom: 20,
  },
  logo: {
    width: width * 0.6,
    height: 300,
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    color: colors.primary,
    marginBottom: 30,
    textAlign: 'center',
  },
  input: {
    height: 50,
    borderWidth: 1,
    borderColor: colors.dark,
    borderRadius: 8,
    paddingHorizontal: 15,
    marginBottom: 15,
    fontSize: 16,
    color: colors.dark,
    backgroundColor: colors.light,
  },
  passwordContainer: {
    position: 'relative',
    marginBottom: 15,
  },
  eyeIcon: {
    position: 'absolute',
    right: 15,
    top: 13,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 20,
  },
  customCheckbox: {
    width: 24,
    height: 24,
    borderRadius: 4,
    borderWidth: 2,
    borderColor: colors.primary,
    marginRight: 10,
    justifyContent: 'center',
    alignItems: 'center',
  },
  customCheckboxChecked: {
    backgroundColor: colors.primary,
  },
  checkboxLabel: {
    fontSize: 16,
    color: colors.dark,
  },
  button: {
    backgroundColor: colors.primary,
    height: 50,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  buttonText: {
    color: colors.white,
    fontSize: 18,
    fontWeight: '600',
  },
  linkContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    marginTop: 20,
  },
  link: {
    color: colors.secondary,
    fontSize: 16,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/storageService.ts:
--------------------------------------------------------------------------------

```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';

class StorageService {
  async set(key: string, value: any): Promise<void> {
    try {
      await AsyncStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error('Error saving to storage:', error);
      throw error;
    }
  }

  async get(key: string): Promise<any> {
    try {
      const item = await AsyncStorage.getItem(key);
      return item ? JSON.parse(item) : null;
    } catch (error) {
      console.error('Error reading from storage:', error);
      throw error;
    }
  }

  async remove(key: string): Promise<void> {
    try {
      await AsyncStorage.removeItem(key);
    } catch (error) {
      console.error('Error removing from storage:', error);
      throw error;
    }
  }

  async clearAll(): Promise<void> {
    try {
      // Get all keys first
      const keys = await AsyncStorage.getAllKeys();
      
      if (keys.length === 0) {
        return; // Nothing to clear
      }
      
      // Try multiRemove first as it's more efficient
      try {
        await AsyncStorage.multiRemove(keys);
        return;
      } catch (multiError) {
        console.warn('Error with multiRemove, falling back to individual removal:', multiError);
        
        // Fall back to removing items one by one
        for (const key of keys) {
          try {
            await AsyncStorage.removeItem(key);
          } catch (individualError) {
            console.warn(`Failed to remove item with key: ${key}`, individualError);
            // Continue with other keys
          }
        }
      }
    } catch (error) {
      console.error('Error clearing storage:', error);
      // Don't throw the error, just log it
    }
  }
}

export const storageService = new StorageService();

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/EditProfile/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
import { colors } from '../../../theme/colors';

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create<Styles>({
container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  header: {
    alignItems: 'center',
    padding: 20,
    backgroundColor: colors.light,
  },
  avatarContainer: {
    width: 120,
    height: 120,
    borderRadius: 60,
    overflow: 'hidden',
    backgroundColor: colors.light,
    position: 'relative',
  },
  profileImage: {
    width: '100%',
    height: '100%',
  },
  cameraIconContainer: {
    position: 'absolute',
    bottom: 0,
    right: 0,
    backgroundColor: colors.primary,
    width: 36,
    height: 36,
    borderRadius: 18,
    justifyContent: 'center',
    alignItems: 'center',
  },
  formContainer: {
    padding: 20,
  },
  inputGroup: {
    marginBottom: 20,
  },
  label: {
    fontSize: 14,
    color: '#666',
    marginBottom: 8,
  },
  inputContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    borderWidth: 1,
    borderColor: colors.dark,
    borderRadius: 8,
    paddingHorizontal: 12,
    backgroundColor: colors.light,
  },
  inputIcon: {
    marginRight: 10,
  },
  input: {
    flex: 1,
    height: 48,
    fontSize: 16,
    color: colors.black,
    backgroundColor: colors.light,
  },
  errorText: {
    color: colors.danger,
    fontSize: 12,
    marginTop: 4,
  },
  buttonContainer: {
    padding: 20,
    paddingBottom: 40,
  },
  button: {
    backgroundColor: colors.primary,
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
  disabledButton: {
    opacity: 0.7,
  },
  buttonText: {
    color: colors.white,
    fontSize: 16,
    fontWeight: '600',
  },
  backButton: {
    color: colors.white,
  }
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/SignUp/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, Dimensions } from 'react-native';
import { colors } from '../../../theme/colors';

const { width } = Dimensions.get('window');

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.white,
    padding: 20,
  },
  scrollContainer: {
    flexGrow: 1,
    justifyContent: 'center',
  },
  logoContainer: {
    alignItems: 'center',
    marginBottom: 0,
  },
  logo: {
    width: width * 0.6,
    height: 200,
    resizeMode: 'contain',
  },
  title: {
    fontSize: 28,
    fontWeight: 'bold',
    color: colors.primary,
    marginBottom: 30,
    textAlign: 'center',
  },
  input: {
    height: 50,
    borderWidth: 1,
    borderColor: colors.dark,
    borderRadius: 8,
    paddingHorizontal: 15,
    marginBottom: 15,
    fontSize: 16,
    backgroundColor: colors.light,
    color: colors.primary,
  },
  errorText: {
    color: colors.danger,
    fontSize: 14,
    marginTop: -10,
    marginBottom: 10,
    marginLeft: 5,
  },
  checkboxContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 20,
  },
  customCheckbox: {
    width: 20,
    height: 20,
    borderRadius: 4,
    borderWidth: 2,
    borderColor: colors.dark,
    marginRight: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  customCheckboxChecked: {
    backgroundColor: colors.primary,
  },
  checkboxLabel: {
    flex: 1,
    marginLeft: 8,
    color: colors.primary,
  },
  button: {
    backgroundColor: colors.primary,
    height: 50,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
    marginBottom: 20,
  },
  buttonText: {
    color: colors.white,
    fontSize: 18,
    fontWeight: '600',
  },
  linkContainer: {
    flexDirection: 'row',
    justifyContent: 'center',
    marginTop: 10,
  },
  linkText: {
    color: colors.primary,
    fontSize: 16,
  },
  link: {
    color: colors.primary,
    textDecorationLine: 'underline',
    fontSize: 16,
    marginLeft: 5,
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/authService.ts:
--------------------------------------------------------------------------------

```typescript
import axiosRequest from './axiosRequest';
import {API} from './config';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { LoginResponse, AuthError } from './types';

class AuthService {
  async login(email: string, password: string): Promise<LoginResponse> {
    try {
      console.log('Attempting login with:', { email });

      const data = {
        email: email.trim(),
        password: password
      };

      console.log('Making request to:', API.ENDPOINTS.LOGIN, 'with data:', data);

      const response = await axiosRequest.post<LoginResponse>(
        API.ENDPOINTS.LOGIN,
        data
      );

      console.log('Login response:', response);

      if (response?.loginInfo?.token) {
        await AsyncStorage.setItem('userToken', response.loginInfo.token);
        // Store data in the correct format expected by the profile screen
        const userData = { loginInfo: response.loginInfo };
        console.log('Storing userData in AuthService:', userData);
        await AsyncStorage.setItem('userData', JSON.stringify(userData));
      }

      return response;
    } catch (error) {
      console.error('Login error:', error);
      throw error as AuthError;
    }
  }

  async logout(): Promise<void> {
    try {
      // Try to remove items individually first
      const keys = ['userToken', 'userData', 'rememberMe'];
      
      for (const key of keys) {
        try {
          await AsyncStorage.removeItem(key);
        } catch (err) {
          console.warn(`Error removing ${key}:`, err);
          // Continue with other keys even if one fails
        }
      }
      
      // If we're still here, try to perform any navigation or state resets
      return;
    } catch (error) {
      console.error('Logout error:', error);
      // Don't throw the error, just log it and continue
      // This prevents the error from bubbling up to the UI
      return;
    }
  }

  // Add other auth-related methods here
}

export default new AuthService();

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/MyProfile/Styles.ts:
--------------------------------------------------------------------------------

```typescript
import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
import { colors } from '../../../theme/colors';

type Styles = {
    [key: string]: ViewStyle | TextStyle | ImageStyle;
};

export const styles = StyleSheet.create<Styles>({
container: {
    flex: 1,
    backgroundColor: colors.white,
  },
  centerContent: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  header: {
    alignItems: 'center',
    padding: 20,
    backgroundColor: colors.light,
  },
  avatarContainer: {
    width: 120,
    height: 120,
    borderRadius: 60,
    overflow: 'hidden',
    marginBottom: 15,
    backgroundColor: colors.primary,
  },
  profileImage: {
    width: '100%',
    height: '100%',
  },
  name: {
    fontSize: 24,
    fontWeight: '600',
    color: '#000',
    marginBottom: 5,
  },
  location: {
    fontSize: 16,
    color: colors.dark,
    marginTop: 4,
  },
  infoSection: {
    padding: 20,
    backgroundColor: colors.white,
    borderRadius: 8,
    margin: 16,
    shadowColor: colors.black,
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  infoItem: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingVertical: 12,
    borderBottomWidth: 1,
    borderBottomColor: colors.light,
  },
  icon: {
    marginRight: 15,
  },
  label: {
    fontSize: 14,
    color: '#666',
    marginBottom: 4,
  },
  value: {
    fontSize: 16,
    color: '#000',
  },
  buttonContainer: {
    padding: 20,
    paddingTop: 0,
  },
  button: {
    backgroundColor: colors.primary,
    borderRadius: 8,
    padding: 15,
    alignItems: 'center',
    marginBottom: 10,
  },
  secondaryButton: {
    backgroundColor: colors.secondary,
    borderWidth: 1,
    borderColor: colors.light,
  },
  buttonText: {
    color: colors.white,
    fontSize: 16,
    fontWeight: '600',
  },
  secondaryButtonText: {
    color: colors.white,
  },
  errorText: {
    fontSize: 16,
    color: '#ff3b30',
    textAlign: 'center',
  },
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/types/react-native.d.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Type declarations for React Native
 * 
 * This file provides type definitions for React Native components and APIs
 * used in the theme examples. This allows TypeScript to understand React Native
 * types without requiring the full React Native package to be installed.
 */

declare module 'react-native' {
  export interface TextStyle {
    fontFamily?: string;
    fontSize?: number;
    fontStyle?: 'normal' | 'italic';
    fontWeight?: string | number;
    letterSpacing?: number;
    lineHeight?: number;
    textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify';
    textDecorationLine?: 'none' | 'underline' | 'line-through' | 'underline line-through';
    textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed';
    textDecorationColor?: string;
    textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
    color?: string;
    includeFontPadding?: boolean;
    textAlignVertical?: 'auto' | 'top' | 'bottom' | 'center';
    fontVariant?: string[];
    writingDirection?: 'auto' | 'ltr' | 'rtl';
  }

  export interface ViewStyle {
    backgroundColor?: string;
    borderBottomColor?: string;
    borderBottomEndRadius?: number;
    borderBottomLeftRadius?: number;
    borderBottomRightRadius?: number;
    borderBottomStartRadius?: number;
    borderBottomWidth?: number;
    borderColor?: string;
    borderEndColor?: string;
    borderEndWidth?: number;
    borderLeftColor?: string;
    borderLeftWidth?: number;
    borderRadius?: number;
    borderRightColor?: string;
    borderRightWidth?: number;
    borderStartColor?: string;
    borderStartWidth?: number;
    borderStyle?: 'solid' | 'dotted' | 'dashed';
    borderTopColor?: string;
    borderTopEndRadius?: number;
    borderTopLeftRadius?: number;
    borderTopRightRadius?: number;
    borderTopStartRadius?: number;
    borderTopWidth?: number;
    borderWidth?: number;
    opacity?: number;
    elevation?: number;
    shadowColor?: string;
    shadowOffset?: { width: number; height: number };
    shadowOpacity?: number;
    shadowRadius?: number;
  }

  export const Platform: {
    OS: 'ios' | 'android' | 'web';
    select: <T extends Record<string, any>>(obj: T) => T[keyof T];
  };
}

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/apiService.ts:
--------------------------------------------------------------------------------

```typescript
import { storageService } from './storageService';
import { environment } from '../config/environment';

const BASE_URL = `https://${environment.server}/`;
const MOBILE_API = `${BASE_URL}wp-json/mobileapi/v1/`;

interface ApiResponse {
  status: string;
  errormsg: string;
  error_code: string;
  categories: Array<{
    category_id: number;
    category_name: string;
    posts: Array<{
      post_id: number;
      post_title: string;
      post_content: string;
      post_date: string;
      featured_image?: string;
    }>;
  }>;
}

class ApiService {
  async getData(endpoint: string) {
    try {
      console.log('Fetching from:', MOBILE_API + endpoint);
      const response = await fetch(MOBILE_API + endpoint);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('Error fetching data:', error);
      throw error;
    }
  }

  async sendData(endpoint: string, data: any) {
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    const payload = {
      ...(typeof data === 'object' ? data : { value: data }),
      timezone,
    };

    try {
      const response = await fetch(MOBILE_API + endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      return result;
    } catch (error) {
      console.error('Error sending data:', error);
      throw error;
    }
  }

  async fetchAndStorePosts() {
    try {
      const response = await this.getData('getPostsByCategories') as ApiResponse;
      console.log('API Response:', response);
      
      if (response?.status === 'ok' && response?.categories) {
        await storageService.set('posts', response.categories);
        return response.categories;
      }
      return null;
    } catch (error) {
      console.error('Error fetching posts:', error);
      throw error;
    }
  }
}

export const apiService = new ApiService();

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/navigation/AppNavigator.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import LoginScreen from '../screens/PreLogin/Login/LoginScreen';

import ForgotPasswordScreen from '../screens/PreLogin/ForgotPassword/ForgotPasswordScreen';
import SignUpScreen from '../screens/PreLogin/SignUp/SignUpScreen';
import VerifyEmailScreen from '../screens/PreLogin/VerifyEmail/VerifyEmailScreen';
import DrawerNavigator from './DrawerNavigator';
import TermsAndConditionsScreen from '../screens/PreLogin/Legal/TermsAndConditionsScreen';
import PrivacyPolicyScreen from '../screens/PreLogin/Legal/PrivacyPolicyScreen';
import { withNavigationWrapper } from './NavigationWrapper';

const Stack = createNativeStackNavigator();

// Wrap components with navigation wrapper
const WrappedLoginScreen = withNavigationWrapper(LoginScreen);
const WrappedSignUpScreen = withNavigationWrapper(SignUpScreen);
const WrappedForgotPasswordScreen = withNavigationWrapper(ForgotPasswordScreen);
const WrappedVerifyEmailScreen = withNavigationWrapper(VerifyEmailScreen);
const WrappedTermsAndConditionsScreen = withNavigationWrapper(TermsAndConditionsScreen);
const WrappedPrivacyPolicyScreen = withNavigationWrapper(PrivacyPolicyScreen);

const AppNavigator = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Login"
        screenOptions={{
          headerShown: false,
          gestureEnabled: true,
          animation: 'default'
        }}>
        <Stack.Screen
          name="Login"
          component={WrappedLoginScreen}
        />
        <Stack.Screen
          name="DrawerNavigator"
          component={DrawerNavigator}
        />
        <Stack.Screen
          name="SignUp"
          component={WrappedSignUpScreen}
          options={{
            presentation: 'card'
          }}
        />
        <Stack.Screen
          name="ForgotPassword"
          component={WrappedForgotPasswordScreen}
          options={{
            presentation: 'card'
          }}
        />
        <Stack.Screen
          name="VerifyEmail"
          component={WrappedVerifyEmailScreen}
          options={{
            presentation: 'card'
          }}
        />
        <Stack.Screen
          name="TermsAndConditions"
          component={WrappedTermsAndConditionsScreen}
          options={{
            presentation: 'modal'
          }}
        />
        <Stack.Screen
          name="PrivacyPolicy"
          component={WrappedPrivacyPolicyScreen}
          options={{
            presentation: 'modal'
          }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default AppNavigator;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Posts/PostScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import { View, Text, ScrollView, Image, ActivityIndicator, useWindowDimensions } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import RenderHtml from 'react-native-render-html';
import { storageService } from '../../../helper/storageService';
import { styles } from './PostStyles';
import { colors } from '../../../theme/colors';

interface Post {
  post_id: string;
  post_title: string;
  post_content: string;
  post_date: string;
  featured_image?: string;
}

const PostScreen = () => {
  const navigation = useNavigation();
  const route = useRoute();
  const { width } = useWindowDimensions();
  const [loading, setLoading] = useState(true);
  const [post, setPost] = useState<Post | null>(null);
  const postId = route.params?.id;

  useEffect(() => {
    loadPost();
  }, [postId]);

  const loadPost = async () => {
    try {
      const categories = await storageService.get('posts');
      if (categories && Array.isArray(categories)) {
        for (const category of categories) {
          const foundPost = category.posts.find(p => p.post_id.toString() === postId?.toString());
          if (foundPost) {
            setPost(foundPost);
            navigation.setOptions({
              headerTitle: foundPost.post_title,
            });
            break;
          }
        }
      }
    } catch (error) {
      console.error('Error loading post:', error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) {
    return (
      <View style={styles.loadingContainer}>
        <ActivityIndicator size="large" color={colors.primary} />
      </View>
    );
  }

  if (!post) {
    return (
      <View style={styles.errorContainer}>
        <Text style={styles.errorText}>Post not found</Text>
      </View>
    );
  }

  const formatDate = (dateString: string) => {
    const date = new Date(dateString);
    return date.toLocaleDateString('en-US', {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
    });
  };

  return (
    <ScrollView style={styles.container}>
      {post.featured_image && (
        <Image
          source={{ uri: post.featured_image }}
          style={styles.featuredImage}
          resizeMode="cover"
        />
      )}
      <View style={styles.content}>
        <Text style={styles.title}>{post.post_title}</Text>
        <Text style={styles.date}>{formatDate(post.post_date)}</Text>
        <RenderHtml
          contentWidth={width - 32}
          source={{ html: post.post_content }}
          tagsStyles={{
            body: {
              color: colors.black,
              fontSize: 16,
              lineHeight: 24,
            },
            a: {
              color: colors.primary,
              textDecorationLine: 'underline',
            },
          }}
        />
      </View>
    </ScrollView>
  );
};

export default PostScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/navigation/NavigationWrapper.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useEffect, useState } from 'react';
import { Alert, View, Text, StyleSheet } from 'react-native';
import { NavigationMonitorService } from '../services/NavigationMonitorService';

interface NavigationProps {
  navigation: any;
  route: {
    name: string;
  };
}

export const withNavigationWrapper = (WrappedComponent: React.ComponentType<any>) => {
  return function WithNavigationWrapper(props: NavigationProps) {
    const { navigation, route } = props;
    const [error, setError] = useState<string | null>(null);

    useEffect(() => {
      // Only check for updates if not an excluded route
      if (!NavigationMonitorService.isExcludedRoute(route.name)) {
        // Perform silent update checks without showing loading indicator
        try {
          checkForUpdates()
            .catch(err => {
              console.error('Error in checkForUpdates:', err);
              setError(`Failed to check for updates: ${err.message}`);
            });
        } catch (error) {
          console.error('Error in navigation wrapper:', error);
          setError(`Navigation error: ${error instanceof Error ? error.message : String(error)}`);
        }
      }
    }, [route]);

    const checkForUpdates = async () => {
      try {
        // Check for updates with improved error handling
        const { termsNeedsUpdate, privacyNeedsUpdate } = await NavigationMonitorService.checkForUpdates();
        
        // Only show alert if updates are actually needed
        if (termsNeedsUpdate || privacyNeedsUpdate) {
          Alert.alert(
            'Update Required',
            `Please review and accept the ${termsNeedsUpdate ? 'Terms' : 'Privacy Policy'} updates to continue.`,
            [
              {
                text: 'Review',
                onPress: () => {
                  navigation.navigate(
                    termsNeedsUpdate ? 'TermsAndConditions' : 'PrivacyPolicy',
                    { fromUpdate: true }
                  );
                },
              },
            ],
            { cancelable: false }
          );
        }
        
        return { termsNeedsUpdate, privacyNeedsUpdate };
      } catch (error) {
        console.error('Failed to check for terms/privacy updates:', error);
        // Don't throw here, just log the error and continue
        return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
      }
    };

    // If there's an error, show it but still render the component
    if (error) {
      console.warn('NavigationWrapper encountered an error:', error);
      // We could show an error UI here, but for now we'll just log it and continue
    }

    // Render the wrapped component without any loading overlay
    return (
      <View style={styles.container}>
        <WrappedComponent {...props} />
      </View>
    );
  };
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
});

export default withNavigationWrapper;

```

--------------------------------------------------------------------------------
/resources/standards/project_structure.md:
--------------------------------------------------------------------------------

```markdown
# React Native Project Structure

BluestoneApps recommends the following project structure for React Native applications:

```
project-name/
├── src/                    # Source code
│   ├── assets/             # Static assets (images, fonts, etc.)
│   ├── components/         # Reusable UI components
│   ├── config/             # Configuration files (API endpoints, constants)
│   ├── hooks/              # Custom React hooks
│   ├── navigation/         # Navigation configuration
│   ├── screens/            # Screen components
│   │   ├── PostLogin/      # Screens available after authentication
│   │   └── PreLogin/       # Authentication and onboarding screens
│   ├── services/           # Business logic services
│   ├── theme/              # Theme definitions (colors, spacing, etc.)
│   ├── types/              # TypeScript type definitions
│   └── utils/              # Utility functions
├── App.tsx                 # Root component
├── index.js                # Entry point
├── package.json            # Dependencies and scripts
└── README.md               # Project documentation
```

## Key Directories

### `src/assets`

Contains static assets such as images, fonts, and other media files used in the application.

### `src/components`

Reusable UI components that can be used across different screens. Each component is typically defined in its own file with associated styles.

### `src/config`

Configuration files for the application, including API endpoint definitions, environment variables, and other constants.

### `src/hooks`

Custom React hooks for shared logic, state management, and side effects.

### `src/navigation`

Navigation configuration using React Navigation, including drawer navigators, stack navigators, and navigation wrappers.

### `src/screens`

Screen components organized by authentication state:
- `PostLogin`: Screens that are accessible after user authentication
- `PreLogin`: Authentication screens, onboarding, and public screens

Each screen may have its own subdirectory containing the main screen component and related files (e.g., styles, subcomponents).

### `src/services`

Business logic, API communication, data transformation, and other services. Typically implemented as singleton classes with specific responsibilities.

### `src/theme`

Theme definitions including colors, typography, spacing, and other styling constants.

### `src/types`

TypeScript type definitions, interfaces, and type guards that are shared across the application. This can be a separate directory or included within the config directory depending on the project size.

### `src/utils`

Utility functions and helpers, including API utilities, formatting functions, and other shared logic.

## Best Practices

1. Use TypeScript for type safety and better developer experience
2. Implement functional components with React hooks
3. Keep components small and focused on a single responsibility
4. Extract business logic into services
5. Use consistent naming conventions (PascalCase for components, camelCase for functions)
6. Implement proper error handling in API calls and async operations
7. Use environment-specific configuration when necessary

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Calendar/EventDetails.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react';
import { View, Text, ScrollView, StyleSheet, useWindowDimensions } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import RenderHtml, { defaultSystemFonts } from 'react-native-render-html';
import { styles } from './EventDetailsStyles';
import { colors } from '../../../theme/colors';

const EventDetails = () => {
  const navigation = useNavigation();
  const route = useRoute();
  const event = route.params?.event;
  const { width } = useWindowDimensions();

  const formatTime = (timeStr: string) => {
    const [hours, minutes] = timeStr.split(':');
    const date = new Date();
    date.setHours(parseInt(hours, 10));
    date.setMinutes(parseInt(minutes, 10));
    return date.toLocaleTimeString('en-US', {
      hour: 'numeric',
      minute: '2-digit',
      hour12: true
    });
  };

  const formatDate = (dateString: string) => {
    const [year, month, day] = dateString.split('-').map(num => parseInt(num, 10));
    const date = new Date(year, month - 1, day);
    return date.toLocaleDateString('en-US', {
      weekday: 'long',
      year: 'numeric',
      month: 'long',
      day: 'numeric'
    });
  };

  // Define default rendering options
  const renderersProps = {
    img: {
      enableExperimentalPercentWidth: true
    }
  };

  const tagsStyles = {
    body: {
      color: colors.black,
      fontSize: 16,
      lineHeight: 24,
    },
    a: {
      color: colors.primary,
      textDecorationLine: 'underline',
    }
  };

  return (
    <View style={styles.container}>
      <ScrollView style={styles.content}>
        <Text style={styles.title}>{event.event_title}</Text>
        <Text style={styles.date}>{formatDate(event.event_date)}</Text>
        <Text style={styles.time}>
          {formatTime(event.event_from_time)} - {formatTime(event.event_to_time)}
        </Text>
        
        <View style={styles.section}>
          <Text style={styles.sectionTitle}>Location</Text>
          <Text style={styles.location}>
            {event.event_street_address}
            {event.event_apt_suite ? `\n${event.event_apt_suite}` : ''}
            {'\n'}
            {[
              event.event_city,
              event.event_state,
              event.event_zip
            ].filter(Boolean).join(', ')}
          </Text>
        </View>

        {event.event_content && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Description</Text>
            <RenderHtml
              contentWidth={width - 40}
              source={{ html: event.event_content }}
              renderersProps={renderersProps}
              tagsStyles={tagsStyles}
              systemFonts={defaultSystemFonts}
              baseStyle={styles.description}
              defaultTextProps={{
                selectable: true
              }}
            />
          </View>
        )}

        {event.event_price && (
          <View style={styles.section}>
            <Text style={styles.sectionTitle}>Price</Text>
            <Text style={styles.price}>${event.event_price}</Text>
          </View>
        )}
      </ScrollView>
    </View>
  );
};

export default EventDetails;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/VerifyEmail/VerifyEmailScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useRef } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  Alert,
  KeyboardAvoidingView,
  Platform,
} from 'react-native';
import axios from 'axios';
import { styles } from './Styles';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { API } from '../../../config/apiConfig';

const VerifyEmailScreen = ({ route, navigation }: any) => {
  const { registerData, otp } = route.params;
  const [otpValue, setOtpValue] = useState('');
  const inputRefs = useRef<Array<TextInput | null>>([]);

  const handleOtpChange = (value: string, index: number) => {
    const newOtp = otpValue.split('');
    newOtp[index] = value;
    const newOtpString = newOtp.join('');
    setOtpValue(newOtpString);

    // Move to next input if value is entered
    if (value && index < 3) {
      inputRefs.current[index + 1]?.focus();
    }
  };

  const handleSubmit = async () => {
    if (!otpValue || otpValue.length !== 4) {
      Alert.alert('Error', 'Please enter the complete OTP');
      return;
    }

    if (parseInt(otpValue) !== parseInt(otp)) {
      Alert.alert('Error', 'OTP does not match. Please try again.');
      return;
    }

    try {
      const response = await axios.post(
        `${API.BASE_URL}${API.ENDPOINTS.MOBILEAPI}/v1/register`,
        {
          ...registerData,
          user_otp: otpValue,
          sent_opt: otp,
          signup_step1_email_otp: 'done',
        }
      );

      if (response.data.loginInfo) {
        // Store login info in AsyncStorage
        await AsyncStorage.setItem('userToken', response.data.loginInfo.token);
        await AsyncStorage.setItem('userData', JSON.stringify(response.data.loginInfo));

        // Navigate to DrawerNavigator
        navigation.reset({
          index: 0,
          routes: [{ name: 'DrawerNavigator' }],
        });
      }
    } catch (error: any) {
      Alert.alert(
        'Error',
        error.response?.data?.msg || 'Unable to verify OTP. Please try again later.'
      );
    }
  };

  return (
    <KeyboardAvoidingView
      style={styles.container}
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
    >
      <View style={styles.header}>
        <Text style={styles.title}>Verify Email</Text>
        <Text style={styles.subtitle}>
          Please enter the verification code sent to your email
        </Text>
      </View>

      <View style={styles.otpContainer}>
        {[0, 1, 2, 3].map((index) => (
          <TextInput
            key={index}
            ref={(ref) => (inputRefs.current[index] = ref)}
            style={styles.otpInput}
            maxLength={1}
            keyboardType="number-pad"
            onChangeText={(value) => handleOtpChange(value, index)}
            value={otpValue[index] || ''}
          />
        ))}
      </View>

      <TouchableOpacity style={styles.button} onPress={handleSubmit}>
        <Text style={styles.buttonText}>Verify</Text>
      </TouchableOpacity>

      <TouchableOpacity
        style={styles.backButton}
        onPress={() => navigation.goBack()}
      >
        <Text style={styles.backButtonText}>Go Back</Text>
      </TouchableOpacity>
    </KeyboardAvoidingView>
  );
};

export default VerifyEmailScreen; 
```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/theme/theme.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Main theme configuration file
 * 
 * This file exports the complete theme object that combines all theme elements:
 * colors, typography, spacing, etc.
 */

import { colors } from './colors';
import { typography, typeScale } from './typography';
import { ViewStyle } from 'react-native';

// Spacing system in pixels
const spacing = {
  none: 0,
  xs: 4,
  sm: 8,
  md: 16,
  lg: 24,
  xl: 32,
  xxl: 48,
  xxxl: 64,
} as const;

// Border radius values
const borderRadius = {
  none: 0,
  xs: 2,
  sm: 4,
  md: 8,
  lg: 12,
  xl: 16,
  round: 9999, // For circular elements
} as const;

// Shadow styles
interface ShadowStyle {
  shadowColor: string;
  shadowOffset: { width: number; height: number };
  shadowOpacity: number;
  shadowRadius: number;
  elevation: number;
}

const shadows: Record<string, ShadowStyle> = {
  none: {
    shadowColor: 'transparent',
    shadowOffset: { width: 0, height: 0 },
    shadowOpacity: 0,
    shadowRadius: 0,
    elevation: 0,
  },
  xs: {
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    elevation: 1,
  },
  sm: {
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 2,
  },
  md: {
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 3 },
    shadowOpacity: 0.2,
    shadowRadius: 6,
    elevation: 3,
  },
  lg: {
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.2,
    shadowRadius: 8,
    elevation: 4,
  },
  xl: {
    shadowColor: colors.black,
    shadowOffset: { width: 0, height: 6 },
    shadowOpacity: 0.3,
    shadowRadius: 12,
    elevation: 6,
  },
};

// Z-index values for stacking elements
const zIndex = {
  background: -1,
  default: 0,
  headerContent: 5,
  header: 10,
  modal: 20,
  toast: 30,
  tooltip: 40,
  overlay: 50,
} as const;

// Opacity values
const opacity = {
  none: 0,
  light: 0.2,
  medium: 0.5,
  high: 0.8,
  full: 1,
} as const;

// Layout constants
const layout = {
  screenPadding: spacing.md,
  headerHeight: 56,
  tabBarHeight: 64,
  maxContentWidth: 680, // Maximum width for content on large screens
} as const;

// Animation timing constants
const animation = {
  durationShort: 150,
  durationMedium: 300,
  durationLong: 500,
  easingDefault: 'ease',
  easingAccelerate: 'ease-in',
  easingDecelerate: 'ease-out',
} as const;

// Screen size breakpoints
const breakpoints = {
  xs: 0,     // Extra small devices
  sm: 375,   // Small devices (phones)
  md: 768,   // Medium devices (tablets)
  lg: 1024,  // Large devices (laptops/desktops)
  xl: 1280,  // Extra large devices (large desktops)
} as const;

// Export the complete theme object
const theme = {
  colors,
  typography,
  typeScale,
  spacing,
  borderRadius,
  shadows,
  zIndex,
  opacity,
  layout,
  animation,
  breakpoints,
} as const;

export type Theme = typeof theme;
export type SpacingKey = keyof typeof spacing;
export type BorderRadiusKey = keyof typeof borderRadius;
export type ShadowKey = keyof typeof shadows;
export type ZIndexKey = keyof typeof zIndex;
export type OpacityKey = keyof typeof opacity;
export type BreakpointKey = keyof typeof breakpoints;

export default theme;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Posts/PostsScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import { View, Text, TouchableOpacity, ScrollView, ActivityIndicator, RefreshControl } from 'react-native';
import { styles } from './Styles';
import { storageService } from '../../../helper/storageService';
import { apiService } from '../../../helper/apiService';
import { colors } from '../../../theme/colors';

interface Post {
  post_id: string;
  post_title: string;
  post_content: string;
  post_date: string;
  featured_image?: string;
}

interface Category {
  category_id: string;
  category_name: string;
  posts: Post[];
}

interface ApiResponse {
  status: string;
  categories: Category[];
}

const PostsScreen = ({ navigation }: any) => {
  const [groupedPosts, setGroupedPosts] = useState<Category[]>([]);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);

  const loadPosts = async (fromRefresh = false) => {
    try {
      // Try to get posts from storage first
      let posts = await storageService.get('posts');
      
      // If no posts in storage or this is a refresh, fetch from API
      if (!posts || fromRefresh) {
        const response = await apiService.fetchAndStorePosts();
        if (response) {
          posts = response;
        }
      }

      if (posts && Array.isArray(posts)) {
        setGroupedPosts(posts);
      } else {
        console.log('No posts found or invalid format');
        setGroupedPosts([]);
      }
    } catch (error) {
      console.error('Error getting posts:', error);
      setGroupedPosts([]);
    } finally {
      setLoading(false);
      setRefreshing(false);
    }
  };

  useEffect(() => {
    loadPosts();
  }, []);

  const onRefresh = () => {
    setRefreshing(true);
    loadPosts(true);
  };

  const handlePostPress = (post: Post) => {
    navigation.navigate('Post', { 
      id: post.post_id,
      title: post.post_title 
    });
  };

  if (loading) {
    return (
      <View style={styles.loadingContainer}>
        <ActivityIndicator size="large" color={colors.primary} />
      </View>
    );
  }

  return (
    <ScrollView 
      style={styles.container}
      refreshControl={
        <RefreshControl
          refreshing={refreshing}
          onRefresh={onRefresh}
          colors={[colors.dark]}
        />
      }
    >

      {groupedPosts.length > 0 ? (
        <View style={styles.postsContainer}>
          {groupedPosts.map((category) => (
            <View key={category.category_id} style={styles.categorySection}>
              <Text style={styles.categoryTitle}>{category.category_name}</Text>
              {category.posts.map((post) => (
                <TouchableOpacity
                  key={post.post_id}
                  style={styles.postCard}
                  onPress={() => handlePostPress(post)}
                >
                  <Text style={styles.postTitle}>{post.post_title}</Text>
                  <Text style={styles.postDate}>
                    {new Date(post.post_date).toLocaleDateString()}
                  </Text>
                </TouchableOpacity>
              ))}
            </View>
          ))}
        </View>
      ) : (
        <View style={styles.emptyContainer}>
          <Text style={styles.emptyText}>No posts available</Text>
        </View>
      )}
    </ScrollView>
  );
};

export default PostsScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/navigation/TabNavigator.tsx:
--------------------------------------------------------------------------------

```typescript
import React from 'react';
import { View } from 'react-native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import { DrawerActions, useNavigation, useRoute, NavigationProp, ParamListBase } from '@react-navigation/native';
import { colors } from '../theme/colors';

type TabParamList = {
  Home: undefined;
  ContactTab: undefined;
  ProfileTab: undefined;
  CalendarTab: undefined;
  Menu: undefined;
};

const Tab = createBottomTabNavigator<TabParamList>();

const TabNavigator = () => {
  const navigation = useNavigation<NavigationProp<TabParamList>>();
  const route = useRoute();

  return (
    <Tab.Navigator
      screenOptions={{
        headerShown: false,
        tabBarShowLabel: false,
        tabBarStyle: {
          backgroundColor: colors.footerBg,
          borderTopWidth: 1,
          borderTopColor: colors.light,
        },
        tabBarActiveTintColor: colors.secondary,
        tabBarInactiveTintColor: colors.footerBg,
      }}
    >
      <Tab.Screen
        name="ProfileTab"
        component={View}
        listeners={{
          tabPress: (e) => {
            e.preventDefault();
            navigation.navigate('MyProfile');
          },
        }}
        options={{
          tabBarIcon: ({ focused, color }) => (
            <Icon
              name={focused ? 'person-outline' : 'person-outline'}
              size={24}
              color={route.name === 'MyProfile' ? colors.secondary : colors.footerFont}
            />
          ),
        }}
      />
      <Tab.Screen
        name="ContactTab"
        component={View}
        listeners={{
          tabPress: (e) => {
            e.preventDefault();
            navigation.navigate('Contact');
          },
        }}
        options={{
          tabBarIcon: ({ focused, color }) => (
            <Icon
              name={focused ? 'mail' : 'mail-outline'}
              size={24}
              color={route.name === 'Contact' ? colors.secondary : colors.footerFont}
            />
          ),
        }}
      />
      <Tab.Screen
        name="HomeTab"
        component={View}
        listeners={{
          tabPress: (e) => {
            e.preventDefault();
            navigation.navigate('Home');
          },
        }}
        options={{
          tabBarIcon: ({ focused, color }) => (
            <Icon
              name={focused ? 'home' : 'home-outline'}
              size={24}
              color={route.name === 'Home' ? colors.secondary : colors.footerFont}
            />
          ),
        }}
      />
      <Tab.Screen
        name="CalendarTab"
        component={View}
        listeners={{
          tabPress: (e) => {
            e.preventDefault();
            navigation.navigate('Calendar');
          },
        }}
        options={{
          tabBarIcon: ({ focused, color }) => (
            <Icon
              name={focused ? 'calendar' : 'calendar-outline'}
              size={24}
              color={route.name === 'Calendar' ? colors.secondary : colors.footerFont}
            />
          ),
        }}
      />
      <Tab.Screen
        name="Menu"
        component={View}
        listeners={{
          tabPress: (e) => {
            e.preventDefault();
            navigation.dispatch(DrawerActions.openDrawer());
          },
        }}
        options={{
          tabBarIcon: ({ focused, color }) => (
            <Icon
              name={focused ? 'menu' : 'menu-outline'}
              size={24}
              color={colors.footerFont}
            />
          ),
        }}
      />
    </Tab.Navigator>
  );
};

export default TabNavigator;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/components/ErrorBoundary.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { Component, ErrorInfo, ReactNode } from 'react';
import {
  SafeAreaView,
  ScrollView,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';

interface Props {
  children: ReactNode;
  fallback?: ReactNode;
}

interface State {
  hasError: boolean;
  error: Error | null;
  errorInfo: ErrorInfo | null;
}

/**
 * ErrorBoundary component to catch JavaScript errors anywhere in the child component tree.
 * It logs the errors and displays a fallback UI instead of crashing the whole app.
 */
class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = {
      hasError: false,
      error: null,
      errorInfo: null,
    };
  }

  static getDerivedStateFromError(error: Error): State {
    // Update state so the next render will show the fallback UI
    return {
      hasError: true,
      error,
      errorInfo: null,
    };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
    // Log the error to the console
    console.error('ErrorBoundary caught an error:', error, errorInfo);
    this.setState({
      errorInfo,
    });
    
    // You can also log the error to an error reporting service here
    // logErrorToService(error, errorInfo);
  }

  resetError = (): void => {
    this.setState({
      hasError: false,
      error: null,
      errorInfo: null,
    });
  };

  render(): ReactNode {
    if (this.state.hasError) {
      // Custom fallback UI
      if (this.props.fallback) {
        return this.props.fallback;
      }

      // Default fallback UI
      return (
        <SafeAreaView style={styles.container}>
          <ScrollView contentContainerStyle={styles.scrollContainer}>
            <View style={styles.errorContainer}>
              <Text style={styles.errorTitle}>Something went wrong</Text>
              
              <View style={styles.errorMessageContainer}>
                <Text style={styles.errorMessage}>
                  {this.state.error?.toString() || 'An unknown error occurred'}
                </Text>
              </View>
              
              {this.state.errorInfo && (
                <View style={styles.componentStackContainer}>
                  <Text style={styles.componentStackTitle}>Component Stack:</Text>
                  <Text style={styles.componentStack}>
                    {this.state.errorInfo.componentStack}
                  </Text>
                </View>
              )}
              
              <TouchableOpacity
                style={styles.resetButton}
                onPress={this.resetError}
              >
                <Text style={styles.resetButtonText}>Try Again</Text>
              </TouchableOpacity>
            </View>
          </ScrollView>
        </SafeAreaView>
      );
    }

    return this.props.children;
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#f8f9fa',
  },
  scrollContainer: {
    flexGrow: 1,
    padding: 20,
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  errorTitle: {
    fontSize: 24,
    fontWeight: 'bold',
    color: '#dc3545',
    marginBottom: 20,
    textAlign: 'center',
  },
  errorMessageContainer: {
    backgroundColor: '#fff',
    borderRadius: 8,
    padding: 15,
    width: '100%',
    marginBottom: 20,
    borderWidth: 1,
    borderColor: '#dee2e6',
  },
  errorMessage: {
    fontSize: 16,
    color: '#343a40',
    lineHeight: 22,
  },
  componentStackContainer: {
    backgroundColor: '#f1f3f5',
    borderRadius: 8,
    padding: 15,
    width: '100%',
    marginBottom: 20,
    borderWidth: 1,
    borderColor: '#dee2e6',
  },
  componentStackTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    color: '#495057',
    marginBottom: 10,
  },
  componentStack: {
    fontSize: 14,
    color: '#6c757d',
    fontFamily: 'Courier',
  },
  resetButton: {
    backgroundColor: '#007bff',
    paddingVertical: 12,
    paddingHorizontal: 24,
    borderRadius: 8,
    marginTop: 10,
  },
  resetButtonText: {
    color: '#fff',
    fontSize: 16,
    fontWeight: 'bold',
  },
});

export default ErrorBoundary;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/BluestoneAppsAI/BluestoneAppsAIScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native';
import { styles } from './Styles';
import axiosRequest from '../../../helper/axiosRequest';
import { API } from '../../../helper/config';
import HTML from 'react-native-render-html';
import { useWindowDimensions } from 'react-native';

const defaultSystemFonts = [
  'Arial',
  'Helvetica',
  'Helvetica Neue',
  'System',
  '-apple-system',
  'sans-serif',
];

const renderersProps = {
  img: {
    enableExperimentalPercentWidth: true,
  },
};

const BluestoneAppsAIScreen = ({ navigation }: any) => {
  const [showWelcomeMessage, setShowWelcomeMessage] = useState(true);
  const [question, setQuestion] = useState('');
  const [replyContent, setReplyContent] = useState('');
  const [aiWelcomeMessage, setAiWelcomeMessage] = useState('');
  const [isLoading, setIsLoading] = useState(false);
  const { width } = useWindowDimensions();

  useEffect(() => {
    getAIWelcome();
  }, []);

  const getAIWelcome = async () => {
    try {
      console.log('Fetching AI welcome message...');
      const response = await axiosRequest.get(
        `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.GET_AI_WELCOME}`
      );
      
      console.log('AI Welcome Response:', response?.data);
      if (response?.data?.status === "success") {
        console.log('Setting welcome message:', response.data.message);
        setAiWelcomeMessage(response.data.message);
      } else {
        console.log('No success status in response');
        setAiWelcomeMessage('Welcome to Bluestone AI! How can I help you today?');
      }
    } catch (error) {
      console.error('Error getting AI welcome message:', error);
      setAiWelcomeMessage('Welcome to Bluestone AI! How can I help you today?');
    }
  };

  const submitQuestion = async () => {
    if (!question.trim()) {
      return;
    }

    setIsLoading(true);
    try {
      console.log('Submitting question to ask_bluestoneai endpoint...');
      const response = await axiosRequest.post(
        `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.ASK_BLUESTONEAI}`,
        { question: question.trim() }
      );

      console.log('Question response:', response?.data);

      if (response?.data?.reply) {
        setReplyContent(response.data.reply);
        setShowWelcomeMessage(false);
        setQuestion('');
      } else {
        console.error('No reply in response');
      }
    } catch (error) {
      console.error('Error submitting question:', error);
    } finally {
      setIsLoading(false);
    }
  };

  const renderHtmlContent = (content: string) => {
    if (!content) return null;

    return (
      <HTML 
        source={{ html: content }} 
        contentWidth={width - 64}
        systemFonts={defaultSystemFonts}
        renderersProps={renderersProps}
        baseStyle={styles.htmlContent}
        tagsStyles={{
          p: styles.paragraph,
          h1: styles.heading1,
          h2: styles.heading2,
          body: { color: '#333' },
        }}
        enableExperimentalBRCollapsing
        enableExperimentalGhostLinesPrevention
      />
    );
  };

  return (
    <ScrollView style={styles.container}>
      <View style={styles.content}>
        {showWelcomeMessage ? (
          <View style={styles.messageContainer}>
            {aiWelcomeMessage ? (
              renderHtmlContent(aiWelcomeMessage)
            ) : (
              <Text style={styles.loadingText}>Loading welcome message...</Text>
            )}
          </View>
        ) : null}

        {replyContent ? (
          <View style={styles.messageContainer}>
            {renderHtmlContent(replyContent)}
          </View>
        ) : null}

        <View style={styles.inputContainer}>
          <TextInput
            style={styles.input}
            value={question}
            onChangeText={setQuestion}
            placeholder="Ask a question"
            multiline
          />
          <TouchableOpacity 
            style={styles.submitButton}
            onPress={submitQuestion}
            disabled={isLoading}
          >
            {isLoading ? (
              <ActivityIndicator color="#fff" />
            ) : (
              <Text style={styles.submitButtonText}>Submit</Text>
            )}
          </TouchableOpacity>
        </View>
      </View>
    </ScrollView>
  );
};

export default BluestoneAppsAIScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/MyProfile/MyProfileScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useCallback } from 'react';
import { View, Text, Image, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useFocusEffect } from '@react-navigation/native';
import Icon from 'react-native-vector-icons/Ionicons';
import { styles } from './Styles';

interface UserProfile {
  loginInfo: {
    first_name: string;
    last_name: string;
    email: string;
    phone: string;
    user_avatar?: string;
    display_name: string;
    city_state?: string;
  };
}

const MyProfileScreen = ({ navigation }: any) => {
  const [userInfo, setUserInfo] = useState<UserProfile | null>(null);
  const [isLoading, setIsLoading] = useState(true);

  const loadUserData = async () => {
    try {
      setIsLoading(true);
      console.log('Attempting to load user data...');
      
      const userDataString = await AsyncStorage.getItem('userData');
      console.log('Raw userData from AsyncStorage:', userDataString);
      
      if (!userDataString) {
        console.log('No userData found in AsyncStorage');
        setUserInfo(null);
        return;
      }

      const userData = JSON.parse(userDataString);
      console.log('Parsed userData:', userData);

      // Ensure the data has the expected structure
      if (!userData?.loginInfo) {
        console.error('Invalid user data structure:', userData);
        setUserInfo(null);
        return;
      }

      console.log('Setting valid user data:', userData);
      setUserInfo(userData);
    } catch (error) {
      console.error('Error loading user data:', error);
      setUserInfo(null);
    } finally {
      setIsLoading(false);
    }
  };

  useFocusEffect(
    useCallback(() => {
      loadUserData();
    }, [])
  );

  if (isLoading) {
    return (
      <View style={[styles.container, styles.centerContent]}>
        <ActivityIndicator size="large" color="#007AFF" />
      </View>
    );
  }

  if (!userInfo?.loginInfo) {
    return (
      <View style={[styles.container, styles.centerContent]}>
        <Text style={styles.errorText}>No user data available</Text>
      </View>
    );
  }

  const { loginInfo } = userInfo;

  return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        <View style={styles.avatarContainer}>
          {loginInfo.user_avatar ? (
            <Image source={{ uri: loginInfo.user_avatar }} style={styles.profileImage} />
          ) : (
            <Image 
              source={require('../../../assets/images/default_profile_pic.png')} 
              style={styles.profileImage}
            />
          )}
        </View>
        <Text style={styles.name}>{loginInfo.display_name}</Text>
        {loginInfo.city_state && (
          <Text style={styles.location}>{loginInfo.city_state}</Text>
        )}
      </View>

      <View style={styles.infoSection}>
        <View style={styles.infoItem}>
          <Icon name="person-outline" size={24} color="#666" style={styles.icon} />
          <View>
            <Text style={styles.label}>Full Name</Text>
            <Text style={styles.value}>
              {`${loginInfo.first_name} ${loginInfo.last_name}`}
            </Text>
          </View>
        </View>

        <View style={styles.infoItem}>
          <Icon name="call-outline" size={24} color="#666" style={styles.icon} />
          <View>
            <Text style={styles.label}>Mobile Number</Text>
            <Text style={styles.value}>{loginInfo.phone || 'Not provided'}</Text>
          </View>
        </View>

        <View style={styles.infoItem}>
          <Icon name="mail-outline" size={24} color="#666" style={styles.icon} />
          <View>
            <Text style={styles.label}>Email</Text>
            <Text style={styles.value}>{loginInfo.email}</Text>
          </View>
        </View>
      </View>

      <View style={styles.buttonContainer}>
        <TouchableOpacity
          style={styles.button}
          onPress={() => navigation.navigate('EditProfile')}
        >
          <Text style={styles.buttonText}>Edit Account</Text>
        </TouchableOpacity>

        <TouchableOpacity
          style={[styles.button, styles.secondaryButton]}
          onPress={() => navigation.navigate('ChangePassword')}
        >
          <Text style={[styles.buttonText, styles.secondaryButtonText]}>Change Password</Text>
        </TouchableOpacity>
      </View>
    </ScrollView>
  );
};

export default MyProfileScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/ForgotPassword/ForgotPasswordScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  Alert,
  Image,
} from 'react-native';
import axios from 'axios';
import { styles } from './Styles';
import { environment } from '../../../config/environment';

const ForgotPasswordScreen = ({ navigation }: any) => {
  const [step, setStep] = useState(1);
  const [email, setEmail] = useState('');
  const [otp, setOtp] = useState('');
  const [password, setPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');

  const handleSendEmail = async () => {
    try {
      const response = await axios.post(`${environment.apiURL}/custom/v1/forgotPassword`, {
        email: email
      });

      if (response.data.status === 'ok') {
        Alert.alert('Success', 'OTP sent to your email successfully!');
        setStep(2);
      } else {
        Alert.alert('Error', response.data.errormsg || 'Failed to send OTP');
      }
    } catch (error: any) {
      Alert.alert('Error', error.response?.data?.errormsg || 'An error occurred');
    }
  };

  const handleVerifyOTP = async () => {
    try {
      const response = await axios.post(`${environment.apiURL}/custom/v1/checkOtp`, {
        otp: otp,
        email: email
      });

      if (response.data.status === 'ok') {
        Alert.alert('Success', 'OTP verified successfully!');
        setStep(3);
      } else {
        Alert.alert('Error', response.data.errormsg || 'Invalid OTP');
      }
    } catch (error: any) {
      Alert.alert('Error', error.response?.data?.errormsg || 'An error occurred');
    }
  };

  const handleResetPassword = async () => {
    if (password !== confirmPassword) {
      Alert.alert('Error', 'Passwords do not match');
      return;
    }

    try {
      const response = await axios.post(`${environment.apiURL}/custom/v1/updatePassword`, {
        password: password,
        email: email
      });

      if (response.data.status === 'ok') {
        Alert.alert('Success', 'Password reset successfully!');
        navigation.navigate('Login');
      } else {
        Alert.alert('Error', response.data.errormsg || 'Failed to reset password');
      }
    } catch (error: any) {
      Alert.alert('Error', error.response?.data?.errormsg || 'An error occurred');
    }
  };

  return (
    <View style={styles.container}>
      <View style={styles.logoContainer}>
        <Image
          source={require('../../../assets/images/logo.png')}
          style={styles.logo}
        />
      </View>
      
      <Text style={styles.title}>Forgot Password</Text>

      {step === 1 && (
        <View>
          <TextInput
            style={styles.input}
            placeholder="Email"
            placeholderTextColor="#999"
            value={email}
            onChangeText={setEmail}
            keyboardType="email-address"
            autoCapitalize="none"
          />
          <TouchableOpacity style={styles.button} onPress={handleSendEmail}>
            <Text style={styles.buttonText}>Send OTP</Text>
          </TouchableOpacity>
        </View>
      )}

      {step === 2 && (
        <View>
          <TextInput
            style={styles.input}
            placeholder="Enter OTP"
            placeholderTextColor="#999"
            value={otp}
            onChangeText={setOtp}
            keyboardType="number-pad"
          />
          <TouchableOpacity style={styles.button} onPress={handleVerifyOTP}>
            <Text style={styles.buttonText}>Verify OTP</Text>
          </TouchableOpacity>
        </View>
      )}

      {step === 3 && (
        <View>
          <TextInput
            style={styles.input}
            placeholder="New Password"
            placeholderTextColor="#999"
            value={password}
            onChangeText={setPassword}
            secureTextEntry
          />
          <TextInput
            style={styles.input}
            placeholder="Confirm Password"
            placeholderTextColor="#999"
            value={confirmPassword}
            onChangeText={setConfirmPassword}
            secureTextEntry
          />
          <TouchableOpacity style={styles.button} onPress={handleResetPassword}>
            <Text style={styles.buttonText}>Reset Password</Text>
          </TouchableOpacity>
        </View>
      )}

      <TouchableOpacity
        style={styles.backToLoginContainer}
        onPress={() => navigation.navigate('Login')}
      >
        <Text style={styles.backToLoginText}>Back to Login</Text>
      </TouchableOpacity>
    </View>
  );
};

export default ForgotPasswordScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/NavigationMonitorService.ts:
--------------------------------------------------------------------------------

```typescript
import AsyncStorage from '@react-native-async-storage/async-storage';
import axiosRequest from '../helper/axiosRequest';
import { API } from '../helper/config';

const STORAGE_KEYS = {
  TERMS_DATE: 'accepted_terms_date',
  PRIVACY_DATE: 'accepted_privacy_date',
  INITIAL_CHECK_COMPLETED: 'terms_privacy_initial_check_completed'
};

const EXCLUDED_ROUTES = [
  'TermsAndConditions',
  'PrivacyPolicy',
  'Login',
  'SignUp',
  'ForgotPassword',
  'VerifyEmail'
];

export class NavigationMonitorService {
  static isExcludedRoute(routeName: string): boolean {
    return EXCLUDED_ROUTES.includes(routeName);
  }

  /**
   * Check if terms and privacy policy need updates
   * Improved to handle API errors and prevent constant prompts
   */
  static async checkForUpdates() {
    try {
      // Check if we've already completed the initial check
      const initialCheckCompleted = await AsyncStorage.getItem(STORAGE_KEYS.INITIAL_CHECK_COMPLETED);
      
      // Get stored dates
      const [storedTermsDate, storedPrivacyDate] = await Promise.all([
        AsyncStorage.getItem(STORAGE_KEYS.TERMS_DATE),
        AsyncStorage.getItem(STORAGE_KEYS.PRIVACY_DATE)
      ]);
      
      // If this is the first time checking and no dates are stored, store current dates
      if (!initialCheckCompleted && (!storedTermsDate || !storedPrivacyDate)) {
        const currentDate = new Date().toISOString();
        
        // Store current date for both terms and privacy
        if (!storedTermsDate) {
          await AsyncStorage.setItem(STORAGE_KEYS.TERMS_DATE, currentDate);
        }
        
        if (!storedPrivacyDate) {
          await AsyncStorage.setItem(STORAGE_KEYS.PRIVACY_DATE, currentDate);
        }
        
        // Mark initial check as completed
        await AsyncStorage.setItem(STORAGE_KEYS.INITIAL_CHECK_COMPLETED, 'true');
        
        // Return false for both to prevent showing update prompt on first run
        return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
      }
      
      // Initialize with default values
      let termsDate = null;
      let privacyDate = null;
      let termsError = false;
      let privacyError = false;
      
      // Fetch terms date with error handling
      try {
        const termsResponse = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_TERMS_DATE}`);
        if (termsResponse && termsResponse.data && termsResponse.data.date) {
          termsDate = termsResponse.data.date;
        } else {
          termsError = true;
        }
      } catch (error) {
        termsError = true;
      }
      
      // Fetch privacy date with error handling
      try {
        const privacyResponse = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_PRIVACY_DATE}`);
        if (privacyResponse && privacyResponse.data && privacyResponse.data.date) {
          privacyDate = privacyResponse.data.date;
        } else {
          privacyError = true;
        }
      } catch (error) {
        privacyError = true;
      }
      
      // If both API calls failed, skip update check
      if (termsError && privacyError) {
        return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
      }
      
      // Compare dates to determine if updates are needed
      const termsNeedsUpdate = termsDate && storedTermsDate 
        ? new Date(termsDate) > new Date(storedTermsDate)
        : false;
        
      const privacyNeedsUpdate = privacyDate && storedPrivacyDate
        ? new Date(privacyDate) > new Date(storedPrivacyDate)
        : false;
      
      return { termsNeedsUpdate, privacyNeedsUpdate };
    } catch (error) {
      // In case of any unexpected errors, return false to prevent blocking the user
      return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
    }
  }

  static async getTermsPublishedDate() {
    try {
      const response = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_TERMS_DATE}`);
      return response.data.date;
    } catch (error) {
      console.error('Error getting terms date:', error);
      return null; // Return null instead of current date as fallback
    }
  }

  static async getPrivacyPublishedDate() {
    try {
      const response = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_PRIVACY_DATE}`);
      return response.data.date;
    } catch (error) {
      console.error('Error getting privacy date:', error);
      return null; // Return null instead of current date as fallback
    }
  }

  static async storeAcceptanceDate(type: 'terms' | 'privacy') {
    const key = type === 'terms' ? STORAGE_KEYS.TERMS_DATE : STORAGE_KEYS.PRIVACY_DATE;
    await AsyncStorage.setItem(key, new Date().toISOString());
    console.log(`Stored ${type} acceptance date:`, new Date().toISOString());
  }
}
```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/AboutUs/AboutUsScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
import axiosRequest from '../../../helper/axiosRequest';
import { API } from '../../../helper/config';
import { WebView } from 'react-native-webview';
import { LoadingSpinner } from '../../../components/LoadingSpinner';
import { styles } from './Styles';

const AboutUsScreen = () => {
  const [aboutUsContent, setAboutUsContent] = useState<string>('');
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    getAboutUs();
  }, []);

  const cleanHtml = (html: string) => {
    // Extract content between <body> tags if present
    const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
    let content = bodyMatch ? bodyMatch[1] : html;

    // Remove scripts, links, and styles
    content = content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
    content = content.replace(/<link[^>]*>/gi, '');
    content = content.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '');

    // Remove WordPress specific comments
    content = content.replace(/<!--[\s\S]*?-->/g, '');
    
    // Clean up image tags
    content = content.replace(/loading="lazy"\s/g, '');
    content = content.replace(/decoding="async"\s/g, '');
    content = content.replace(/\sonerror="[^"]*"/g, '');

    return content;
  };

  const getAboutUs = async () => {
    setIsLoading(true);
    try {
      const response = await axiosRequest.post(
        `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.GET_ABOUTUS}`,
        {},
        {
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          }
        }
      );
      
      console.log('About Us API Response:', response);
      if (response?.data?.aboutus_content) {
        const cleanContent = cleanHtml(response.data.aboutus_content);
        const content = `
          <!DOCTYPE html>
          <html>
            <head>
              <meta charset="utf-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
              <style>
                * {
                  box-sizing: border-box;
                }
                body {
                  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
                  padding: 16px;
                  margin: 0;
                  color: #333;
                  font-size: 16px;
                  line-height: 1.5;
                  background-color: #ffffff;
                }
                img {
                  max-width: 100%;
                  height: auto;
                  display: block;
                  margin: 16px auto;
                  border-radius: 8px;
                }
                h2, h3 {
                  color: #000;
                  margin: 24px 0 16px 0;
                  text-align: center;
                  font-weight: bold;
                }
                h2 {
                  font-size: 24px;
                }
                h3 {
                  font-size: 20px;
                }
                h4 {
                  font-size: 16px;
                  color: #666;
                  margin: 8px 0 24px 0;
                  text-align: center;
                  font-weight: normal;
                }
                p {
                  margin: 16px 0;
                  color: #333;
                }
                .team-member {
                  text-align: center;
                  margin-bottom: 32px;
                }
              </style>
            </head>
            <body>
              <div class="content">
                ${cleanContent}
              </div>
            </body>
          </html>
        `;
        console.log('Final HTML:', content);
        setAboutUsContent(content);
      }
    } catch (error: any) {
      console.error('Error getting about us content:', error);
    } finally {
      setIsLoading(false);
    }
  };

  if (isLoading) {
    return <LoadingSpinner />;
  }

  return (
    <View style={styles.container}>

      <View style={styles.webViewContainer}>
        {aboutUsContent ? (
          <WebView
            source={{ html: aboutUsContent }}
            style={styles.webView}
            originWhitelist={['*']}
            onError={(syntheticEvent) => {
              const { nativeEvent } = syntheticEvent;
              console.warn('WebView error: ', nativeEvent);
            }}
            startInLoadingState={true}
            renderLoading={() => <LoadingSpinner />}
            showsVerticalScrollIndicator={true}
            bounces={true}
            automaticallyAdjustContentInsets={true}
            injectedJavaScript={`
              true; // Required by iOS
            `}
          />
        ) : (
          <Text style={styles.noContent}>No content available</Text>
        )}
      </View>
    </View>
  );
};

export default AboutUsScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/Legal/TermsAndConditionsScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useEffect, useState } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity, ActivityIndicator, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { colors } from '../../../theme/colors';
import { API } from '../../../helper/config';
import { NavigationMonitorService } from '../../../helper/NavigationMonitorService';
import axiosRequest from '../../../helper/axiosRequest';
import HTML from 'react-native-render-html';

interface TermsResponse {
  status: number;
  terms_page: Array<{
    post_title: string;
    post_content: string;
  }>;
}

const TermsAndConditionsScreen = ({ navigation, route }: any) => {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [content, setContent] = useState<string>('');
  const [title, setTitle] = useState<string>('');
  const fromUpdate = route.params?.fromUpdate || false;
  useEffect(() => {
    fetchTermsContent();
  }, []);

  const fetchTermsContent = async () => {
    try {
      const response = await axiosRequest.get<TermsResponse>(`${API.BASE_URL}/${API.ENDPOINTS.GET_TERMS_PAGE}`);
      
      if (response.data?.terms_page?.[0]) {
        setTitle(response.data.terms_page[0].post_title);
        setContent(response.data.terms_page[0].post_content);
      } else {
        setError('No terms content found');
      }
    } catch (err) {
      setError('Failed to load terms content');
      console.error('Error fetching terms:', err);
    } finally {
      setLoading(false);
    }
  };

  const handleAccept = async () => {
    try {
      await NavigationMonitorService.storeAcceptanceDate('terms');
      
      if (fromUpdate) {
        navigation.goBack();
      }
    } catch (err) {
      console.error('Error saving acceptance date:', err);
      Alert.alert('Error', 'Failed to save your acceptance. Please try again.');
    }
  };

  if (loading) {
    return (
      <SafeAreaView style={styles.container}>
        <View style={styles.loadingContainer}>
          <ActivityIndicator size="large" color={colors.primary} />
        </View>
      </SafeAreaView>
    );
  }

  if (error) {
    return (
      <SafeAreaView style={styles.container}>
        <View style={styles.errorContainer}>
          <Text style={styles.errorText}>{error}</Text>
          <TouchableOpacity style={styles.retryButton} onPress={fetchTermsContent}>
            <Text style={styles.retryButtonText}>Retry</Text>
          </TouchableOpacity>
        </View>
      </SafeAreaView>
    );
  }

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.header}>
        <TouchableOpacity 
          style={styles.backButton} 
          onPress={() => navigation.goBack()}
        >
          <Text style={styles.backButtonText}>←</Text>
        </TouchableOpacity>
        <Text style={styles.headerTitle}>{title || 'Terms and Conditions'}</Text>
      </View>
      <ScrollView style={styles.scrollView}>
        <View style={styles.content}>
          <HTML source={{ html: content }} contentWidth={300} />
        </View>
      </ScrollView>
      {fromUpdate && (
        <TouchableOpacity style={styles.acceptButton} onPress={handleAccept}>
          <Text style={styles.acceptButtonText}>Accept Terms</Text>
        </TouchableOpacity>
      )}
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  errorText: {
    fontSize: 16,
    color: 'red',
    textAlign: 'center',
    marginBottom: 20,
  },
  retryButton: {
    backgroundColor: colors.primary,
    padding: 10,
    borderRadius: 5,
  },
  retryButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
  },
  acceptButton: {
    backgroundColor: colors.primary,
    padding: 16,
    margin: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  acceptButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: '600',
  },
  container: {
    flex: 1,
    backgroundColor: '#FFFFFF',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#E5E5E5',
  },
  backButton: {
    padding: 8,
  },
  backButtonText: {
    fontSize: 24,
    color: colors.primary,
  },
  headerTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginLeft: 8,
    color: colors.primary,
  },
  scrollView: {
    flex: 1,
  },
  content: {
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
    color: colors.primary,
  },
  lastUpdated: {
    fontSize: 14,
    color: '#666',
    marginBottom: 20,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 10,
    color: colors.primary,
  },
  text: {
    fontSize: 16,
    lineHeight: 24,
    color: colors.primary,
    marginBottom: 15,
  },
});

export default TermsAndConditionsScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/Legal/PrivacyPolicyScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useEffect, useState } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity, ActivityIndicator, Alert } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { colors } from '../../../theme/colors';
import { API } from '../../../helper/config';
import { NavigationMonitorService } from '../../../helper/NavigationMonitorService';
import axiosRequest from '../../../helper/axiosRequest';
import HTML from 'react-native-render-html';

interface PrivacyResponse {
  status: number;
  privacy_page: Array<{
    post_title: string;
    post_content: string;
  }>;
}

const PrivacyPolicyScreen = ({ navigation, route }: any) => {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [content, setContent] = useState<string>('');
  const [title, setTitle] = useState<string>('');
  const fromUpdate = route.params?.fromUpdate || false;
  useEffect(() => {
    fetchPrivacyContent();
  }, []);

  const fetchPrivacyContent = async () => {
    try {
      const response = await axiosRequest.get<PrivacyResponse>(`${API.BASE_URL}/${API.ENDPOINTS.GET_PRIVACY_PAGE}`);
      
      if (response.data?.privacy_page?.[0]) {
        setTitle(response.data.privacy_page[0].post_title);
        setContent(response.data.privacy_page[0].post_content);
      } else {
        setError('No privacy policy content found');
      }
    } catch (err) {
      setError('Failed to load privacy policy content');
      console.error('Error fetching privacy policy:', err);
    } finally {
      setLoading(false);
    }
  };

  const handleAccept = async () => {
    try {
      await NavigationMonitorService.storeAcceptanceDate('privacy');
      
      if (fromUpdate) {
        navigation.goBack();
      }
    } catch (err) {
      console.error('Error saving acceptance date:', err);
      Alert.alert('Error', 'Failed to save your acceptance. Please try again.');
    }
  };

  if (loading) {
    return (
      <SafeAreaView style={styles.container}>
        <View style={styles.loadingContainer}>
          <ActivityIndicator size="large" color={colors.primary} />
        </View>
      </SafeAreaView>
    );
  }

  if (error) {
    return (
      <SafeAreaView style={styles.container}>
        <View style={styles.errorContainer}>
          <Text style={styles.errorText}>{error}</Text>
          <TouchableOpacity style={styles.retryButton} onPress={fetchPrivacyContent}>
            <Text style={styles.retryButtonText}>Retry</Text>
          </TouchableOpacity>
        </View>
      </SafeAreaView>
    );
  }

  return (
    <SafeAreaView style={styles.container}>
      <View style={styles.header}>
        <TouchableOpacity 
          style={styles.backButton} 
          onPress={() => navigation.goBack()}
        >
          <Text style={styles.backButtonText}>←</Text>
        </TouchableOpacity>
        <Text style={styles.headerTitle}>{title || 'Privacy Policy'}</Text>
      </View>
      <ScrollView style={styles.scrollView}>
        <View style={styles.content}>
          <HTML source={{ html: content }} contentWidth={300} />
        </View>
      </ScrollView>
      {fromUpdate && (
        <TouchableOpacity style={styles.acceptButton} onPress={handleAccept}>
          <Text style={styles.acceptButtonText}>Accept Privacy Policy</Text>
        </TouchableOpacity>
      )}
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  errorText: {
    fontSize: 16,
    color: 'red',
    textAlign: 'center',
    marginBottom: 20,
  },
  retryButton: {
    backgroundColor: colors.primary,
    padding: 10,
    borderRadius: 5,
  },
  retryButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
  },
  acceptButton: {
    backgroundColor: colors.primary,
    padding: 16,
    margin: 16,
    borderRadius: 8,
    alignItems: 'center',
  },
  acceptButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: '600',
  },
  container: {
    flex: 1,
    backgroundColor: '#FFFFFF',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#E5E5E5',
  },
  backButton: {
    padding: 8,
  },
  backButtonText: {
    fontSize: 24,
    color: colors.primary,
  },
  headerTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginLeft: 8,
    color: colors.primary,
  },
  scrollView: {
    flex: 1,
  },
  content: {
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
    color: colors.primary,
  },
  lastUpdated: {
    fontSize: 14,
    color: '#666',
    marginBottom: 20,
  },
  sectionTitle: {
    fontSize: 18,
    fontWeight: '600',
    marginTop: 20,
    marginBottom: 10,
    color: colors.primary,
  },
  text: {
    fontSize: 16,
    lineHeight: 24,
    color: colors.primary,
    marginBottom: 15,
  },
});

export default PrivacyPolicyScreen;

```

--------------------------------------------------------------------------------
/resources/standards/component_design.md:
--------------------------------------------------------------------------------

```markdown
# Component Design Standards

BluestoneApps follows these standards for designing React Native components.

## Component Structure

### Flat Component Organization

We use a flat component organization structure with all reusable components placed directly in the components directory:

```
src/
└── components/
    ├── Button.tsx
    ├── ErrorBoundary.tsx
    ├── LoadingSpinner.tsx
    └── UpdateModal.tsx
```

Screen-specific components may be placed within their respective screen directories when they are not meant to be reused across the application.

## Component Implementation

### Functional Components with TypeScript

We use functional components with TypeScript interfaces for props:

```typescript
// src/components/Button.tsx
import React from 'react';
import {
  TouchableOpacity,
  Text,
  StyleSheet,
  ViewStyle,
  TextStyle,
  ActivityIndicator,
} from 'react-native';

interface ButtonProps {
  title: string;
  onPress: () => void;
  style?: ViewStyle;
  textStyle?: TextStyle;
  loading?: boolean;
  disabled?: boolean;
}

export const Button: React.FC<ButtonProps> = ({
  title,
  onPress,
  style,
  textStyle,
  loading = false,
  disabled = false,
}) => {
  return (
    <TouchableOpacity
      style={[
        styles.button,
        style,
        disabled && styles.disabledButton,
      ]}
      onPress={onPress}
      disabled={disabled || loading}
    >
      {loading ? (
        <ActivityIndicator color="#fff" />
      ) : (
        <Text style={[styles.text, textStyle]}>{title}</Text>
      )}
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  button: {
    backgroundColor: '#007AFF',
    paddingVertical: 12,
    paddingHorizontal: 24,
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
  },
  text: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: '600',
  },
  disabledButton: {
    backgroundColor: '#CCCCCC',
  },
});
```

### Inline Styles

For simpler components, we define styles within the same file using StyleSheet.create(). For more complex components or screens, we may use a separate Styles.ts file in the same directory.

```typescript
// Example of styles in a separate file (for a screen component)
// src/screens/PostLogin/BluestoneAppsAI/Styles.ts
import { StyleSheet } from 'react-native';

export const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#FFFFFF',
  },
  header: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 16,
  },
  // Other styles...
});
```

## Component Best Practices

### 1. Props and TypeScript Interfaces

- Use TypeScript interfaces for prop typing
- Provide default values for optional props
- Use optional chaining and nullish coalescing for safer prop access

```typescript
// Example of proper TypeScript interface usage
interface LoadingSpinnerProps {
  size?: 'small' | 'large';
  color?: string;
  text?: string;
}

export const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
  size = 'large',
  color = '#007AFF',
  text,
}) => {
  // Component implementation
};
```

### 2. Error Handling

- Implement error boundaries to catch and handle component errors
- Use try/catch blocks for error handling in async operations
- Provide meaningful feedback to users when errors occur

```typescript
// Example of an error boundary component
import React, { Component, ErrorInfo, ReactNode } from 'react';
import { View, Text, StyleSheet } from 'react-native';

interface ErrorBoundaryProps {
  children: ReactNode;
  fallback?: ReactNode;
}

interface ErrorBoundaryState {
  hasError: boolean;
  error: Error | null;
}

export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props);
    this.state = { hasError: false, error: null };
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
    console.error('Component error:', error, errorInfo);
  }

  render(): ReactNode {
    if (this.state.hasError) {
      if (this.props.fallback) {
        return this.props.fallback;
      }
      return (
        <View style={styles.errorContainer}>
          <Text style={styles.errorText}>Something went wrong</Text>
        </View>
      );
    }
    return this.props.children;
  }
}
```

### 3. State Management

- Use useState and useEffect hooks for component-level state
- Extract complex state logic into custom hooks
- Use AsyncStorage for persistent data storage
- Consider context API for state that needs to be shared across components

### 4. Performance Considerations

- Memoize expensive calculations with useMemo
- Use useCallback for event handlers passed to child components
- Implement proper list rendering with FlatList or SectionList
- Avoid unnecessary re-renders by using React.memo when appropriate

### 5. Accessibility

- Provide accessible labels for interactive elements
- Ensure sufficient color contrast
- Support dynamic text sizes
- Test with screen readers
- Ensure adequate color contrast

### 6. Testing

- Write unit tests for component logic
- Use snapshot testing for UI consistency
- Test user interactions

## Component Documentation

Document components with JSDoc comments:

```typescript
/**
 * Primary button component for user actions.
 * 
 * @example
 * <Button 
 *   title="Sign Up" 
 *   onPress={handleSignUp} 
 *   variant="primary" 
 * />
 */
export const Button: React.FC<ButtonProps> = (/* ... */) => {
  // ...
};
```

```

--------------------------------------------------------------------------------
/resources/standards/api_communication.md:
--------------------------------------------------------------------------------

```markdown
# API Communication Standards

BluestoneApps follows these standards for API communication in React Native applications.

## Structure

### API Configuration and Utilities

We use a structured approach to API communication with the following key files:

```
src/
├── config/
│   ├── apiConfig.ts       # API endpoint definitions and configuration
│   └── environment.ts     # Environment-specific configuration
├── services/
    ├── apiService.ts      # Core API service with fetch methods
    ├── authService.ts     # Authentication-related API calls
    ├── userService.ts     # User-related API calls
    └── ...                # Other domain-specific services
```

## API Configuration

We define API endpoints and configuration in dedicated files:

```typescript
// src/config/environment.ts
export const environment = {
  server: 'api.example.com',
  isProduction: true,
  version: '1.0.0',
};

// src/config/apiConfig.ts
import { environment } from './environment';

export const API = {
  BASE_URL: `https://${environment.server}/`,
  ENDPOINTS: {
    LOGIN: 'auth/login',
    REGISTER: 'auth/register',
    USER_PROFILE: 'user/profile',
    MOBILE_API: 'wp-json/mobileapi/v1/',
    // Other endpoints
  },
  TIMEOUT: 30000,
};

// Optional: Define types for API responses
export interface ApiResponse<T> {
  status: string;
  message?: string;
  data?: T;
}
```

## API Service Implementation

We use a centralized API service with fetch-based methods:

```typescript
// src/services/apiService.ts
import { storageService } from './storageService';
import { environment } from '../config/environment';

const BASE_URL = `https://${environment.server}/`;
const MOBILE_API = `${BASE_URL}wp-json/mobileapi/v1/`;

interface ApiResponse {
  status: string;
  errormsg: string;
  error_code: string;
  data?: any;
}

class ApiService {
  async getData(endpoint: string) {
    try {
      console.log('Fetching from:', MOBILE_API + endpoint);
      const response = await fetch(MOBILE_API + endpoint);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      return data;
    } catch (error) {
      console.error('Error fetching data:', error);
      throw error;
    }
  }

  async sendData(endpoint: string, data: any) {
    const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
    const payload = {
      ...(typeof data === 'object' ? data : { value: data }),
      timezone,
    };

    try {
      const response = await fetch(MOBILE_API + endpoint, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(payload),
      });

      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }

      const result = await response.json();
      return result;
    } catch (error) {
      console.error('Error sending data:', error);
      throw error;
    }
  }
}

export const apiService = new ApiService();
```

## Domain-Specific Services

We create separate service files for different domains:

```typescript
// src/services/authService.ts
import { apiService } from './apiService';
import { storageService } from './storageService';

class AuthService {
  async login(email: string, password: string) {
    try {
      const response = await apiService.sendData('login', { email, password });
      
      if (response.status === 'ok' && response.token) {
        await storageService.set('userToken', response.token);
        await storageService.set('user', response.user);
        return response;
      }
      
      throw new Error(response.errormsg || 'Login failed');
    } catch (error) {
      console.error('Login error:', error);
      throw error;
    }
  }

  async logout() {
    try {
      await storageService.remove('userToken');
      await storageService.remove('user');
      return true;
    } catch (error) {
      console.error('Logout error:', error);
      throw error;
    }
  }
}

export const authService = new AuthService();
```

## Error Handling

We implement consistent error handling across all API calls:

1. Log errors for debugging
2. Use try/catch blocks for all async operations
3. Provide meaningful error messages
4. Handle specific error types appropriately

## Example Usage in Components

```typescript
// Example in a screen component
import React, { useState } from 'react';
import { View, Alert } from 'react-native';
import { authService } from '../services/authService';
import { Button } from '../components/Button';

const LoginScreen = ({ navigation }) => {
  const [loading, setLoading] = useState(false);

  const handleLogin = async (email: string, password: string) => {
    try {
      setLoading(true);
      await authService.login(email, password);
      navigation.navigate('Home');
    } catch (error) {
      Alert.alert('Login Failed', error instanceof Error ? error.message : 'Unknown error');
    } finally {
      setLoading(false);
    }
  };

  return (
    <View>
      {/* Form fields */}
      <Button 
        title="Login" 
        onPress={() => handleLogin('[email protected]', 'password')} 
        loading={loading} 
      />
    </View>
  );
};
```

## Best Practices

1. Use TypeScript interfaces for request and response types
2. Implement proper error handling for all API calls
3. Store authentication tokens securely
4. Use environment-specific configuration
5. Log API calls and errors for debugging
6. Implement retry logic for important operations
7. Handle offline scenarios gracefully

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/AboutUs.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useEffect, useState } from 'react';
import { View, Text, ScrollView, StyleSheet, Alert } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import axiosRequest from '../helper/axiosRequest';
import { API } from '../helper/config';
import { Button } from '../components/Button';
import HTML from 'react-native-render-html';
import { useWindowDimensions } from 'react-native';
import { LoadingSpinner } from '../components/LoadingSpinner';

export const AboutUs = () => {
  const [aboutUsContent, setAboutUsContent] = useState<string>('');
  const [userId, setUserId] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const navigation = useNavigation();
  const { width } = useWindowDimensions();

  useEffect(() => {
    getAboutUs();
    getUserData();
  }, []);

  const getUserData = async () => {
    try {
      const userDataString = await AsyncStorage.getItem('userData');
      if (userDataString) {
        const userData = JSON.parse(userDataString);
        setUserId(userData.user_id);
      }
    } catch (error) {
      console.error('Error getting user data:', error);
    }
  };

  const getAboutUs = async () => {
    setIsLoading(true);
    try {
      const response = await axiosRequest.post(
        `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.GET_ABOUTUS}`,
        {},
        {
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          }
        }
      );
      setAboutUsContent(response.aboutus_content);
    } catch (error: any) {
      console.error('Error getting about us content:', error);
      Alert.alert('Error', 'Failed to load about us content');
    } finally {
      setIsLoading(false);
    }
  };

  const confirmDeleteAccount = () => {
    Alert.alert(
      'Delete Account',
      'This action cannot be undone. Are you sure you want to delete your account?',
      [
        {
          text: 'Cancel',
          style: 'cancel'
        },
        {
          text: 'Delete',
          onPress: deleteAccount,
          style: 'destructive'
        }
      ]
    );
  };

  const deleteAccount = async () => {
    if (!userId) {
      Alert.alert('Error', 'User ID not found');
      return;
    }

    setIsLoading(true);
    try {
      const response = await axiosRequest.post(
        `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.DELETE_USER}`,
        { user_id: userId },
        {
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          }
        }
      );

      if (response.status === 'success') {
        Alert.alert(
          'Account Deleted',
          'Thank you for using our app.',
          [
            {
              text: 'OK',
              onPress: async () => {
                try {
                  await AsyncStorage.clear();
                } catch (err) {
                  console.warn('Error clearing storage:', err);
                  // Continue even if clearing fails
                } finally {
                  navigation.reset({
                    index: 0,
                    routes: [{ name: 'Login' }],
                  });
                }
              }
            }
          ]
        );
      } else {
        throw new Error(response.message || 'Failed to delete account');
      }
    } catch (error: any) {
      console.error('Error deleting account:', error);
      Alert.alert('Error', 'Something went wrong. Please try again later.');
      try {
        await AsyncStorage.clear();
      } catch (err) {
        console.warn('Error clearing storage:', err);
        // Continue even if clearing fails
      } finally {
        navigation.reset({
          index: 0,
          routes: [{ name: 'Login' }],
        });
      }
    } finally {
      setIsLoading(false);
    }
  };

  if (isLoading) {
    return <LoadingSpinner />;
  }

  return (
    <View style={styles.container}>
      <ScrollView contentContainerStyle={styles.scrollContent}>
        {aboutUsContent ? (
          <HTML 
            source={{ html: aboutUsContent }} 
            contentWidth={width}
            tagsStyles={{
              p: styles.paragraph,
              h1: styles.heading,
              h2: styles.heading,
              h3: styles.heading,
              a: styles.link
            }}
          />
        ) : (
          <Text style={styles.noContent}>No content available</Text>
        )}
      </ScrollView>
      <View style={styles.buttonContainer}>
        <Button 
          title="Delete Account" 
          onPress={confirmDeleteAccount}
          style={styles.deleteButton}
          textStyle={styles.deleteButtonText}
        />
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  },
  scrollContent: {
    padding: 16,
    paddingBottom: 80
  },
  paragraph: {
    fontSize: 16,
    lineHeight: 24,
    color: '#333',
    marginBottom: 16
  },
  heading: {
    fontSize: 20,
    fontWeight: 'bold',
    color: '#000',
    marginBottom: 16,
    marginTop: 8
  },
  link: {
    color: '#007AFF'
  },
  noContent: {
    fontSize: 16,
    color: '#666',
    textAlign: 'center',
    marginTop: 20
  },
  buttonContainer: {
    padding: 16,
    backgroundColor: '#fff',
    borderTopWidth: 1,
    borderTopColor: '#eee',
    position: 'absolute',
    bottom: 0,
    left: 0,
    right: 0
  },
  deleteButton: {
    backgroundColor: '#FF3B30'
  },
  deleteButtonText: {
    color: '#fff'
  }
});

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/hooks/useForm.ts:
--------------------------------------------------------------------------------

```typescript
import { useState, useCallback, useMemo } from 'react';

/**
 * Form field configuration
 */
interface FormField<T> {
  value: T;
  error?: string;
  touched: boolean;
  required?: boolean;
  validator?: (value: T) => string | undefined;
}

/**
 * Form state containing fields
 */
type FormState<T extends Record<string, any>> = {
  [K in keyof T]: FormField<T[K]>;
};

/**
 * Form values extracted from form state
 */
type FormValues<T extends Record<string, any>> = {
  [K in keyof T]: T[K];
};

/**
 * Form errors extracted from form state
 */
type FormErrors<T extends Record<string, any>> = {
  [K in keyof T]?: string;
};

/**
 * Custom hook for form state management
 * 
 * @param initialValues Initial values for the form
 * @param validators Optional validators for form fields
 * @returns Form state and helper functions
 * 
 * @example
 * ```tsx
 * const { values, errors, touched, handleChange, handleBlur, handleSubmit, isValid } = useForm({
 *   email: '',
 *   password: '',
 * }, {
 *   email: (value) => (!value ? 'Email is required' : !isValidEmail(value) ? 'Invalid email format' : undefined),
 *   password: (value) => (!value ? 'Password is required' : value.length < 6 ? 'Password too short' : undefined),
 * });
 * ```
 */
function useForm<T extends Record<string, any>>(
  initialValues: T,
  validators?: Partial<Record<keyof T, (value: any) => string | undefined>>,
  requiredFields?: Array<keyof T>
) {
  // Create initial form state
  const createInitialState = (): FormState<T> => {
    const state: Partial<FormState<T>> = {};
    
    for (const key in initialValues) {
      if (Object.prototype.hasOwnProperty.call(initialValues, key)) {
        state[key] = {
          value: initialValues[key],
          touched: false,
          required: requiredFields?.includes(key) ?? false,
          validator: validators?.[key],
        };
      }
    }
    
    return state as FormState<T>;
  };
  
  // State for form fields
  const [formState, setFormState] = useState<FormState<T>>(createInitialState());
  
  // Extract values from form state
  const values = useMemo(() => {
    const result: Partial<FormValues<T>> = {};
    
    for (const key in formState) {
      if (Object.prototype.hasOwnProperty.call(formState, key)) {
        result[key] = formState[key].value;
      }
    }
    
    return result as FormValues<T>;
  }, [formState]);
  
  // Extract errors from form state
  const errors = useMemo(() => {
    const result: Partial<FormErrors<T>> = {};
    
    for (const key in formState) {
      if (Object.prototype.hasOwnProperty.call(formState, key) && formState[key].error) {
        result[key] = formState[key].error;
      }
    }
    
    return result as FormErrors<T>;
  }, [formState]);
  
  // Extract touched state from form state
  const touched = useMemo(() => {
    const result: Partial<Record<keyof T, boolean>> = {};
    
    for (const key in formState) {
      if (Object.prototype.hasOwnProperty.call(formState, key)) {
        result[key] = formState[key].touched;
      }
    }
    
    return result as Record<keyof T, boolean>;
  }, [formState]);
  
  // Validate a single field
  const validateField = useCallback((name: keyof T, value: any): string | undefined => {
    const field = formState[name];
    
    // Required field validation
    if (field.required && (value === '' || value === null || value === undefined)) {
      return `${String(name)} is required`;
    }
    
    // Custom validator
    if (field.validator) {
      return field.validator(value);
    }
    
    return undefined;
  }, [formState]);
  
  // Handle field change
  const handleChange = useCallback((name: keyof T, value: any) => {
    setFormState(prev => ({
      ...prev,
      [name]: {
        ...prev[name],
        value,
        error: validateField(name, value),
      },
    }));
  }, [validateField]);
  
  // Handle field blur
  const handleBlur = useCallback((name: keyof T) => {
    setFormState(prev => ({
      ...prev,
      [name]: {
        ...prev[name],
        touched: true,
        error: validateField(name, prev[name].value),
      },
    }));
  }, [validateField]);
  
  // Reset form to initial values
  const resetForm = useCallback(() => {
    setFormState(createInitialState());
  }, []);
  
  // Validate all fields
  const validateForm = useCallback((): boolean => {
    let isValid = true;
    const newState = { ...formState };
    
    for (const key in formState) {
      if (Object.prototype.hasOwnProperty.call(formState, key)) {
        const error = validateField(key, formState[key].value);
        newState[key] = {
          ...newState[key],
          error,
          touched: true,
        };
        
        if (error) {
          isValid = false;
        }
      }
    }
    
    setFormState(newState);
    return isValid;
  }, [formState, validateField]);
  
  // Handle form submission
  const handleSubmit = useCallback((onSubmit: (values: FormValues<T>) => void) => {
    return (e?: React.FormEvent) => {
      if (e) {
        e.preventDefault();
      }
      
      const isValid = validateForm();
      
      if (isValid) {
        onSubmit(values);
      }
    };
  }, [validateForm, values]);
  
  // Check if form is valid
  const isValid = useMemo(() => {
    for (const key in formState) {
      if (Object.prototype.hasOwnProperty.call(formState, key)) {
        if (formState[key].error) {
          return false;
        }
        
        if (formState[key].required && 
            (formState[key].value === '' || 
             formState[key].value === null || 
             formState[key].value === undefined)) {
          return false;
        }
      }
    }
    
    return true;
  }, [formState]);
  
  return {
    values,
    errors,
    touched,
    handleChange,
    handleBlur,
    handleSubmit,
    resetForm,
    validateForm,
    isValid,
  };
}

export default useForm;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/SignUp/SignUpScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  Alert,
  Image,
  ScrollView,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import axios from 'axios';
import { styles } from './Styles.ts';
import { API } from '../../../helper/config';
import { colors } from '../../../theme/colors';

const SignUpScreen = ({ navigation }: any) => {
  console.log('SignUpScreen rendered');

  const [formData, setFormData] = useState({
    email: '',
    first_name: '',
    last_name: '',
    password: '',
    confirmPassword: '',
  });
  const [acceptTerms, setAcceptTerms] = useState(false);
  const [errors, setErrors] = useState<{ [key: string]: string }>({});

  const validateForm = () => {
    const newErrors: { [key: string]: string } = {};

    // Email validation
    const emailRegex = /^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/;
    if (!formData.email) {
      newErrors.email = 'Email is required';
    } else if (!emailRegex.test(formData.email)) {
      newErrors.email = 'Please enter a valid email';
    }

    // Name validation
    if (!formData.first_name) newErrors.first_name = 'First name is required';
    if (!formData.last_name) newErrors.last_name = 'Last name is required';

    // Password validation
    if (!formData.password) {
      newErrors.password = 'Password is required';
    } else if (formData.password.length < 5) {
      newErrors.password = 'Password must be at least 5 characters';
    }

    // Confirm password validation
    if (formData.password !== formData.confirmPassword) {
      newErrors.confirmPassword = 'Passwords do not match';
    }

    // Terms validation
    if (!acceptTerms) {
      newErrors.terms = 'Please accept the terms and conditions';
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleSignUp = async () => {
    if (!validateForm()) {
      return;
    }

    try {
      const response = await axios.post(
        `${API.BASE_URL}${API.ENDPOINTS.MOBILEAPI}/verifyemail_and_send_otp`,
        {
          ...formData,
          emailVerification: 'pending',
          acceptTermsConditions: acceptTerms,
        }
      );

      if (response.data.status === 'ok') {
        Alert.alert('Success', response.data.msg);
        navigation.navigate('VerifyEmail', {
          registerData: formData,
          otp: response.data.otp,
        });
      } else {
        Alert.alert('Error', response.data.msg || 'Registration failed');
      }
    } catch (error: any) {
      Alert.alert(
        'Error',
        error.response?.data?.msg || 'An error occurred during registration'
      );
    }
  };

  return (
    <View style={styles.container}>
      <ScrollView contentContainerStyle={styles.scrollContainer}>
        <View style={styles.logoContainer}>
          <Image
            source={require('../../../assets/images/logo.png')}
            style={styles.logo}
          />
        </View>

        <Text style={styles.title}>Sign Up</Text>

        <TextInput
          style={styles.input}
          placeholder="Email"
          placeholderTextColor="#2c3e50"
          value={formData.email}
          onChangeText={(text) => setFormData({ ...formData, email: text.toLowerCase() })}
          keyboardType="email-address"
          autoCapitalize="none"
        />
        {errors.email && <Text style={styles.errorText}>{errors.email}</Text>}

        <TextInput
          style={styles.input}
          placeholder="First Name"
          placeholderTextColor="#2c3e50"
          value={formData.first_name}
          onChangeText={(text) => setFormData({ ...formData, first_name: text })}
        />
        {errors.first_name && <Text style={styles.errorText}>{errors.first_name}</Text>}

        <TextInput
          style={styles.input}
          placeholder="Last Name"
          placeholderTextColor="#2c3e50"
          value={formData.last_name}
          onChangeText={(text) => setFormData({ ...formData, last_name: text })}
        />
        {errors.last_name && <Text style={styles.errorText}>{errors.last_name}</Text>}

        <TextInput
          style={styles.input}
          placeholder="Password"
          placeholderTextColor="#2c3e50"
          value={formData.password}
          onChangeText={(text) => setFormData({ ...formData, password: text })}
          secureTextEntry
        />
        {errors.password && <Text style={styles.errorText}>{errors.password}</Text>}

        <TextInput
          style={styles.input}
          placeholder="Confirm Password"
          placeholderTextColor="#2c3e50"
          value={formData.confirmPassword}
          onChangeText={(text) => setFormData({ ...formData, confirmPassword: text })}
          secureTextEntry
        />
        {errors.confirmPassword && <Text style={styles.errorText}>{errors.confirmPassword}</Text>}

        <View style={styles.checkboxContainer}>
          <TouchableOpacity
            style={[styles.customCheckbox, acceptTerms && styles.customCheckboxChecked]}
            onPress={() => setAcceptTerms(!acceptTerms)}
          >
            {acceptTerms && (
              <Icon name="checkmark" size={16} color="#fff" />
            )}
          </TouchableOpacity>
          <Text style={styles.checkboxLabel}>
            I accept the{' '}
            <Text 
              style={[styles.checkboxLabel, styles.link]}
              onPress={() => navigation.navigate('TermsAndConditions')}
            >
              Terms and Conditions
            </Text>
            {' '}and{' '}
            <Text 
              style={[styles.checkboxLabel, styles.link]}
              onPress={() => navigation.navigate('PrivacyPolicy')}
            >
              Privacy Policy
            </Text>
          </Text>
        </View>
        {errors.terms && <Text style={styles.errorText}>{errors.terms}</Text>}

        <TouchableOpacity style={styles.button} onPress={handleSignUp}>
          <Text style={styles.buttonText}>Sign Up</Text>
        </TouchableOpacity>

        <View style={styles.linkContainer}>
          <Text style={styles.linkText}>Already have an account?</Text>
          <TouchableOpacity onPress={() => navigation.navigate('Login')}>
            <Text style={styles.link}>Login</Text>
          </TouchableOpacity>
        </View>
      </ScrollView>
    </View>
  );
};

export default SignUpScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/Contact/ContactScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  ScrollView,
  StyleSheet,
  Alert,
  KeyboardAvoidingView,
  Platform,
  SafeAreaView,
  Keyboard,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { API } from '../../../config/apiConfig';
import axiosRequest from '../../../utils/axiosUtils';
import { styles } from './Styles';
import { colors } from '../../../theme/colors';

const ContactScreen = () => {
  const navigation = useNavigation();
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [phone, setPhone] = useState('');
  const [subject, setSubject] = useState('');
  const [message, setMessage] = useState('');
  const [isSubmitting, setIsSubmitting] = useState(false);

  useEffect(() => {
    loadUserData();
  }, []);

  const loadUserData = async () => {
    try {
      const userDataString = await AsyncStorage.getItem('userData');
      if (userDataString) {
        const userData = JSON.parse(userDataString);
        if (userData.userData) {
          setName(userData.userData.display_name || '');
          setEmail(userData.userData.user_email || '');
          setPhone(userData.userData.phone || '');
        }
      }
    } catch (error) {
      console.error('Error loading user data:', error);
    }
  };

  const handleSubmit = async () => {
    if (isSubmitting) return;

    if (!name || !email || !subject || !message) {
      Alert.alert('Error', 'Please fill in all required fields');
      return;
    }

    setIsSubmitting(true);
    Keyboard.dismiss();

    try {
      const userData = await AsyncStorage.getItem('userData');
      const token = userData ? JSON.parse(userData).token : null;
      
      // Create URL-encoded form data
      const params = new URLSearchParams();
      params.append('name', name.trim());
      params.append('email', email.trim());
      if (phone) params.append('phone', phone.trim());
      params.append('subject', subject.trim());
      params.append('message', message.trim());

      const response = await axiosRequest.post(`${API.ENDPOINTS.MOBILEAPI}/contact_us`, 
        params.toString(),
        {
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded',
            ...(token ? { 'Authorization': `Bearer ${token}` } : {})
          }
        }
      );

      if (response?.data?.success) {
        // Clear form
        setName('');
        setEmail('');
        setPhone('');
        setSubject('');
        setMessage('');
        
        // Show success and navigate
        Alert.alert(
          'Success',
          response.data.message || 'Your message has been sent successfully.',
          [{
            text: 'OK',
            onPress: () => navigation.navigate('Home'),
            style: 'default'
          }]
        );
      } else {
        Alert.alert('Error', response?.data?.message || 'Failed to send message. Please try again.');
      }
    } catch (error: any) {
      console.error('Contact submission error:', error.message);
      Alert.alert('Error', error.response?.data?.message || error.message || 'Failed to send message. Please try again.');
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <SafeAreaView style={styles.safeArea}>
      <KeyboardAvoidingView 
        style={styles.keyboardAvoidingView}
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
        keyboardVerticalOffset={Platform.OS === 'ios' ? 90 : 0}
      >
        <View style={styles.contentContainer}>
          <ScrollView
            style={styles.scrollView}
            contentContainerStyle={styles.scrollViewContent}
            keyboardShouldPersistTaps="handled"
            showsVerticalScrollIndicator={false}
          >
            <View style={styles.formContainer}>
              <Text style={styles.label}>Name *</Text>
              <TextInput
                style={styles.input}
                value={name}
                onChangeText={setName}
                placeholder="Enter your full name"
                placeholderTextColor={colors.dark}
                returnKeyType="next"
              />

              <Text style={styles.label}>Email *</Text>
              <TextInput
                style={styles.input}
                value={email}
                onChangeText={setEmail}
                placeholder="Enter your email"
                placeholderTextColor={colors.dark}
                keyboardType="email-address"
                autoCapitalize="none"
                returnKeyType="next"
              />

              <Text style={styles.label}>Phone</Text>
              <TextInput
                style={styles.input}
                value={phone}
                onChangeText={setPhone}
                placeholder="Enter your phone number"
                placeholderTextColor={colors.dark}
                keyboardType="phone-pad"
                returnKeyType="next"
              />

              <Text style={styles.label}>Subject *</Text>
              <TextInput
                style={styles.input}
                value={subject}
                onChangeText={setSubject}
                placeholder="Enter subject"
                placeholderTextColor={colors.dark}
                returnKeyType="next"
              />

              <Text style={styles.label}>Message *</Text>
              <TextInput
                style={[styles.input, styles.messageInput]}
                value={message}
                onChangeText={setMessage}
                placeholder="Enter a brief message"
                placeholderTextColor={colors.dark}
                multiline
                numberOfLines={4}
                returnKeyType="done"
                onSubmitEditing={Keyboard.dismiss}
              />
            </View>
          </ScrollView>

          <View style={styles.buttonWrapper}>
            <TouchableOpacity
              style={[styles.submitButton, isSubmitting && styles.submitButtonDisabled]}
              onPress={() => {
                Keyboard.dismiss();
                handleSubmit();
              }}
              disabled={isSubmitting}
            >
              <Text style={styles.submitButtonText}>
                {isSubmitting ? 'Sending...' : 'Send Message'}
              </Text>
            </TouchableOpacity>
          </View>
        </View>
      </KeyboardAvoidingView>
    </SafeAreaView>
  );
};

export default ContactScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/services/userService.ts:
--------------------------------------------------------------------------------

```typescript
import axiosRequest from './axiosRequest';
import { API } from './config';
import AsyncStorage from '@react-native-async-storage/async-storage';

interface UserProfile {
  first_name: string;
  last_name: string;
  email: string;
  phone: string;
  user_avatar?: string;
  access_token: string;
}

class UserService {
  async getProfile(): Promise<UserProfile> {
    try {
      const userToken = await AsyncStorage.getItem('userToken');
      if (!userToken) {
        throw new Error('No auth token found');
      }

      const response = await axiosRequest.post(`${API.ENDPOINTS.MOBILEAPI}/getProfile`, {
        token: userToken,
      });

      console.log('Profile API Response:', response);

      if (response.status === 'success' && response.data) {
        await AsyncStorage.setItem('userData', JSON.stringify(response.data));
        return response.data;
      }

      throw new Error(response.message || 'Failed to get profile');
    } catch (error) {
      console.error('Get profile error:', error);
      throw error;
    }
  }

  async changePassword(oldPassword: string, newPassword: string, confirmPassword: string): Promise<any> {
    try {
      const userDataString = await AsyncStorage.getItem('userData');
      if (!userDataString) {
        throw new Error('User data not found');
      }
      
      const userData = JSON.parse(userDataString);
      const token = userData.loginInfo?.token;
      const email = userData.loginInfo?.email;
      
      if (!token || !email) {
        throw new Error('User information not found');
      }

      const formData = {
        old_password: oldPassword,
        password: newPassword,
        token: token,
        email: email
      };

      console.log('Sending password change request:', formData);

      const response = await axiosRequest.post(
        `${API.ENDPOINTS.MOBILEAPI}/updatePassword`,
        formData,
        {
          headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          }
        }
      );

      console.log('Raw response:', response);
      console.log('Response data:', response.data);
      console.log('Response status:', response.status);

      // Handle both direct response and axios wrapped response
      const apiResponse = response.data || response;
      console.log('API response:', apiResponse);

      // If we have a successful response from the API
      if (apiResponse && (apiResponse.status === 'ok' || apiResponse.status === 'success')) {
        // Password was changed successfully, now try to re-login
        try {
          const loginResponse = await axiosRequest.post(
            API.ENDPOINTS.LOGIN,
            {
              email: email,
              password: newPassword
            },
            {
              headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded'
              }
            }
          );

          console.log('Re-login response:', loginResponse);

          if (loginResponse.data?.loginInfo?.token || loginResponse.loginInfo?.token) {
            const finalLoginData = loginResponse.data || loginResponse;
            await AsyncStorage.setItem('userData', JSON.stringify(finalLoginData));
            return { status: 'ok', message: 'Password changed successfully' };
          }

          // If we get here, login succeeded but didn't return expected data
          return { status: 'ok', message: 'Password changed successfully, please log in again' };
        } catch (loginError) {
          console.error('Re-login error:', loginError);
          // Even if re-login fails, password was changed successfully
          return { status: 'ok', message: 'Password changed successfully, please log in again' };
        }
      }

      // If we get here, the password change failed
      const errorMsg = apiResponse.errormsg || apiResponse.message || 'Failed to change password';
      throw new Error(errorMsg);
    } catch (error: any) {
      console.error('Change password error:', error);
      // If we have a successful response but hit this block, return success
      if (error.response?.data?.status === 'ok' || error.response?.status === 'ok') {
        return { status: 'ok', message: 'Password changed successfully' };
      }
      // Otherwise handle the error
      if (error.response?.data?.errormsg) {
        throw new Error(error.response.data.errormsg);
      } else if (error.response?.data?.message) {
        throw new Error(error.response.data.message);
      } else if (error.message) {
        throw error;
      }
      throw new Error('Failed to change password');
    }
  }

  async updateProfile(data: {
    first_name: string;
    last_name: string;
    phone: string;
    profile_img?: any;
  }): Promise<any> {
    try {
      const userDataString = await AsyncStorage.getItem('userData');
      if (!userDataString) {
        throw new Error('User data not found');
      }
      
      const userData = JSON.parse(userDataString);
      const token = userData.loginInfo?.token;
      
      if (!token) {
        throw new Error('User token not found');
      }

      const formData = new FormData();
      formData.append('first_name', data.first_name);
      formData.append('last_name', data.last_name);
      formData.append('phone', data.phone);
      formData.append('token', token);

      if (data.profile_img) {
        formData.append('profile_img', {
          uri: data.profile_img.uri,
          type: data.profile_img.type,
          name: data.profile_img.fileName || 'profile.jpg',
        });
      }

      const response = await axiosRequest.post(API.ENDPOINTS.UPDATE_PROFILE, formData, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });

      console.log('Raw API Response:', response);

      // The response might be wrapped in a data property
      const responseData = response.data || response;

      // Check if we have a successful response
      if (responseData.code === 200 && responseData.status === 'ok') {
        // The API returns the complete updated user data
        return responseData;
      }
      
      // If we have an error message from the API, use it
      if (responseData.errormsg) {
        throw new Error(responseData.errormsg);
      }
      
      throw new Error('Failed to update profile');
    } catch (error: any) {
      console.error('Update profile error:', error);
      // If it's an API error response
      if (error.response?.data?.errormsg) {
        throw new Error(error.response.data.errormsg);
      }
      // If it's our own error message
      if (error.message) {
        throw error;
      }
      // Generic error
      throw new Error('Failed to update profile');
    }
  }
}

export default new UserService();

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PreLogin/Login/LoginScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  Alert,
  Image,
  KeyboardAvoidingView,
  ScrollView,
  Platform,
} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import Icon from 'react-native-vector-icons/Ionicons';
import { styles } from './Styles';
import authService from '../../../helper/authService';
import { AuthError, LoginResponse } from '../../../helper/types';
import { StackNavigationProp } from '@react-navigation/stack';

type RootStackParamList = {
  Login: undefined;
  DrawerNavigator: undefined;
  ForgotPassword: undefined;
  SignUp: undefined;
};

type LoginScreenNavigationProp = StackNavigationProp<RootStackParamList, 'Login'>;

interface Props {
  navigation: LoginScreenNavigationProp;
}

const LoginScreen: React.FC<Props> = ({ navigation }) => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [rememberMe, setRememberMe] = useState(false);
  const [showPassword, setShowPassword] = useState(false);

  useEffect(() => {
    checkPreviousLogin();
  }, []);

  const checkPreviousLogin = async () => {
    try {
      const rememberMeStatus = await AsyncStorage.getItem('rememberMe');
      if (rememberMeStatus === 'true') {
        const savedEmail = await AsyncStorage.getItem('userEmail');
        const savedPassword = await AsyncStorage.getItem('userPassword');
        const userData = await AsyncStorage.getItem('userData');

        if (savedEmail && savedPassword && userData) {
          // If we have all the necessary data and Remember Me is true,
          // automatically navigate to DrawerNavigator
          navigation.replace('DrawerNavigator');
        } else {
          // If we're missing any data, clear everything to ensure a fresh state
          await AsyncStorage.removeItem('rememberMe');
          await AsyncStorage.removeItem('userEmail');
          await AsyncStorage.removeItem('userPassword');
          await AsyncStorage.removeItem('userData');
        }
      }
    } catch (error) {
      console.error('Error checking previous login:', error);
    }
  };

  const handleLogin = async () => {
    try {
      const trimmedEmail = email.trim();
      if (!trimmedEmail || !password) {
        Alert.alert('Error', 'Please enter both email and password');
        return;
      }

      // Basic email validation
      const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      if (!emailRegex.test(trimmedEmail)) {
        Alert.alert('Error', 'Please enter a valid email address');
        return;
      }

      console.log('Attempting login with:', { email: trimmedEmail });

      const response = await authService.login(trimmedEmail, password);
      
      if (response?.data?.loginInfo?.token) {
        await AsyncStorage.setItem('rememberMe', rememberMe.toString());
        // Store user credentials if remember me is checked
        if (rememberMe) {
          await AsyncStorage.setItem('userEmail', trimmedEmail);
          await AsyncStorage.setItem('userPassword', password);
        } else {
          // Clear stored credentials if remember me is unchecked
          await AsyncStorage.removeItem('userEmail');
          await AsyncStorage.removeItem('userPassword');
        }
        // Store data in the correct format expected by the profile screen
        const userData = { loginInfo: response.data.loginInfo };
        console.log('Storing userData:', userData);
        await AsyncStorage.setItem('userData', JSON.stringify(userData));
        console.log('Login successful, navigating to DrawerNavigator');
        navigation.replace('DrawerNavigator');
      } else {
        console.log('No token in response:', response);
        Alert.alert('Error', 'Invalid response from server');
      }
    } catch (error) {
      const authError = error as AuthError;
      console.error('Login error:', authError);
      Alert.alert(
        'Error',
        authError.response?.data?.message?.replace(/<[^>]*>/g, '') || 
        authError.response?.data?.errormsg || 
        'An error occurred during login. Please try again.'
      );
    }
  };

  return (
    <KeyboardAvoidingView 
      behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
      style={{ flex: 1 }}
    >
      <ScrollView 
        contentContainerStyle={styles.container}
        keyboardShouldPersistTaps="handled"
        showsVerticalScrollIndicator={false}
      >
        <View style={styles.logoContainer}>
          <Image
            source={require('../../../assets/images/logo.png')}
            style={styles.logo}
            resizeMode="contain"
          />
        </View>
        <Text style={styles.title}>Login</Text>
        <TextInput
          style={styles.input}
          placeholder="Email"
          placeholderTextColor="#2c3e50"
          value={email}
          onChangeText={(text) => setEmail(text.toLowerCase().trim())}
          keyboardType="email-address"
          autoCapitalize="none"
          autoCorrect={false}
          spellCheck={false}
        />
        <View style={styles.passwordContainer}>
          <TextInput
            style={[styles.input, { marginBottom: 0, color: '#2c3e50' }]}
            placeholder="Password"
            placeholderTextColor="#2c3e50"
            value={password}
            onChangeText={setPassword}
            secureTextEntry={!showPassword}
            autoCapitalize="none"
            autoCorrect={false}
          />
          <TouchableOpacity
            style={styles.eyeIcon}
            onPress={() => setShowPassword(!showPassword)}
          >
            <Icon
              name={showPassword ? 'eye-off-outline' : 'eye-outline'}
              size={24}
              color="#2c3e50"
            />
          </TouchableOpacity>
        </View>
        <View style={styles.checkboxContainer}>
          <TouchableOpacity
            style={[styles.customCheckbox, rememberMe && styles.customCheckboxChecked]}
            onPress={() => setRememberMe(!rememberMe)}
          >
            {rememberMe && (
              <Icon name="checkmark" size={16} color="#fff" />
            )}
          </TouchableOpacity>
          <Text style={styles.checkboxLabel}>Remember me</Text>
        </View>
        <TouchableOpacity style={styles.button} onPress={handleLogin}>
          <Text style={styles.buttonText}>Login</Text>
        </TouchableOpacity>
        <View style={styles.linkContainer}>
          <TouchableOpacity onPress={() => navigation.navigate('ForgotPassword')}>
            <Text style={styles.link}>Forgot Password?</Text>
          </TouchableOpacity>
          <TouchableOpacity onPress={() => navigation.navigate('SignUp')}>
            <Text style={styles.link}>Sign Up</Text>
          </TouchableOpacity>
        </View>
      </ScrollView>
    </KeyboardAvoidingView>
  );
};

export default LoginScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/theme/typography.ts:
--------------------------------------------------------------------------------

```typescript
/**
 * Typography styles for the application
 * 
 * This file defines all typography styles used throughout the app.
 * It establishes a consistent type system with predefined text styles.
 */

import { Platform, TextStyle } from 'react-native';
import { colors } from './colors';

// Font family definitions
const fontFamily = {
  // Primary font
  regular: Platform.OS === 'ios' ? 'System' : 'Roboto',
  medium: Platform.OS === 'ios' ? 'System' : 'Roboto-Medium',
  semiBold: Platform.OS === 'ios' ? 'System' : 'Roboto-Medium',
  bold: Platform.OS === 'ios' ? 'System' : 'Roboto-Bold',
  
  // Monospace font for code or technical content
  mono: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
} as const;

// Font size scale (in pixels)
const fontSize = {
  xs: 12,
  sm: 14,
  md: 16,
  lg: 18,
  xl: 20,
  xxl: 24,
  xxxl: 28,
  xxxxl: 32,
  display: 40,
  jumbo: 48,
} as const;

// Line height scale (multiplier of font size)
const lineHeightMultiplier = {
  tight: 1.2,    // For headings
  normal: 1.4,   // For body text
  relaxed: 1.6,  // For readable paragraphs
} as const;

// Calculate line heights based on font sizes
const lineHeight = {
  xs: Math.round(fontSize.xs * lineHeightMultiplier.normal),
  sm: Math.round(fontSize.sm * lineHeightMultiplier.normal),
  md: Math.round(fontSize.md * lineHeightMultiplier.normal),
  lg: Math.round(fontSize.lg * lineHeightMultiplier.normal),
  xl: Math.round(fontSize.xl * lineHeightMultiplier.normal),
  xxl: Math.round(fontSize.xxl * lineHeightMultiplier.tight),
  xxxl: Math.round(fontSize.xxxl * lineHeightMultiplier.tight),
  xxxxl: Math.round(fontSize.xxxxl * lineHeightMultiplier.tight),
  display: Math.round(fontSize.display * lineHeightMultiplier.tight),
  jumbo: Math.round(fontSize.jumbo * lineHeightMultiplier.tight),
} as const;

// Font weight definitions
const fontWeight = {
  regular: '400',
  medium: '500',
  semiBold: '600',
  bold: '700',
} as const;

// Letter spacing (tracking)
const letterSpacing = {
  tight: -0.5,
  normal: 0,
  wide: 0.5,
  extraWide: 1,
} as const;

// Text transform options
const textTransform = {
  none: 'none',
  capitalize: 'capitalize',
  uppercase: 'uppercase',
  lowercase: 'lowercase',
} as const;

// Predefined typography styles
export const typography: Record<string, TextStyle> = {
  // Headings
  h1: {
    fontFamily: fontFamily.bold,
    fontSize: fontSize.xxxxl,
    lineHeight: lineHeight.xxxxl,
    fontWeight: fontWeight.bold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.tight,
  },
  h2: {
    fontFamily: fontFamily.bold,
    fontSize: fontSize.xxxl,
    lineHeight: lineHeight.xxxl,
    fontWeight: fontWeight.bold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.tight,
  },
  h3: {
    fontFamily: fontFamily.bold,
    fontSize: fontSize.xxl,
    lineHeight: lineHeight.xxl,
    fontWeight: fontWeight.bold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.tight,
  },
  h4: {
    fontFamily: fontFamily.semiBold,
    fontSize: fontSize.xl,
    lineHeight: lineHeight.xl,
    fontWeight: fontWeight.semiBold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.normal,
  },
  h5: {
    fontFamily: fontFamily.semiBold,
    fontSize: fontSize.lg,
    lineHeight: lineHeight.lg,
    fontWeight: fontWeight.semiBold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.normal,
  },
  h6: {
    fontFamily: fontFamily.medium,
    fontSize: fontSize.md,
    lineHeight: lineHeight.md,
    fontWeight: fontWeight.medium,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.normal,
  },
  
  // Body text
  bodyLarge: {
    fontFamily: fontFamily.regular,
    fontSize: fontSize.lg,
    lineHeight: lineHeight.lg,
    fontWeight: fontWeight.regular,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.normal,
  },
  body: {
    fontFamily: fontFamily.regular,
    fontSize: fontSize.md,
    lineHeight: lineHeight.md,
    fontWeight: fontWeight.regular,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.normal,
  },
  bodySmall: {
    fontFamily: fontFamily.regular,
    fontSize: fontSize.sm,
    lineHeight: lineHeight.sm,
    fontWeight: fontWeight.regular,
    color: colors.textSecondary,
    letterSpacing: letterSpacing.normal,
  },
  
  // Special text styles
  caption: {
    fontFamily: fontFamily.regular,
    fontSize: fontSize.xs,
    lineHeight: lineHeight.xs,
    fontWeight: fontWeight.regular,
    color: colors.textSecondary,
    letterSpacing: letterSpacing.normal,
  },
  button: {
    fontFamily: fontFamily.medium,
    fontSize: fontSize.md,
    lineHeight: lineHeight.md,
    fontWeight: fontWeight.medium,
    letterSpacing: letterSpacing.wide,
    textTransform: textTransform.none,
  },
  buttonSmall: {
    fontFamily: fontFamily.medium,
    fontSize: fontSize.sm,
    lineHeight: lineHeight.sm,
    fontWeight: fontWeight.medium,
    letterSpacing: letterSpacing.wide,
    textTransform: textTransform.none,
  },
  label: {
    fontFamily: fontFamily.medium,
    fontSize: fontSize.sm,
    lineHeight: lineHeight.sm,
    fontWeight: fontWeight.medium,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.wide,
  },
  link: {
    fontFamily: fontFamily.regular,
    fontSize: fontSize.md,
    lineHeight: lineHeight.md,
    fontWeight: fontWeight.regular,
    color: colors.link,
    letterSpacing: letterSpacing.normal,
  },
  
  // Display and special cases
  display: {
    fontFamily: fontFamily.bold,
    fontSize: fontSize.display,
    lineHeight: lineHeight.display,
    fontWeight: fontWeight.bold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.tight,
  },
  jumbo: {
    fontFamily: fontFamily.bold,
    fontSize: fontSize.jumbo,
    lineHeight: lineHeight.jumbo,
    fontWeight: fontWeight.bold,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.tight,
  },
  
  // Utility styles
  uppercase: {
    textTransform: textTransform.uppercase,
  },
  capitalize: {
    textTransform: textTransform.capitalize,
  },
  
  // Form elements
  input: {
    fontFamily: fontFamily.regular,
    fontSize: fontSize.md,
    lineHeight: lineHeight.md,
    fontWeight: fontWeight.regular,
    color: colors.textPrimary,
  },
  
  // Code/monospace
  code: {
    fontFamily: fontFamily.mono,
    fontSize: fontSize.sm,
    lineHeight: Math.round(fontSize.sm * 1.5),
    fontWeight: fontWeight.regular,
    color: colors.textPrimary,
    letterSpacing: letterSpacing.tight,
  },
};

// Export raw values for custom use cases
export const typeScale = {
  fontFamily,
  fontSize,
  lineHeight,
  fontWeight,
  letterSpacing,
  textTransform,
} as const;

export type FontFamilyKey = keyof typeof fontFamily;
export type FontSizeKey = keyof typeof fontSize;
export type LineHeightKey = keyof typeof lineHeight;
export type FontWeightKey = keyof typeof fontWeight;
export type LetterSpacingKey = keyof typeof letterSpacing;
export type TextTransformKey = keyof typeof textTransform;
export type TypographyStyleKey = keyof typeof typography;

export default typography;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/ChangePassword/ChangePasswordScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  ScrollView,
  Alert,
  ActivityIndicator,
} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import { styles } from './Styles';
import userService from '../../../helper/userService';
import { colors } from '../../../theme/colors';

interface FormData {
  currentPassword: string;
  newPassword: string;
  confirmPassword: string;
}

interface PasswordVisibility {
  currentPassword: boolean;
  newPassword: boolean;
  confirmPassword: boolean;
}

const ChangePasswordScreen = ({ navigation }: any) => {
  const [formData, setFormData] = useState<FormData>({
    currentPassword: '',
    newPassword: '',
    confirmPassword: '',
  });

  const [showPassword, setShowPassword] = useState<PasswordVisibility>({
    currentPassword: false,
    newPassword: false,
    confirmPassword: false,
  });

  const [errors, setErrors] = useState<Partial<FormData>>({});
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    // Set up the navigation header
    navigation.setOptions({
      headerShown: true,
      headerTitle: 'Change Password',
      headerLeft: () => (
        <TouchableOpacity 
          style={{ marginLeft: 10 }}
          onPress={() => navigation.navigate('MyProfile')}
        >
          <Icon style={styles.backButton} name="chevron-back" size={24} />
        </TouchableOpacity>
      ),
    });
  }, [navigation]);

  const togglePasswordVisibility = (field: keyof PasswordVisibility) => {
    setShowPassword(prev => ({
      ...prev,
      [field]: !prev[field]
    }));
  };

  const validateForm = () => {
    const newErrors: Partial<FormData> = {};

    if (!formData.currentPassword) {
      newErrors.currentPassword = 'Current password is required';
    }

    if (!formData.newPassword) {
      newErrors.newPassword = 'New password is required';
    }

    if (!formData.confirmPassword) {
      newErrors.confirmPassword = 'Confirm password is required';
    } else if (formData.newPassword !== formData.confirmPassword) {
      newErrors.confirmPassword = 'Passwords do not match';
    }

    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleChangePassword = async () => {
    if (!validateForm()) {
      return;
    }

    try {
      setIsLoading(true);
      const response = await userService.changePassword(
        formData.currentPassword,
        formData.newPassword,
        formData.confirmPassword
      );

      Alert.alert('Success', 'Password changed successfully', [
        {
          text: 'OK',
          onPress: () => {
            navigation.navigate('Login');
          },
        },
      ]);
    } catch (error: any) {
      Alert.alert('Error', error.message || 'Failed to change password');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        <Text style={styles.title}>Change Password</Text>
        <Text style={styles.subtitle}>Please enter your current password and choose a new password</Text>
      </View>

      <View style={styles.formContainer}>
        <View style={styles.inputGroup}>
          <Text style={styles.label}>Current Password</Text>
          <View style={styles.inputContainer}>
            <Icon name="lock-closed" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={styles.input}
              value={formData.currentPassword}
              onChangeText={(text) => {
                setFormData({ ...formData, currentPassword: text });
                if (errors.currentPassword) {
                  setErrors({ ...errors, currentPassword: '' });
                }
              }}
              placeholder="Enter current password"
              placeholderTextColor={colors.dark}
              secureTextEntry={!showPassword.currentPassword}
            />
            <TouchableOpacity onPress={() => togglePasswordVisibility('currentPassword')}>
              <Icon 
                name={showPassword.currentPassword ? 'eye-off' : 'eye'} 
                size={20} 
                color="#666" 
              />
            </TouchableOpacity>
          </View>
          {errors.currentPassword && (
            <Text style={styles.errorText}>{errors.currentPassword}</Text>
          )}
        </View>

        <View style={styles.inputGroup}>
          <Text style={styles.label}>New Password</Text>
          <View style={styles.inputContainer}>
            <Icon name="lock-closed" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={styles.input}
              value={formData.newPassword}
              onChangeText={(text) => {
                setFormData({ ...formData, newPassword: text });
                if (errors.newPassword) {
                  setErrors({ ...errors, newPassword: '' });
                }
              }}
              placeholder="Enter new password"
              placeholderTextColor={colors.dark}
              secureTextEntry={!showPassword.newPassword}
            />
            <TouchableOpacity onPress={() => togglePasswordVisibility('newPassword')}>
              <Icon 
                name={showPassword.newPassword ? 'eye-off' : 'eye'} 
                size={20} 
                color="#666" 
              />
            </TouchableOpacity>
          </View>
          {errors.newPassword && (
            <Text style={styles.errorText}>{errors.newPassword}</Text>
          )}
        </View>

        <View style={styles.inputGroup}>
          <Text style={styles.label}>Confirm New Password</Text>
          <View style={styles.inputContainer}>
            <Icon name="lock-closed" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={styles.input}
              value={formData.confirmPassword}
              onChangeText={(text) => {
                setFormData({ ...formData, confirmPassword: text });
                if (errors.confirmPassword) {
                  setErrors({ ...errors, confirmPassword: '' });
                }
              }}
              placeholder="Confirm new password"
              placeholderTextColor={colors.dark}
              secureTextEntry={!showPassword.confirmPassword}
            />
            <TouchableOpacity onPress={() => togglePasswordVisibility('confirmPassword')}>
              <Icon 
                name={showPassword.confirmPassword ? 'eye-off' : 'eye'} 
                size={20} 
                color="#666" 
              />
            </TouchableOpacity>
          </View>
          {errors.confirmPassword && (
            <Text style={styles.errorText}>{errors.confirmPassword}</Text>
          )}
        </View>

        <TouchableOpacity
          style={[styles.button, isLoading && styles.disabledButton]}
          onPress={handleChangePassword}
          disabled={isLoading}
        >
          {isLoading ? (
            <ActivityIndicator color="#fff" />
          ) : (
            <Text style={styles.buttonText}>Change Password</Text>
          )}
        </TouchableOpacity>
      </View>
    </ScrollView>
  );
};

export default ChangePasswordScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/screens/PostLogin/EditProfile/EditProfileScreen.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  TextInput,
  TouchableOpacity,
  Image,
  ScrollView,
  ActivityIndicator,
  Alert,
} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as ImagePicker from 'react-native-image-picker';
import Icon from 'react-native-vector-icons/Ionicons';
import { styles } from './Styles';
import userService from '../../../services/userService';

interface FormData {
  first_name: string;
  last_name: string;
  phone: string;
  email: string;
}

interface FormErrors {
  first_name?: string;
  last_name?: string;
  phone?: string;
}

const EditProfileScreen = ({ navigation }: any) => {
  const [formData, setFormData] = useState<FormData>({
    first_name: '',
    last_name: '',
    phone: '',
    email: '',
  });
  const [errors, setErrors] = useState<FormErrors>({});
  const [isLoading, setIsLoading] = useState(false);
  const [profileImage, setProfileImage] = useState<any>(null);
  const [currentAvatar, setCurrentAvatar] = useState<string>('');

  useEffect(() => {
    // Set up the navigation header
    navigation.setOptions({
      headerShown: true,
      headerTitle: 'Edit Profile',
      headerLeft: () => (
        <TouchableOpacity 
          style={{ marginLeft: 10 }}
          onPress={() => navigation.navigate('MyProfile')}
        >
          <Icon style={styles.backButton} name="chevron-back" size={24} />
        </TouchableOpacity>
      ),
    });
    
    loadUserData();
  }, [navigation]);

  const loadUserData = async () => {
    try {
      const userDataString = await AsyncStorage.getItem('userData');
      if (userDataString) {
        const userData = JSON.parse(userDataString);
        const { loginInfo } = userData;
        setFormData({
          first_name: loginInfo.first_name || '',
          last_name: loginInfo.last_name || '',
          phone: loginInfo.phone || '',
          email: loginInfo.email || '',
        });
        setCurrentAvatar(loginInfo.user_avatar || '');
      }
    } catch (error) {
      console.error('Error loading user data:', error);
      Alert.alert('Error', 'Failed to load user data');
    }
  };

  const validateForm = () => {
    const newErrors: FormErrors = {};
    if (!formData.first_name.trim()) {
      newErrors.first_name = 'First name is required';
    }
    if (!formData.last_name.trim()) {
      newErrors.last_name = 'Last name is required';
    }
    if (!formData.phone.trim()) {
      newErrors.phone = 'Phone number is required';
    } else if (formData.phone.length < 10) {
      newErrors.phone = 'Phone number must be at least 10 digits';
    }
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };

  const handleImagePicker = () => {
    const options: ImagePicker.ImageLibraryOptions = {
      mediaType: 'photo',
      quality: 1,
      selectionLimit: 1,
    };

    ImagePicker.launchImageLibrary(options, (response) => {
      if (response.didCancel) {
        return;
      }
      if (response.errorCode) {
        Alert.alert('Error', response.errorMessage || 'Failed to pick image');
        return;
      }
      if (response.assets && response.assets[0]) {
        setProfileImage(response.assets[0]);
      }
    });
  };

  const handleSubmit = async () => {
    if (!validateForm()) {
      return;
    }

    try {
      setIsLoading(true);
      const response = await userService.updateProfile({
        first_name: formData.first_name,
        last_name: formData.last_name,
        phone: formData.phone,
        profile_img: profileImage,
      });

      // The response is already successful if we reach this point
      // Store the updated user data
      await AsyncStorage.setItem('userData', JSON.stringify(response));
      Alert.alert('Success', 'Profile updated successfully', [
        { 
          text: 'OK', 
          onPress: () => {
            if (navigation) {
              navigation.navigate('MyProfile');
            }
          }
        },
      ]);
    } catch (error: any) {
      Alert.alert('Error', error.message || 'Failed to update profile');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <ScrollView style={styles.container}>
      <View style={styles.header}>
        <TouchableOpacity style={styles.avatarContainer} onPress={handleImagePicker}>
          {profileImage ? (
            <Image source={{ uri: profileImage.uri }} style={styles.profileImage} />
          ) : currentAvatar ? (
            <Image source={{ uri: currentAvatar }} style={styles.profileImage} />
          ) : (
            <Image
              source={require('../../../assets/images/default_profile_pic.png')}
              style={styles.profileImage}
            />
          )}
          <View style={styles.cameraIconContainer}>
            <Icon name="camera" size={20} color="#fff" />
          </View>
        </TouchableOpacity>
      </View>

      <View style={styles.formContainer}>
        <View style={styles.inputGroup}>
          <Text style={styles.label}>First Name</Text>
          <View style={styles.inputContainer}>
            <Icon name="person-outline" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={styles.input}
              placeholder="Enter first name"
              value={formData.first_name}
              onChangeText={(text) => setFormData({ ...formData, first_name: text })}
            />
          </View>
          {errors.first_name && <Text style={styles.errorText}>{errors.first_name}</Text>}
        </View>

        <View style={styles.inputGroup}>
          <Text style={styles.label}>Last Name</Text>
          <View style={styles.inputContainer}>
            <Icon name="person-outline" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={styles.input}
              placeholder="Enter last name"
              value={formData.last_name}
              onChangeText={(text) => setFormData({ ...formData, last_name: text })}
            />
          </View>
          {errors.last_name && <Text style={styles.errorText}>{errors.last_name}</Text>}
        </View>

        <View style={styles.inputGroup}>
          <Text style={styles.label}>Phone Number</Text>
          <View style={styles.inputContainer}>
            <Icon name="call-outline" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={styles.input}
              placeholder="Enter phone number"
              value={formData.phone}
              onChangeText={(text) => setFormData({ ...formData, phone: text })}
              keyboardType="phone-pad"
            />
          </View>
          {errors.phone && <Text style={styles.errorText}>{errors.phone}</Text>}
        </View>

        <View style={styles.inputGroup}>
          <Text style={styles.label}>Email</Text>
          <View style={styles.inputContainer}>
            <Icon name="mail-outline" size={20} color="#666" style={styles.inputIcon} />
            <TextInput
              style={[styles.input, { color: '#666' }]}
              value={formData.email}
              editable={false}
            />
          </View>
        </View>
      </View>

      <View style={styles.buttonContainer}>
        <TouchableOpacity
          style={[styles.button, isLoading && styles.disabledButton]}
          onPress={handleSubmit}
          disabled={isLoading}
        >
          {isLoading ? (
            <ActivityIndicator color="#fff" />
          ) : (
            <Text style={styles.buttonText}>Update Profile</Text>
          )}
        </TouchableOpacity>
      </View>
    </ScrollView>
  );
};

export default EditProfileScreen;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/hooks/useAppUpdate.ts:
--------------------------------------------------------------------------------

```typescript
import { useState, useCallback, useEffect } from 'react';
import UpdateService from '../services/UpdateService';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { compareVersions } from 'compare-versions';

interface VersionInfo {
  latestVersion: string;
  minimumVersion: string;
  releaseNotes?: string;
}

/**
 * Custom hook for managing app update state and logic
 * @param checkOnMount Whether to check for updates when the component mounts
 * @param updateCheckInterval Time interval between update checks (in milliseconds)
 * @returns Object containing update state and functions
 */
const useAppUpdate = (checkOnMount = true, updateCheckInterval = 60 * 60 * 1000) => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [versionInfo, setVersionInfo] = useState<VersionInfo | null>(null);
  const [isAppStoreVersion, setIsAppStoreVersion] = useState(false);
  const [storedAppVersion, setStoredAppVersion] = useState<string | null>(null);
  const [updateModalVisible, setUpdateModalVisible] = useState(false);
  const [lastUpdateCheck, setLastUpdateCheck] = useState<number | null>(null);

  // Time interval between update checks (in milliseconds)
  // Default: 1 hour - adjust this value based on how frequently you want to check for updates
  // Lower values will check more frequently but may impact performance
  const UPDATE_CHECK_INTERVAL = updateCheckInterval;

  // Check if the app is from the App Store
  const checkAppSource = useCallback(async () => {
    try {
      const isFromAppStore = await UpdateService.isAppStoreVersion();
      setIsAppStoreVersion(isFromAppStore);
      return isFromAppStore;
    } catch (err) {
      console.error('Error checking app source');
      return false;
    }
  }, []);

  // Get the stored app version
  const getStoredAppVersion = useCallback(async () => {
    try {
      const version = await AsyncStorage.getItem('app_version');
      setStoredAppVersion(version);
      return version;
    } catch (err) {
      console.error('Error getting stored app version');
      return null;
    }
  }, []);

  // Update the stored app version
  const updateStoredAppVersion = useCallback(async (version: string) => {
    try {
      await AsyncStorage.setItem('app_version', version);
      setStoredAppVersion(version);
    } catch (err) {
      console.error('Error updating stored app version');
    }
  }, []);

  /**
   * Load the last update check time from storage
   */
  const loadLastUpdateCheckTime = useCallback(async () => {
    try {
      const storedTime = await AsyncStorage.getItem('lastUpdateCheckTime');
      if (storedTime) {
        setLastUpdateCheck(parseInt(storedTime, 10));
      }
    } catch (error) {
      console.error('Error loading last update check time');
    }
  }, []);

  /**
   * Save the current time as the last update check time
   */
  const saveLastUpdateCheckTime = async () => {
    try {
      const currentTime = Date.now();
      await AsyncStorage.setItem('lastUpdateCheckTime', currentTime.toString());
      setLastUpdateCheck(currentTime);
    } catch (error) {
      console.error('Error saving last update check time');
    }
  };

  /**
   * Check if enough time has passed since the last update check
   */
  const shouldCheckForUpdates = () => {
    if (!lastUpdateCheck) {
      return true;
    }
    
    const currentTime = Date.now();
    const timeSinceLastCheck = currentTime - lastUpdateCheck;
    const shouldCheck = timeSinceLastCheck > UPDATE_CHECK_INTERVAL;
    
    return shouldCheck;
  };

  /**
   * Check if app version needs update
   * @param silent If true, performs the check silently in the background without showing loading indicators
   * @param force If true, checks for updates regardless of when the last check occurred
   * 
   * Usage examples:
   * - checkAppVersion(true, true): Silent check that bypasses time interval (ideal for HomeScreen focus)
   * - checkAppVersion(false, false): Regular check with loading indicator that respects time interval
   * - checkAppVersion(true, false): Silent check that respects time interval (good for background checks)
   * @returns Promise that resolves when the check is complete
   */
  const checkAppVersion = useCallback(async (silent = false, force = false): Promise<void> => {
    try {
      // Skip check if it was done recently, unless force is true
      if (!force && !shouldCheckForUpdates()) {
        return;
      }

      if (!silent) {
        setLoading(true);
      }
      
      // Get the current app version
      const currentVersion = await UpdateService.getCurrentVersion();
      
      if (!currentVersion) {
        console.error('Failed to get current app version');
        return;
      }
      
      // Get the latest version info from the server
      const versionInfo = await UpdateService.checkForUpdates();
      
      if (!versionInfo) {
        console.error('Failed to get latest version info');
        return;
      }
      
      // Update the last check time
      await saveLastUpdateCheckTime();
      
      // Set version info state
      setVersionInfo(versionInfo);
      
      // Check if update is needed
      const shouldShowModal = UpdateService.shouldShowUpdateModal(
        currentVersion,
        versionInfo.latestVersion,
        versionInfo.minimumVersion
      );
      
      // Only show modal if update is needed
      if (shouldShowModal) {
        setUpdateModalVisible(true);
      } else {
        setUpdateModalVisible(false);
      }
    } catch (error) {
      console.error('Error checking app version');
      // Don't show modal on error
      setUpdateModalVisible(false);
    } finally {
      if (!silent) {
        setLoading(false);
      }
    }
  }, [shouldCheckForUpdates, saveLastUpdateCheckTime]);

  /**
   * Close the update modal
   */
  const closeUpdateModal = useCallback(async () => {
    try {
      // If there's version info and it's not a required update, mark it as skipped
      if (versionInfo) {
        const currentVersion = await UpdateService.getCurrentVersion();
        const isRequired = UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion);
        
        if (!isRequired) {
          await UpdateService.skipVersion(versionInfo.latestVersion);
        }
      }
      setUpdateModalVisible(false);
    } catch (error) {
      console.error('Error closing update modal');
    }
  }, [versionInfo]);

  /**
   * Navigate to the app store to update the app
   */
  const goToUpdate = useCallback(async () => {
    try {
      await UpdateService.openAppStore();
    } catch (error) {
      console.error('Error navigating to app store');
      setError(`Failed to open app store: ${error instanceof Error ? error.message : String(error)}`);
    }
  }, []);

  // Check for updates on mount if checkOnMount is true
  useEffect(() => {
    // Always load the last update check time
    loadLastUpdateCheckTime();
    
    // Only check for updates if checkOnMount is true
    if (checkOnMount) {
      // Use silent mode for initial check to avoid disrupting the user experience
      checkAppVersion(true, false);
    }
  }, [checkOnMount, loadLastUpdateCheckTime]);

  // Check if the app is from the App Store on mount
  useEffect(() => {
    checkAppSource();
  }, [checkAppSource]);

  // Get the stored app version on mount
  useEffect(() => {
    getStoredAppVersion();
  }, [getStoredAppVersion]);

  return {
    versionInfo,
    isAppStoreVersion,
    storedAppVersion,
    loading,
    error,
    updateModalVisible,
    setUpdateModalVisible,
    checkAppVersion,
    checkForUpdates: useCallback((silent = false, force = false): Promise<void> => {
      // Directly call checkAppVersion with the provided parameters
      return checkAppVersion(silent, force);
    }, [checkAppVersion]),
    closeUpdateModal,
    goToUpdate,
  };
};

export default useAppUpdate;

```

--------------------------------------------------------------------------------
/resources/code-examples/react-native/components/UpdateModal.tsx:
--------------------------------------------------------------------------------

```typescript
import React, { useState, useCallback, useEffect } from 'react';
import { 
  Modal, 
  View, 
  Text, 
  StyleSheet, 
  TouchableOpacity, 
  Platform,
  Switch,
  Dimensions,
  ActivityIndicator
} from 'react-native';

// Import the VersionInfo interface from the hook instead of the service
import UpdateService from '../services/UpdateService';
import { compareVersions } from 'compare-versions';

const { width } = Dimensions.get('window');

interface UpdateModalProps {
  isVisible: boolean;
  versionInfo: {
    latestVersion: string;
    minimumVersion: string;
    releaseNotes?: string;
  } | null;
  onClose: () => void;
  onUpdate?: () => Promise<void>; // Optional prop for update handling
}

const UpdateModal: React.FC<UpdateModalProps> = ({ 
  isVisible, 
  versionInfo, 
  onClose,
  onUpdate 
}) => {
  const [skipVersion, setSkipVersion] = useState(false);
  const [isUpdating, setIsUpdating] = useState(false);
  const [updateError, setUpdateError] = useState<string | null>(null);
  const [currentVersion, setCurrentVersion] = useState<string>('');

  // Get the current version when the component mounts
  React.useEffect(() => {
    const fetchCurrentVersion = async () => {
      try {
        const version = await UpdateService.getCurrentVersion();
        setCurrentVersion(version);
      } catch (error) {
        console.error('Error getting current version:', error);
      }
    };

    fetchCurrentVersion();
  }, []);

  const handleUpdate = useCallback(async () => {
    try {
      setIsUpdating(true);
      setUpdateError(null);
      
      if (onUpdate) {
        // Use the provided update handler if available
        await onUpdate();
      } else {
        // Default behavior
        await UpdateService.openAppStore();
      }
      
      // Only close modal if update is not required
      if (!versionInfo || !currentVersion || !UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion)) {
        onClose();
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : 'Failed to open app store';
      setUpdateError(errorMessage);
      console.error('Update error:', error);
    } finally {
      setIsUpdating(false);
    }
  }, [versionInfo, onClose, onUpdate, currentVersion]);

  const handleSkip = useCallback(async () => {
    try {
      if (skipVersion && versionInfo) {
        // Skip this version
        await UpdateService.skipVersion(versionInfo.latestVersion);
      }
      
      // Only close modal if update is not required
      if (!versionInfo || !currentVersion || !UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion)) {
        onClose();
      }
    } catch (error) {
      console.error('Error skipping version:', error);
    }
  }, [versionInfo, skipVersion, onClose, currentVersion]);

  // Determine the message to display based on version comparison
  const getUpdateMessage = () => {
    if (!versionInfo || !currentVersion) return '';
    
    const { latestVersion, minimumVersion } = versionInfo;
    
    // Check if update is required
    const isRequired = UpdateService.isUpdateRequired(currentVersion, minimumVersion);
    
    if (isRequired) {
      return 'This update is required to continue using the app.';
    } else if (compareVersions(currentVersion, latestVersion) < 0) {
      return 'A new version of the app is available. Would you like to update now?';
    } else {
      return 'Your app is up to date.';
    }
  };

  if (!versionInfo) {
    return null;
  }

  return (
    <Modal
      animationType="fade"
      transparent={true}
      visible={isVisible}
      onRequestClose={() => {
        if (!versionInfo || !currentVersion || !UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion)) {
          onClose();
        }
      }}
    >
      <View style={styles.centeredView}>
        <View style={styles.modalView}>
          <Text style={styles.modalTitle}>
            {versionInfo && currentVersion && UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion) ? 'Required Update' : 'Update Available'}
          </Text>
          
          <Text style={styles.modalText}>
            {getUpdateMessage()}
          </Text>

          {versionInfo.releaseNotes && (
            <Text style={styles.releaseNotes}>
              {versionInfo.releaseNotes}
            </Text>
          )}

          {updateError && (
            <Text style={styles.errorText}>
              {updateError}
            </Text>
          )}

          {versionInfo && currentVersion && UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion) ? (
            <Text style={styles.warningText}>
              This update includes critical changes and is required to continue using the app.
            </Text>
          ) : (
            <View style={styles.skipContainer}>
              <Switch
                value={skipVersion}
                onValueChange={setSkipVersion}
                trackColor={{ false: '#767577', true: '#81b0ff' }}
                thumbColor={skipVersion ? '#f5dd4b' : '#f4f3f4'}
              />
              <Text style={styles.skipText}>Skip this version</Text>
            </View>
          )}

          <View style={styles.buttonsContainer}>
            {(!versionInfo || !currentVersion || !UpdateService.isUpdateRequired(currentVersion, versionInfo.minimumVersion)) && (
              <TouchableOpacity
                style={[styles.button, styles.buttonCancel]}
                onPress={handleSkip}
                disabled={isUpdating}
              >
                <Text style={styles.buttonText}>Later</Text>
              </TouchableOpacity>
            )}
            
            <TouchableOpacity
              style={[styles.button, styles.buttonUpdate]}
              onPress={handleUpdate}
              disabled={isUpdating}
            >
              {isUpdating ? (
                <ActivityIndicator size="small" color="#ffffff" />
              ) : (
                <Text style={[styles.buttonText, styles.updateButtonText]}>Update Now</Text>
              )}
            </TouchableOpacity>
          </View>
        </View>
      </View>
    </Modal>
  );
};

const styles = StyleSheet.create({
  centeredView: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'rgba(0, 0, 0, 0.5)',
  },
  modalView: {
    width: width * 0.85,
    backgroundColor: 'white',
    borderRadius: 20,
    padding: 25,
    alignItems: 'center',
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 2,
    },
    shadowOpacity: 0.25,
    shadowRadius: 4,
    elevation: 5,
  },
  modalTitle: {
    fontSize: 20,
    fontWeight: 'bold',
    marginBottom: 15,
    textAlign: 'center',
  },
  modalText: {
    marginBottom: 15,
    textAlign: 'center',
    fontSize: 16,
    lineHeight: 22,
  },
  releaseNotes: {
    marginBottom: 15,
    textAlign: 'left',
    fontSize: 14,
    lineHeight: 20,
    padding: 10,
    backgroundColor: '#f9f9f9',
    borderRadius: 8,
    width: '100%',
  },
  warningText: {
    color: '#d9534f',
    marginBottom: 20,
    textAlign: 'center',
    fontSize: 14,
  },
  errorText: {
    color: '#d9534f',
    marginBottom: 15,
    textAlign: 'center',
    fontSize: 14,
    backgroundColor: '#ffeeee',
    padding: 10,
    borderRadius: 5,
    width: '100%',
  },
  skipContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 20,
  },
  skipText: {
    marginLeft: 10,
    fontSize: 14,
  },
  buttonsContainer: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: '100%',
  },
  button: {
    borderRadius: 10,
    padding: 12,
    elevation: 2,
    minWidth: 100,
    marginHorizontal: 5,
    alignItems: 'center',
  },
  buttonCancel: {
    backgroundColor: '#f8f9fa',
    borderWidth: 1,
    borderColor: '#dee2e6',
  },
  buttonUpdate: {
    backgroundColor: '#007bff',
    flex: 1,
  },
  buttonText: {
    textAlign: 'center',
    fontSize: 16,
  },
  updateButtonText: {
    color: 'white',
    fontWeight: 'bold',
  },
});

export default UpdateModal;

```
Page 1/2FirstPrevNextLast