#
tokens: 48430/50000 59/75 files (page 1/2)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 1 of 2. Use http://codebase.md/lallen30/mcp-remote-server?lines=true&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:
--------------------------------------------------------------------------------

```
 1 | # Dependencies
 2 | node_modules/
 3 | 
 4 | # Build output
 5 | build/
 6 | dist/
 7 | 
 8 | # Environment variables
 9 | .env
10 | .env.local
11 | .env.*.local
12 | 
13 | # Logs
14 | logs/
15 | *.log
16 | npm-debug.log*
17 | yarn-debug.log*
18 | yarn-error.log*
19 | 
20 | # Editor directories and files
21 | .idea/
22 | .vscode/
23 | *.swp
24 | *.swo
25 | .DS_Store
26 | 
27 | # Testing
28 | coverage/
29 | 
30 | # Temporary files
31 | .tmp/
32 | .temp/
33 | 
34 | # Debug
35 | .node-version
36 | .npm/
37 | 
38 | # TypeScript cache
39 | *.tsbuildinfo
40 | 
41 | # Optional npm cache directory
42 | .npm
43 | 
44 | # Optional eslint cache
45 | .eslintcache
46 | 
```

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

```markdown
 1 | # MCP Remote Server (Node.js Version)
 2 | 
 3 | This is a Node.js implementation of the BluestoneApps Coding Standards and Examples MCP server.
 4 | 
 5 | ## Overview
 6 | 
 7 | 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.
 8 | 
 9 | ## Features
10 | 
11 | - Access to React Native coding standards
12 | - Component, hook, screen, service, and theme code examples
13 | - Fuzzy matching for finding examples by name
14 | - Full integration with the MCP protocol
15 | 
16 | ## Installation
17 | 
18 | 1. Clone this repository
19 | 2. Install dependencies:
20 |    ```bash
21 |    npm install
22 |    ```
23 | 3. Build the project:
24 |    ```bash
25 |    npm run build
26 |    ```
27 | 
28 | ## Usage
29 | 
30 | Start the server:
31 | 
32 | ```bash
33 | npm start
34 | ```
35 | 
36 | To use with MCP clients, configure them to connect to this server.
37 | 
38 | ## Tools
39 | 
40 | The server provides the following tools:
41 | 
42 | - `get_project_structure`: Get project structure standards
43 | - `get_api_communication`: Get API communication standards 
44 | - `get_component_design`: Get component design standards
45 | - `get_state_management`: Get state management standards
46 | - `get_component_example`: Get a specific component example
47 | - `get_hook_example`: Get a specific hook example
48 | - `get_service_example`: Get a specific service example 
49 | - `get_screen_example`: Get a specific screen example
50 | - `get_theme_example`: Get a specific theme example
51 | - `list_available_examples`: List all available code examples
52 | 
53 | ## Configuring with MCP Clients
54 | 
55 | For Windsurf IDE, update the `mcp_config.json` with:
56 | 
57 | ```json
58 | {
59 |   "servers": {
60 |     "bluestoneapps": {
61 |       "command": "node",
62 |       "args": ["/path/to/build/index.js"],
63 |       "description": "BluestoneApps Coding Standards and Examples",
64 |       "displayName": "BluestoneApps MCP Server",
65 |       "timeout": 30000
66 |     }
67 |   }
68 | }
69 | 
```

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

```markdown
 1 | # React Native Theme System
 2 | 
 3 | This directory contains the TypeScript theme files for React Native applications. The theme system provides a consistent design language across the application.
 4 | 
 5 | ## Standards
 6 | 
 7 | - All theme files are written in TypeScript (.ts) for better type safety and developer experience
 8 | - Theme files export both the values and TypeScript types for proper type checking
 9 | - The theme system is modular and composable, with separate files for different aspects of the design system
10 | 
11 | ## Files
12 | 
13 | - `colors.ts` - Color palette definitions and utility functions
14 | - `typography.ts` - Typography styles, font families, sizes, and text styles
15 | - `theme.ts` - Main theme configuration that combines all theme elements
16 | 
17 | ## Usage
18 | 
19 | Import the theme elements in your components:
20 | 
21 | ```tsx
22 | import { colors } from './theme/colors';
23 | import typography from './theme/typography';
24 | import theme from './theme/theme';
25 | 
26 | // Using colors
27 | const styles = StyleSheet.create({
28 |   container: {
29 |     backgroundColor: colors.background,
30 |   },
31 |   text: {
32 |     ...typography.body,
33 |     color: colors.textPrimary,
34 |   },
35 |   button: {
36 |     padding: theme.spacing.md,
37 |     borderRadius: theme.borderRadius.md,
38 |   },
39 | });
40 | ```
41 | 
42 | ## Type Support
43 | 
44 | The theme files export TypeScript types to provide autocompletion and type checking:
45 | 
46 | ```tsx
47 | import { ColorKey } from './theme/colors';
48 | import { TypographyStyleKey } from './theme/typography';
49 | import { SpacingKey, BorderRadiusKey } from './theme/theme';
50 | 
51 | // Type-safe usage
52 | const color: ColorKey = 'primary';
53 | const textStyle: TypographyStyleKey = 'body';
54 | const spacing: SpacingKey = 'md';
55 | ```
56 | 
57 | ## Extending the Theme
58 | 
59 | When extending the theme, follow these guidelines:
60 | 
61 | 1. Add new values to the appropriate theme file
62 | 2. Ensure all values are properly typed
63 | 3. Use consistent naming conventions
64 | 4. Document any complex values or usage patterns
65 | 5. Update the theme.ts file if necessary to expose new theme elements
66 | 
67 | ## Migration from JavaScript
68 | 
69 | This theme system has been migrated from JavaScript to TypeScript. All theme files now use the `.ts` extension and include proper type definitions.
70 | 
```

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

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "NodeNext",
 5 |     "moduleResolution": "NodeNext",
 6 |     "esModuleInterop": true,
 7 |     "outDir": "./build",
 8 |     "strict": true,
 9 |     "skipLibCheck": true
10 |   },
11 |   "include": ["src/**/*"]
12 | }
13 | 
```

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

```typescript
 1 | import React from 'react';
 2 | import { View, Text } from 'react-native';
 3 | import { styles } from './Styles';
 4 | 
 5 | const CustomerSupportScreen = () => {
 6 |   return (
 7 |     <View style={styles.container}>
 8 |       <Text style={styles.title}>Customer Support</Text>
 9 |       <Text style={styles.subtitle}>Coming Soon</Text>
10 |     </View>
11 |   );
12 | };
13 | 
14 | export default CustomerSupportScreen; 
```

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

```typescript
 1 | export const colors = {
 2 |   primary: '#412DA5',
 3 |   secondary: '#6032FF',
 4 |   tertiary: '#29243F',
 5 |   success: '#23AD51',
 6 |   warning: '#EF7F18',
 7 |   danger: '#E02D47',
 8 |   white: '#FFFFFF',
 9 |   light: '#EEF1F7',
10 |   medium: '#747D8B',
11 |   dark: '#2D3035',
12 |   black: '#070707',
13 |   headerBg: '#29243F',
14 |   headerFont: '#FFFFFF',
15 |   footerBg: '#FFFFFF',
16 |   footerFont: '#747D8B',
17 | } as const;
```

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

```typescript
 1 | export const environment = {
 2 |   server: 'wordpress.betaplanets.com',
 3 |   production: false,
 4 |   baseURL: 'https://wordpress.betaplanets.com',
 5 |   apiURL: 'https://wordpress.betaplanets.com/wp-json'
 6 |   // server: 'laravelapi2.betaplanets.com/api',
 7 |   // production: false,
 8 |   // baseURL: 'https://laravelapi2.betaplanets.com/api',
 9 |   // apiURL: 'https://laravelapi2.betaplanets.com/api/wp-json'
10 | };
11 | 
```

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

```typescript
 1 | import React from 'react';
 2 | import { View, ActivityIndicator, StyleSheet } from 'react-native';
 3 | 
 4 | export const LoadingSpinner = () => (
 5 |   <View style={styles.container}>
 6 |     <ActivityIndicator size="large" color="#007AFF" />
 7 |   </View>
 8 | );
 9 | 
10 | const styles = StyleSheet.create({
11 |   container: {
12 |     flex: 1,
13 |     justifyContent: 'center',
14 |     alignItems: 'center',
15 |     backgroundColor: '#fff'
16 |   }
17 | });
18 | 
```

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

```typescript
 1 | export interface LoginResponse {
 2 |   loginInfo: {
 3 |     token: string;
 4 |     user_email: string;
 5 |     user_nicename: string;
 6 |     user_display_name: string;
 7 |     [key: string]: any;
 8 |   };
 9 | }
10 | 
11 | export interface LoginCredentials {
12 |   email: string;
13 |   password: string;
14 | }
15 | 
16 | export interface AuthError {
17 |   response?: {
18 |     data?: {
19 |       message?: string;
20 |     };
21 |     status?: number;
22 |   };
23 |   message?: string;
24 | }
25 | 
```

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

```typescript
 1 | import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
 2 | 
 3 | type Styles = {
 4 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 5 | };
 6 | 
 7 | export const styles = StyleSheet.create<Styles>({
 8 | container: {
 9 |     flex: 1,
10 |     justifyContent: 'center',
11 |     alignItems: 'center',
12 |     backgroundColor: '#fff',
13 |   },
14 |   title: {
15 |     fontSize: 24,
16 |     fontWeight: 'bold',
17 |     marginBottom: 10,
18 |   },
19 |   subtitle: {
20 |     fontSize: 16,
21 |     color: '#666',
22 |   },
23 | });
24 | 
```

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

```json
 1 | {
 2 |   "name": "mcp-remote-server",
 3 |   "version": "1.0.0",
 4 |   "type": "module",
 5 |   "scripts": {
 6 |     "build": "tsc",
 7 |     "start": "node build/index.js"
 8 |   },
 9 |   "keywords": [],
10 |   "author": "",
11 |   "license": "ISC",
12 |   "description": "BluestoneApps Coding Standards and Examples MCP Server",
13 |   "dependencies": {
14 |     "@modelcontextprotocol/sdk": "^1.1.0",
15 |     "glob": "^10.3.10",
16 |     "zod": "^3.22.4"
17 |   },
18 |   "devDependencies": {
19 |     "@types/node": "^22.10.5",
20 |     "typescript": "^5.7.2"
21 |   }
22 | }
23 | 
```

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

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "es2020",
 4 |     "module": "esnext",
 5 |     "moduleResolution": "node",
 6 |     "jsx": "react-native",
 7 |     "strict": true,
 8 |     "esModuleInterop": true,
 9 |     "skipLibCheck": true,
10 |     "forceConsistentCasingInFileNames": true,
11 |     "resolveJsonModule": true,
12 |     "isolatedModules": true,
13 |     "noEmit": true,
14 |     "baseUrl": ".",
15 |     "paths": {
16 |       "*": ["types/*"]
17 |     },
18 |     "typeRoots": ["./types", "./node_modules/@types"]
19 |   },
20 |   "include": [
21 |     "**/*.ts",
22 |     "**/*.tsx"
23 |   ],
24 |   "exclude": [
25 |     "node_modules"
26 |   ]
27 | }
28 | 
```

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

```typescript
 1 | export const colors = {
 2 |   primary: '#007AFF',
 3 |   secondary: '#50cebb',
 4 |   tertiary: '#F0A225',
 5 |   Success: '#2FD36F',
 6 |   Warning: '#FDC40C',
 7 |   Danger: '#EC445A',
 8 |   White: '#FFFFFF',
 9 |   ultraLight: '#F9F9FC',
10 |   light: '#EBEBEB',
11 |   mediumLight: '#BEC6C8',
12 |   mediumDark: '#707070',
13 |   dark: '#222428',
14 |   black: '#000000',
15 |   text: {
16 |     primary: '#2c3e50',
17 |     secondary: '#999',
18 |     error: '#dc3545',
19 |     white: '#fff',
20 |     header: '#FFFFFF',
21 |     footer: '#96A1A5',
22 |   },
23 |   background: {
24 |     primary: '#fff',
25 |     secondary: '#f8f9fa',
26 |     header: '#3B00FF',
27 |     footer: '#F9F9FC',
28 |   },
29 |   border: {
30 |     primary: '#e9ecef',
31 |     error: '#dc3545',
32 |   },
33 | } as const;
34 | 
```

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

```typescript
 1 | import { StyleSheet } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | export const styles = StyleSheet.create({
 5 |   container: {
 6 |     flex: 1,
 7 |     backgroundColor: colors.primary,
 8 |   },
 9 |   header: {
10 |     padding: 16,
11 |     borderBottomWidth: 1,
12 |     borderBottomColor: colors.light,
13 |     backgroundColor: colors.white,
14 |     marginBottom: 0
15 |   },
16 |   title: {
17 |     fontSize: 24,
18 |     fontWeight: 'bold',
19 |     color: colors.primary,
20 |   },
21 |   webViewContainer: {
22 |     flex: 1,
23 |     backgroundColor: colors.white,
24 |   },
25 |   webView: {
26 |     flex: 1,
27 |     backgroundColor: colors.white,
28 |     opacity: 0.99 // Fix for iOS WebView rendering
29 |   },
30 |   noContent: {
31 |     fontSize: 16,
32 |     color: colors.dark,
33 |     textAlign: 'center',
34 |     marginTop: 20
35 |   }
36 | });
37 | 
```

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

```typescript
 1 | import { StyleSheet, Dimensions } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | const { width } = Dimensions.get('window');
 5 | 
 6 | export const styles = StyleSheet.create({
 7 |   container: {
 8 |     flex: 1,
 9 |     backgroundColor: colors.white,
10 |   },
11 |   loadingContainer: {
12 |     flex: 1,
13 |     justifyContent: 'center',
14 |     alignItems: 'center',
15 |     backgroundColor: colors.white,
16 |   },
17 |   errorContainer: {
18 |     flex: 1,
19 |     justifyContent: 'center',
20 |     alignItems: 'center',
21 |     padding: 32,
22 |     backgroundColor: colors.white,
23 |   },
24 |   errorText: {
25 |     fontSize: 16,
26 |     color: colors.danger,
27 |     textAlign: 'center',
28 |   },
29 |   featuredImage: {
30 |     width: width,
31 |     height: width * 0.6,
32 |     backgroundColor: colors.secondary,
33 |   },
34 |   content: {
35 |     padding: 16,
36 |   },
37 |   title: {
38 |     fontSize: 24,
39 |     fontWeight: 'bold',
40 |     color: colors.primary,
41 |     marginBottom: 8,
42 |   },
43 |   date: {
44 |     fontSize: 14,
45 |     color: colors.dark,
46 |     marginBottom: 16,
47 |   },
48 | });
49 | 
```

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

```typescript
 1 | import { StyleSheet } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | export const styles = StyleSheet.create({
 5 |   
 6 |   container: {
 7 |     flex: 1,
 8 |     backgroundColor: '#fff',
 9 |   },
10 |   content: {
11 |     flex: 1,
12 |     padding: 20,
13 |   },
14 |   title: {
15 |     fontSize: 24,
16 |     fontWeight: 'bold',
17 |     color: colors.black,
18 |     marginBottom: 10,
19 |   },
20 |   date: {
21 |     fontSize: 18,
22 |     color: colors.secondary,
23 |     marginBottom: 5,
24 |   },
25 |   time: {
26 |     fontSize: 18,
27 |     color: colors.secondary,
28 |     marginBottom: 20,
29 |   },
30 |   section: {
31 |     marginBottom: 25,
32 |     borderTopWidth: 1,
33 |     borderTopColor: colors.light,
34 |     paddingTop: 20,
35 |   },
36 |   sectionTitle: {
37 |     fontSize: 18,
38 |     fontWeight: '600',
39 |     color: colors.black,
40 |     marginBottom: 10,
41 |   },
42 |   location: {
43 |     fontSize: 16,
44 |     color: colors.dark,
45 |     lineHeight: 24,
46 |   },
47 |   description: {
48 |     fontSize: 16,
49 |     color: colors.dark,
50 |     lineHeight: 24,
51 |   },
52 |   price: {
53 |     fontSize: 18,
54 |     color: colors.secondary,
55 |     fontWeight: '500',
56 |     marginTop: 5,
57 |   },
58 | });
59 | 
```

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

```typescript
 1 | /**
 2 |  * This file contains utilities to suppress specific console warnings
 3 |  * that are not relevant to the application's functionality.
 4 |  */
 5 | 
 6 | // Original console.warn function
 7 | const originalWarn = console.warn;
 8 | 
 9 | // List of warning messages to suppress
10 | const suppressedWarnings = [
11 |   'TRenderEngineProvider: Support for defaultProps will be removed from function components',
12 |   'MemoizedTNodeRenderer: Support for defaultProps will be removed from memo components',
13 |   'TNodeChildrenRenderer: Support for defaultProps will be removed from function components',
14 | ];
15 | 
16 | // Override console.warn to filter out specific warnings
17 | console.warn = function (message: any, ...optionalParams: any[]) {
18 |   // Check if this is a warning we want to suppress
19 |   if (typeof message === 'string') {
20 |     for (const warningText of suppressedWarnings) {
21 |       if (message.includes(warningText)) {
22 |         // Skip this warning
23 |         return;
24 |       }
25 |     }
26 |   }
27 |   
28 |   // Pass through to the original console.warn for all other warnings
29 |   originalWarn(message, ...optionalParams);
30 | };
31 | 
32 | export {}; // Make this a module
33 | 
```

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

```typescript
 1 | import React from 'react';
 2 | import {
 3 |   TouchableOpacity,
 4 |   Text,
 5 |   StyleSheet,
 6 |   ViewStyle,
 7 |   TextStyle,
 8 |   ActivityIndicator,
 9 | } from 'react-native';
10 | 
11 | interface ButtonProps {
12 |   title: string;
13 |   onPress: () => void;
14 |   style?: ViewStyle;
15 |   textStyle?: TextStyle;
16 |   loading?: boolean;
17 |   disabled?: boolean;
18 | }
19 | 
20 | export const Button: React.FC<ButtonProps> = ({
21 |   title,
22 |   onPress,
23 |   style,
24 |   textStyle,
25 |   loading = false,
26 |   disabled = false,
27 | }) => {
28 |   return (
29 |     <TouchableOpacity
30 |       style={[
31 |         styles.button,
32 |         style,
33 |         disabled && styles.disabledButton,
34 |       ]}
35 |       onPress={onPress}
36 |       disabled={disabled || loading}
37 |     >
38 |       {loading ? (
39 |         <ActivityIndicator color="#fff" />
40 |       ) : (
41 |         <Text style={[styles.text, textStyle]}>{title}</Text>
42 |       )}
43 |     </TouchableOpacity>
44 |   );
45 | };
46 | 
47 | const styles = StyleSheet.create({
48 |   button: {
49 |     backgroundColor: '#007AFF',
50 |     paddingVertical: 12,
51 |     paddingHorizontal: 24,
52 |     borderRadius: 8,
53 |     alignItems: 'center',
54 |     justifyContent: 'center',
55 |   },
56 |   text: {
57 |     color: '#fff',
58 |     fontSize: 16,
59 |     fontWeight: '600',
60 |   },
61 |   disabledButton: {
62 |     opacity: 0.6,
63 |   },
64 | });
65 | 
```

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

```typescript
 1 | import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
 2 | 
 3 | type Styles = {
 4 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 5 | };
 6 | 
 7 | export const styles = StyleSheet.create<Styles>({
 8 | container: {
 9 |     flex: 1,
10 |     backgroundColor: '#fff',
11 |     padding: 20,
12 |   },
13 |   header: {
14 |     marginTop: 40,
15 |     marginBottom: 30,
16 |   },
17 |   title: {
18 |     fontSize: 24,
19 |     fontWeight: 'bold',
20 |     color: '#000',
21 |     textAlign: 'center',
22 |     marginBottom: 10,
23 |   },
24 |   subtitle: {
25 |     fontSize: 16,
26 |     color: '#666',
27 |     textAlign: 'center',
28 |     marginBottom: 30,
29 |   },
30 |   otpContainer: {
31 |     flexDirection: 'row',
32 |     justifyContent: 'space-between',
33 |     marginBottom: 30,
34 |   },
35 |   otpInput: {
36 |     width: 50,
37 |     height: 50,
38 |     borderWidth: 1,
39 |     borderColor: '#ddd',
40 |     borderRadius: 8,
41 |     textAlign: 'center',
42 |     fontSize: 20,
43 |     color: '#000',
44 |   },
45 |   button: {
46 |     backgroundColor: '#007AFF',
47 |     height: 50,
48 |     borderRadius: 8,
49 |     justifyContent: 'center',
50 |     alignItems: 'center',
51 |     marginTop: 20,
52 |   },
53 |   buttonText: {
54 |     color: '#fff',
55 |     fontSize: 16,
56 |     fontWeight: 'bold',
57 |   },
58 |   backButton: {
59 |     marginTop: 20,
60 |     alignItems: 'center',
61 |   },
62 |   backButtonText: {
63 |     color: '#007AFF',
64 |     fontSize: 16,
65 |   },
66 | });
67 | 
```

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

```typescript
 1 | import { StyleSheet, Dimensions, ViewStyle, TextStyle, ImageStyle } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | const { width } = Dimensions.get('window');
 5 | 
 6 | type Styles = {
 7 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 8 | };
 9 | 
10 | export const styles = StyleSheet.create({
11 |   container: {
12 |     flex: 1,
13 |     backgroundColor: colors.white,
14 |     padding: 20,
15 |     justifyContent: 'center' as const,
16 |   },
17 |   logoContainer: {
18 |     alignItems: 'center',
19 |     marginBottom: 20,
20 |   },
21 |   logo: {
22 |     width: width * 0.6,
23 |     height: 200,
24 |     resizeMode: 'contain',
25 |   },
26 |   title: {
27 |     fontSize: 28,
28 |     fontWeight: 'bold',
29 |     color: colors.primary,
30 |     marginBottom: 10,
31 |     textAlign: 'center',
32 |   },
33 |   subtitle: {
34 |     fontSize: 16,
35 |     color: colors.secondary,
36 |     marginBottom: 30,
37 |     textAlign: 'center',
38 |   },
39 |   input: {
40 |     backgroundColor: colors.light,
41 |     borderRadius: 8,
42 |     padding: 15,
43 |     marginBottom: 15,
44 |     color: colors.black,
45 |   },
46 |   button: {
47 |     backgroundColor: colors.primary,
48 |     borderRadius: 8,
49 |     padding: 15,
50 |     alignItems: 'center',
51 |     marginBottom: 15,
52 |   },
53 |   buttonText: {
54 |     color: colors.white,
55 |     fontSize: 16,
56 |     fontWeight: 'bold',
57 |   },
58 |   backButton: {
59 |     alignItems: 'center',
60 |     marginTop: 10,
61 |   },
62 |   backButtonText: {
63 |     color: colors.primary,
64 |     fontSize: 16,
65 |   },
66 | });
67 | 
```

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

```typescript
 1 | import { StyleSheet } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | export const styles = StyleSheet.create({
 5 |   container: {
 6 |     flex: 1,
 7 |     backgroundColor: colors.light,
 8 |   },
 9 |   loadingContainer: {
10 |     flex: 1,
11 |     justifyContent: 'center',
12 |     alignItems: 'center',
13 |     backgroundColor: colors.white,
14 |   },
15 |   header: {
16 |     padding: 16,
17 |     backgroundColor: colors.headerBg,
18 |     borderBottomWidth: 1,
19 |     borderBottomColor: colors.primary,
20 |   },
21 |   title: {
22 |     fontSize: 24,
23 |     fontWeight: 'bold',
24 |     color: colors.headerFont,
25 |   },
26 |   postsContainer: {
27 |     padding: 16,
28 |   },
29 |   categorySection: {
30 |     marginBottom: 24,
31 |   },
32 |   categoryTitle: {
33 |     fontSize: 20,
34 |     fontWeight: '600',
35 |     color: colors.primary,
36 |     marginBottom: 12,
37 |   },
38 |   postCard: {
39 |     backgroundColor: colors.white,
40 |     borderRadius: 8,
41 |     padding: 16,
42 |     marginBottom: 12,
43 |     shadowColor: colors.black,
44 |     shadowOffset: {
45 |       width: 0,
46 |       height: 2,
47 |     },
48 |     shadowOpacity: 0.1,
49 |     shadowRadius: 4,
50 |     elevation: 3,
51 |   },
52 |   postTitle: {
53 |     fontSize: 18,
54 |     fontWeight: '500',
55 |     color: colors.black,
56 |     marginBottom: 8,
57 |   },
58 |   postDate: {
59 |     fontSize: 14,
60 |     color: colors.secondary,
61 |   },
62 |   emptyContainer: {
63 |     flex: 1,
64 |     justifyContent: 'center',
65 |     alignItems: 'center',
66 |     padding: 32,
67 |   },
68 |   emptyText: {
69 |     fontSize: 16,
70 |     color: colors.secondary,
71 |     textAlign: 'center',
72 |   },
73 | });
74 | 
```

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

```typescript
 1 | import axios from 'axios';
 2 | import AsyncStorage from '@react-native-async-storage/async-storage';
 3 | import { API } from './config';
 4 | 
 5 | const axiosRequest = axios.create({
 6 |   baseURL: API.BASE_URL,
 7 |   timeout: 30000,
 8 |   headers: {
 9 |     'Accept': 'application/json'
10 |   },
11 |   transformRequest: [(data, headers) => {
12 |     // Don't transform FormData
13 |     if (data instanceof FormData) {
14 |       return data;
15 |     }
16 |     
17 |     // For regular objects, transform to form-urlencoded
18 |     if (data && typeof data === 'object') {
19 |       headers['Content-Type'] = 'application/x-www-form-urlencoded';
20 |       return Object.entries(data)
21 |         .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
22 |         .join('&');
23 |     }
24 |     return data;
25 |   }]
26 | });
27 | 
28 | // Request interceptor
29 | axiosRequest.interceptors.request.use(
30 |   async (config) => {
31 |     console.log('Making request to:', config.url);
32 |     console.log('Request data:', config.data);
33 |     console.log('Request headers:', config.headers);
34 |     console.log('Request method:', config.method);
35 |     return config;
36 |   },
37 |   (error) => {
38 |     return Promise.reject(error);
39 |   }
40 | );
41 | 
42 | // Response interceptor
43 | axiosRequest.interceptors.response.use(
44 |   (response) => {
45 |     console.log('API Response:', response.data);
46 |     return response;
47 |   },
48 |   (error) => {
49 |     console.error('API Error:', error.response?.data || error.message);
50 |     return Promise.reject(error);
51 |   }
52 | );
53 | 
54 | export default axiosRequest;
55 | 
```

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

```typescript
 1 | import axios from 'axios';
 2 | import AsyncStorage from '@react-native-async-storage/async-storage';
 3 | import { API } from '../config/apiConfig';
 4 | 
 5 | const axiosRequest = axios.create({
 6 |   baseURL: API.BASE_URL,
 7 |   timeout: 30000,
 8 |   headers: {
 9 |     'Accept': 'application/json'
10 |   },
11 |   transformRequest: [(data, headers) => {
12 |     // Don't transform FormData
13 |     if (data instanceof FormData) {
14 |       return data;
15 |     }
16 |     
17 |     // For regular objects, transform to form-urlencoded
18 |     if (data && typeof data === 'object') {
19 |       headers['Content-Type'] = 'application/x-www-form-urlencoded';
20 |       return Object.entries(data)
21 |         .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
22 |         .join('&');
23 |     }
24 |     return data;
25 |   }]
26 | });
27 | 
28 | // Request interceptor
29 | axiosRequest.interceptors.request.use(
30 |   async (config) => {
31 |     console.log('Making request to:', config.url);
32 |     console.log('Request data:', config.data);
33 |     console.log('Request headers:', config.headers);
34 |     console.log('Request method:', config.method);
35 |     return config;
36 |   },
37 |   (error) => {
38 |     return Promise.reject(error);
39 |   }
40 | );
41 | 
42 | // Response interceptor
43 | axiosRequest.interceptors.response.use(
44 |   (response) => {
45 |     console.log('API Response:', response.data);
46 |     return response;
47 |   },
48 |   (error) => {
49 |     console.error('API Error:', error.response?.data || error.message);
50 |     return Promise.reject(error);
51 |   }
52 | );
53 | 
54 | export default axiosRequest;
55 | 
```

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

```typescript
 1 | import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | type Styles = {
 5 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 6 | };
 7 | 
 8 | export const styles = StyleSheet.create<Styles>({
 9 | container: {
10 |     flex: 1,
11 |     backgroundColor: colors.white,
12 |   },
13 |   header: {
14 |     padding: 20,
15 |     paddingTop: 40,
16 |   },
17 |   title: {
18 |     fontSize: 24,
19 |     fontWeight: 'bold',
20 |     marginBottom: 10,
21 |   },
22 |   backButton: {
23 |     color: colors.white,
24 |   },
25 |   subtitle: {
26 |     fontSize: 16,
27 |     color: colors.dark,
28 |     marginBottom: 20,
29 |   },
30 |   formContainer: {
31 |     padding: 20,
32 |   },
33 |   inputGroup: {
34 |     marginBottom: 20,
35 |   },
36 |   label: {
37 |     fontSize: 16,
38 |     marginBottom: 8,
39 |     color: colors.dark,
40 |   },
41 |   inputContainer: {
42 |     flexDirection: 'row',
43 |     alignItems: 'center',
44 |     borderWidth: 1,
45 |     borderColor: colors.dark,
46 |     borderRadius: 8,
47 |     paddingHorizontal: 12,
48 |     backgroundColor: colors.light,
49 |   },
50 |   inputIcon: {
51 |     marginRight: 10,
52 |   },
53 |   input: {
54 |     flex: 1,
55 |     height: 48,
56 |     fontSize: 16,
57 |     color: colors.dark,
58 |   },
59 |   errorText: {
60 |     color: colors.danger,
61 |     fontSize: 14,
62 |     marginTop: 5,
63 |   },
64 |   button: {
65 |     backgroundColor: colors.primary,
66 |     borderRadius: 8,
67 |     height: 48,
68 |     justifyContent: 'center',
69 |     alignItems: 'center',
70 |     marginTop: 20,
71 |   },
72 |   disabledButton: {
73 |     opacity: 0.7,
74 |   },
75 |   buttonText: {
76 |     color: '#fff',
77 |     fontSize: 16,
78 |     fontWeight: '600',
79 |   },
80 | });
81 | 
```

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

```typescript
 1 | import { StyleSheet, Dimensions, ViewStyle, TextStyle, ImageStyle, Platform } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | const { width } = Dimensions.get('window');
 5 | 
 6 | type Styles = {
 7 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 8 | };
 9 | 
10 | export const styles = StyleSheet.create({
11 |   safeArea: {
12 |     flex: 1,
13 |     backgroundColor: colors.white,
14 |   },
15 |   keyboardAvoidingView: {
16 |     flex: 1,
17 |   },
18 |   contentContainer: {
19 |     flex: 1,
20 |     backgroundColor: colors.white,
21 |   },
22 |   scrollView: {
23 |     flex: 1,
24 |   },
25 |   scrollViewContent: {
26 |     padding: 20,
27 |   },
28 |   formContainer: {
29 |     flex: 1,
30 |   },
31 |   buttonWrapper: {
32 |     backgroundColor: colors.white,
33 |     padding: 16,
34 |     paddingBottom: Platform.OS === 'ios' ? 0 : 16,
35 |     borderTopWidth: 1,
36 |     borderTopColor: colors.light,
37 |   },
38 |   label: {
39 |     fontSize: 16,
40 |     fontWeight: '600',
41 |     marginBottom: 5,
42 |     color: colors.dark,
43 |   },
44 |   input: {
45 |     height: 50,
46 |     borderWidth: 1,
47 |     borderColor: colors.dark,
48 |     borderRadius: 8,
49 |     paddingHorizontal: 15,
50 |     marginBottom: 15,
51 |     fontSize: 16,
52 |     color: colors.dark,
53 |     backgroundColor: colors.light,
54 |   },
55 |   messageInput: {
56 |     height: 120,
57 |     textAlignVertical: 'top',
58 |     paddingTop: 12,
59 |     paddingBottom: 12,
60 |   },
61 |   submitButton: {
62 |     backgroundColor: colors.primary,
63 |     height: 50,
64 |     borderRadius: 8,
65 |     alignItems: 'center',
66 |     justifyContent: 'center',
67 |   },
68 |   submitButtonDisabled: {
69 |     opacity: 0.7,
70 |   },
71 |   submitButtonText: {
72 |     color: colors.white,
73 |     fontSize: 16,
74 |     fontWeight: '600',
75 |   },
76 | });
77 | 
```

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

```typescript
 1 | import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
 2 | 
 3 | type Styles = {
 4 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 5 | };
 6 | 
 7 | export const styles = StyleSheet.create<Styles>({
 8 | container: {
 9 |     flex: 1,
10 |     backgroundColor: '#fff',
11 |   },
12 |   header: {
13 |     padding: 16,
14 |     backgroundColor: '#f5f5f5',
15 |   },
16 |   title: {
17 |     fontSize: 24,
18 |     fontWeight: 'bold',
19 |     color: '#333',
20 |   },
21 |   content: {
22 |     flex: 1,
23 |     padding: 16,
24 |   },
25 |   messageContainer: {
26 |     marginBottom: 16,
27 |     padding: 16,
28 |     backgroundColor: '#f9f9f9',
29 |     borderRadius: 8,
30 |     borderWidth: 1,
31 |     borderColor: '#eee',
32 |   },
33 |   inputContainer: {
34 |     marginTop: 16,
35 |   },
36 |   input: {
37 |     borderWidth: 1,
38 |     borderColor: '#ddd',
39 |     borderRadius: 8,
40 |     padding: 12,
41 |     marginBottom: 12,
42 |     minHeight: 100,
43 |     textAlignVertical: 'top',
44 |   },
45 |   submitButton: {
46 |     backgroundColor: '#007AFF',
47 |     padding: 16,
48 |     borderRadius: 8,
49 |     alignItems: 'center',
50 |   },
51 |   submitButtonText: {
52 |     color: '#fff',
53 |     fontSize: 16,
54 |     fontWeight: '600',
55 |   },
56 |   loadingText: {
57 |     color: '#666',
58 |     fontSize: 16,
59 |     textAlign: 'center',
60 |     padding: 16,
61 |   },
62 |   // HTML content styles
63 |   htmlContent: {
64 |     color: '#333',
65 |     fontSize: 16,
66 |     lineHeight: 24,
67 |   },
68 |   paragraph: {
69 |     marginVertical: 8,
70 |     color: '#333',
71 |     fontSize: 16,
72 |     lineHeight: 24,
73 |   },
74 |   heading1: {
75 |     fontSize: 24,
76 |     fontWeight: 'bold',
77 |     color: '#333',
78 |     marginVertical: 12,
79 |   },
80 |   heading2: {
81 |     fontSize: 20,
82 |     fontWeight: 'bold',
83 |     color: '#333',
84 |     marginVertical: 10,
85 |   },
86 | });
87 | 
```

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

```typescript
 1 | import { StyleSheet } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | export const styles = StyleSheet.create({
 5 |   container: {
 6 |     flex: 1,
 7 |     backgroundColor: colors.white,
 8 |   },
 9 |   calendar: {
10 |     marginBottom: 0,
11 |   },
12 |   contentContainer: {
13 |     flex: 1,
14 |     backgroundColor: colors.white,
15 |   },
16 |   sectionHeader: {
17 |     backgroundColor: colors.white,
18 |     borderBottomWidth: 1,
19 |     borderTopWidth: 1,
20 |     borderColor: colors.light,
21 |   },
22 |   sectionTitle: {
23 |     color: colors.black,
24 |     textAlign: 'center',
25 |   },
26 |   titleContainer: {
27 |     backgroundColor: colors.light,
28 |     margin: 15,
29 |     borderRadius: 8,
30 |     shadowColor: colors.black,
31 |     shadowOffset: {
32 |       width: 0,
33 |       height: 1,
34 |     },
35 |     shadowOpacity: 0.1,
36 |     shadowRadius: 2,
37 |     elevation: 2,
38 |   },
39 |   eventsContainer: {
40 |     flex: 1,
41 |     paddingHorizontal: 15,
42 |   },
43 |   eventCard: {
44 |     backgroundColor: colors.white,
45 |     padding: 15,
46 |     marginBottom: 12,
47 |     borderRadius: 10,
48 |     shadowColor: colors.black,
49 |     shadowOffset: {
50 |       width: 0,
51 |       height: 2,
52 |     },
53 |     shadowOpacity: 0.1,
54 |     shadowRadius: 3,
55 |     elevation: 3,
56 |     borderWidth: 1,
57 |     borderColor: colors.light,
58 |   },
59 |   eventTitle: {
60 |     fontSize: 16,
61 |     fontWeight: 'bold',
62 |     color: colors.black,
63 |     marginBottom: 8,
64 |   },
65 |   eventTime: {
66 |     fontSize: 14,
67 |     color: colors.secondary,
68 |     marginBottom: 8,
69 |     fontWeight: '500',
70 |   },
71 |   eventLocation: {
72 |     fontSize: 14,
73 |     color: colors.dark,
74 |     lineHeight: 20,
75 |   },
76 |   noEventsText: {
77 |     textAlign: 'center',
78 |     color: colors.dark,
79 |     fontSize: 15,
80 |     paddingVertical: 20,
81 |     fontStyle: 'italic',
82 |   },
83 | });
84 | 
```

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

```typescript
 1 | import React, { useRef, useState, useEffect } from 'react';
 2 | import { View, Text, StyleSheet } from 'react-native';
 3 | import useAppUpdate from '../../../hooks/useAppUpdate';
 4 | import { useFocusEffect } from '@react-navigation/native';
 5 | 
 6 | const HomeScreen = () => {
 7 |   // Get the checkForUpdates function from the useAppUpdate hook
 8 |   // Use a shorter interval for the home screen (30 minutes)
 9 |   const { checkForUpdates } = useAppUpdate(false, 30 * 60 * 1000);
10 |   
11 |   // Use a ref to track if we're already checking for updates
12 |   const isCheckingRef = useRef(false);
13 |   
14 |   // Track if this is the first render
15 |   const [hasCheckedOnMount, setHasCheckedOnMount] = useState(false);
16 | 
17 |   // Check for updates once when the component mounts
18 |   useEffect(() => {
19 |     if (!hasCheckedOnMount && !isCheckingRef.current) {
20 |       isCheckingRef.current = true;
21 |       
22 |       // Run the update check silently and forced
23 |       checkForUpdates(true, true).finally(() => {
24 |         isCheckingRef.current = false;
25 |         setHasCheckedOnMount(true);
26 |       });
27 |     }
28 |   }, [checkForUpdates, hasCheckedOnMount]);
29 | 
30 |   // We're not using useFocusEffect anymore to prevent multiple checks
31 |   // when the screen is repeatedly focused
32 | 
33 |   return (
34 |     <View style={styles.container}>
35 |       <Text style={styles.welcomeText}>Welcome to the Bluestone Apps Home screen</Text>
36 |     </View>
37 |   );
38 | };
39 | 
40 | const styles = StyleSheet.create({
41 |   container: {
42 |     flex: 1,
43 |     justifyContent: 'center',
44 |     alignItems: 'center',
45 |     backgroundColor: '#fff',
46 |     padding: 20,
47 |   },
48 |   welcomeText: {
49 |     fontSize: 24,
50 |     fontWeight: '600',
51 |     color: '#333',
52 |     textAlign: 'center',
53 |   },
54 | });
55 | 
56 | export default HomeScreen;
57 | 
```

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

```typescript
 1 | import { environment } from './environment';
 2 | 
 3 | interface AppConstType {
 4 |   APP_NAME: string;
 5 |   VERSION: string;
 6 | }
 7 | 
 8 | interface APIEndpoints {
 9 |   LOGIN: string;
10 |   MOBILEAPI: string;
11 |   GET_PROFILE: string;
12 |   UPDATE_PROFILE: string;
13 |   CHANGE_PASSWORD: string;
14 |   GET_ABOUTUS: string;
15 |   DELETE_USER: string;
16 |   GET_EVENTS: string;
17 |   GET_AI_API_URL: string;
18 |   GET_AI_WELCOME: string;
19 |   SAVE_AI_QNA: string;
20 |   ASK_BLUESTONEAI: string;
21 |   GET_AI_CREDENTIALS: string;
22 |   GET_TERMS_DATE: string;
23 |   GET_PRIVACY_DATE: string;
24 |   GET_TERMS_PAGE: string;
25 |   GET_PRIVACY_PAGE: string;
26 |   APP_VERSION: string;
27 | }
28 | 
29 | interface APIConfig {
30 |   BASE_URL: string;
31 |   ENDPOINTS: APIEndpoints;
32 | }
33 | 
34 | export const AppConst: AppConstType = {
35 |   APP_NAME: 'LA React Native',
36 |   VERSION: '1.5.0',
37 | };
38 | 
39 | export const API: APIConfig = {
40 |   BASE_URL: environment.baseURL,
41 |   ENDPOINTS: {
42 |     LOGIN: 'wp-json/jwt-auth/v1/token',
43 |     MOBILEAPI: 'wp-json/mobileapi/v1',
44 |     GET_PROFILE: 'wp-json/mobileapi/v1/getProfile',
45 |     UPDATE_PROFILE: 'wp-json/mobileapi/v1/updateProfile',
46 |     CHANGE_PASSWORD: 'updatePassword',
47 |     GET_ABOUTUS: 'get_aboutus',
48 |     DELETE_USER: 'delete_user',
49 |     GET_EVENTS: 'wp-json/mobileapi/v1/getEvents',
50 |     GET_AI_API_URL: 'get_ai_api_url',
51 |     GET_AI_WELCOME: 'get_ai_welcome',
52 |     SAVE_AI_QNA: 'save_ai_qna',
53 |     ASK_BLUESTONEAI: 'ask_bluestoneai',
54 |     GET_AI_CREDENTIALS: 'get_ai_credentials',
55 |     GET_TERMS_DATE: 'wp-json/mobileapi/v1/getTermsPublishedDate',
56 |     GET_PRIVACY_DATE: 'wp-json/mobileapi/v1/getPrivacyPublishedDate',
57 |     GET_TERMS_PAGE: 'wp-json/mobileapi/v1/getTermsPage',
58 |     GET_PRIVACY_PAGE: 'wp-json/mobileapi/v1/getPrivacyPage',
59 |     APP_VERSION: 'wp-json/mobileapi/v1/app_version'
60 |   }
61 | };
62 | 
```

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

```typescript
 1 | import { environment } from '../config/environment';
 2 | 
 3 | interface AppConstType {
 4 |   APP_NAME: string;
 5 |   VERSION: string;
 6 | }
 7 | 
 8 | interface APIEndpoints {
 9 |   LOGIN: string;
10 |   MOBILEAPI: string;
11 |   GET_PROFILE: string;
12 |   UPDATE_PROFILE: string;
13 |   CHANGE_PASSWORD: string;
14 |   GET_ABOUTUS: string;
15 |   DELETE_USER: string;
16 |   GET_EVENTS: string;
17 |   GET_AI_API_URL: string;
18 |   GET_AI_WELCOME: string;
19 |   SAVE_AI_QNA: string;
20 |   ASK_BLUESTONEAI: string;
21 |   GET_AI_CREDENTIALS: string;
22 |   GET_TERMS_DATE: string;
23 |   GET_PRIVACY_DATE: string;
24 |   GET_TERMS_PAGE: string;
25 |   GET_PRIVACY_PAGE: string;
26 |   APP_VERSION: string;
27 | }
28 | 
29 | interface APIConfig {
30 |   BASE_URL: string;
31 |   ENDPOINTS: APIEndpoints;
32 | }
33 | 
34 | export const AppConst: AppConstType = {
35 |   APP_NAME: 'LA React Native',
36 |   VERSION: '1.5.0',
37 | };
38 | 
39 | export const API: APIConfig = {
40 |   BASE_URL: environment.baseURL,
41 |   ENDPOINTS: {
42 |     LOGIN: 'wp-json/jwt-auth/v1/token',
43 |     MOBILEAPI: 'wp-json/mobileapi/v1',
44 |     GET_PROFILE: 'wp-json/mobileapi/v1/getProfile',
45 |     UPDATE_PROFILE: 'wp-json/mobileapi/v1/updateProfile',
46 |     CHANGE_PASSWORD: 'updatePassword',
47 |     GET_ABOUTUS: 'get_aboutus',
48 |     DELETE_USER: 'delete_user',
49 |     GET_EVENTS: 'wp-json/mobileapi/v1/getEvents',
50 |     GET_AI_API_URL: 'get_ai_api_url',
51 |     GET_AI_WELCOME: 'get_ai_welcome',
52 |     SAVE_AI_QNA: 'save_ai_qna',
53 |     ASK_BLUESTONEAI: 'ask_bluestoneai',
54 |     GET_AI_CREDENTIALS: 'get_ai_credentials',
55 |     GET_TERMS_DATE: 'wp-json/mobileapi/v1/getTermsPublishedDate',
56 |     GET_PRIVACY_DATE: 'wp-json/mobileapi/v1/getPrivacyPublishedDate',
57 |     GET_TERMS_PAGE: 'wp-json/mobileapi/v1/getTermsPage',
58 |     GET_PRIVACY_PAGE: 'wp-json/mobileapi/v1/getPrivacyPage',
59 |     APP_VERSION: 'wp-json/mobileapi/v1/app_version'
60 |   }
61 | };
62 | 
```

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

```typescript
 1 | import { StyleSheet, Dimensions } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | const { width } = Dimensions.get('window');
 5 | 
 6 | export const styles = StyleSheet.create({
 7 |   container: {
 8 |     flex: 1,
 9 |     backgroundColor: colors.white,
10 |     padding: 20,
11 |     justifyContent: 'center',
12 |   },
13 |   logoContainer: {
14 |     alignItems: 'center',
15 |     marginBottom: 20,
16 |   },
17 |   logo: {
18 |     width: width * 0.6,
19 |     height: 300,
20 |   },
21 |   title: {
22 |     fontSize: 28,
23 |     fontWeight: 'bold',
24 |     color: colors.primary,
25 |     marginBottom: 30,
26 |     textAlign: 'center',
27 |   },
28 |   input: {
29 |     height: 50,
30 |     borderWidth: 1,
31 |     borderColor: colors.dark,
32 |     borderRadius: 8,
33 |     paddingHorizontal: 15,
34 |     marginBottom: 15,
35 |     fontSize: 16,
36 |     color: colors.dark,
37 |     backgroundColor: colors.light,
38 |   },
39 |   passwordContainer: {
40 |     position: 'relative',
41 |     marginBottom: 15,
42 |   },
43 |   eyeIcon: {
44 |     position: 'absolute',
45 |     right: 15,
46 |     top: 13,
47 |   },
48 |   checkboxContainer: {
49 |     flexDirection: 'row',
50 |     alignItems: 'center',
51 |     marginBottom: 20,
52 |   },
53 |   customCheckbox: {
54 |     width: 24,
55 |     height: 24,
56 |     borderRadius: 4,
57 |     borderWidth: 2,
58 |     borderColor: colors.primary,
59 |     marginRight: 10,
60 |     justifyContent: 'center',
61 |     alignItems: 'center',
62 |   },
63 |   customCheckboxChecked: {
64 |     backgroundColor: colors.primary,
65 |   },
66 |   checkboxLabel: {
67 |     fontSize: 16,
68 |     color: colors.dark,
69 |   },
70 |   button: {
71 |     backgroundColor: colors.primary,
72 |     height: 50,
73 |     borderRadius: 8,
74 |     justifyContent: 'center',
75 |     alignItems: 'center',
76 |   },
77 |   buttonText: {
78 |     color: colors.white,
79 |     fontSize: 18,
80 |     fontWeight: '600',
81 |   },
82 |   linkContainer: {
83 |     flexDirection: 'row',
84 |     justifyContent: 'space-between',
85 |     marginTop: 20,
86 |   },
87 |   link: {
88 |     color: colors.secondary,
89 |     fontSize: 16,
90 |   },
91 | });
92 | 
```

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

```typescript
 1 | import AsyncStorage from '@react-native-async-storage/async-storage';
 2 | 
 3 | class StorageService {
 4 |   async set(key: string, value: any): Promise<void> {
 5 |     try {
 6 |       await AsyncStorage.setItem(key, JSON.stringify(value));
 7 |     } catch (error) {
 8 |       console.error('Error saving to storage:', error);
 9 |       throw error;
10 |     }
11 |   }
12 | 
13 |   async get(key: string): Promise<any> {
14 |     try {
15 |       const item = await AsyncStorage.getItem(key);
16 |       return item ? JSON.parse(item) : null;
17 |     } catch (error) {
18 |       console.error('Error reading from storage:', error);
19 |       throw error;
20 |     }
21 |   }
22 | 
23 |   async remove(key: string): Promise<void> {
24 |     try {
25 |       await AsyncStorage.removeItem(key);
26 |     } catch (error) {
27 |       console.error('Error removing from storage:', error);
28 |       throw error;
29 |     }
30 |   }
31 | 
32 |   async clearAll(): Promise<void> {
33 |     try {
34 |       // Get all keys first
35 |       const keys = await AsyncStorage.getAllKeys();
36 |       
37 |       if (keys.length === 0) {
38 |         return; // Nothing to clear
39 |       }
40 |       
41 |       // Try multiRemove first as it's more efficient
42 |       try {
43 |         await AsyncStorage.multiRemove(keys);
44 |         return;
45 |       } catch (multiError) {
46 |         console.warn('Error with multiRemove, falling back to individual removal:', multiError);
47 |         
48 |         // Fall back to removing items one by one
49 |         for (const key of keys) {
50 |           try {
51 |             await AsyncStorage.removeItem(key);
52 |           } catch (individualError) {
53 |             console.warn(`Failed to remove item with key: ${key}`, individualError);
54 |             // Continue with other keys
55 |           }
56 |         }
57 |       }
58 |     } catch (error) {
59 |       console.error('Error clearing storage:', error);
60 |       // Don't throw the error, just log it
61 |     }
62 |   }
63 | }
64 | 
65 | export const storageService = new StorageService();
66 | 
```

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

```typescript
 1 | import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
 2 | import { colors } from '../../../theme/colors';
 3 | 
 4 | type Styles = {
 5 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
 6 | };
 7 | 
 8 | export const styles = StyleSheet.create<Styles>({
 9 | container: {
10 |     flex: 1,
11 |     backgroundColor: '#fff',
12 |   },
13 |   header: {
14 |     alignItems: 'center',
15 |     padding: 20,
16 |     backgroundColor: colors.light,
17 |   },
18 |   avatarContainer: {
19 |     width: 120,
20 |     height: 120,
21 |     borderRadius: 60,
22 |     overflow: 'hidden',
23 |     backgroundColor: colors.light,
24 |     position: 'relative',
25 |   },
26 |   profileImage: {
27 |     width: '100%',
28 |     height: '100%',
29 |   },
30 |   cameraIconContainer: {
31 |     position: 'absolute',
32 |     bottom: 0,
33 |     right: 0,
34 |     backgroundColor: colors.primary,
35 |     width: 36,
36 |     height: 36,
37 |     borderRadius: 18,
38 |     justifyContent: 'center',
39 |     alignItems: 'center',
40 |   },
41 |   formContainer: {
42 |     padding: 20,
43 |   },
44 |   inputGroup: {
45 |     marginBottom: 20,
46 |   },
47 |   label: {
48 |     fontSize: 14,
49 |     color: '#666',
50 |     marginBottom: 8,
51 |   },
52 |   inputContainer: {
53 |     flexDirection: 'row',
54 |     alignItems: 'center',
55 |     borderWidth: 1,
56 |     borderColor: colors.dark,
57 |     borderRadius: 8,
58 |     paddingHorizontal: 12,
59 |     backgroundColor: colors.light,
60 |   },
61 |   inputIcon: {
62 |     marginRight: 10,
63 |   },
64 |   input: {
65 |     flex: 1,
66 |     height: 48,
67 |     fontSize: 16,
68 |     color: colors.black,
69 |     backgroundColor: colors.light,
70 |   },
71 |   errorText: {
72 |     color: colors.danger,
73 |     fontSize: 12,
74 |     marginTop: 4,
75 |   },
76 |   buttonContainer: {
77 |     padding: 20,
78 |     paddingBottom: 40,
79 |   },
80 |   button: {
81 |     backgroundColor: colors.primary,
82 |     padding: 15,
83 |     borderRadius: 8,
84 |     alignItems: 'center',
85 |   },
86 |   disabledButton: {
87 |     opacity: 0.7,
88 |   },
89 |   buttonText: {
90 |     color: colors.white,
91 |     fontSize: 16,
92 |     fontWeight: '600',
93 |   },
94 |   backButton: {
95 |     color: colors.white,
96 |   }
97 | });
98 | 
```

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

```typescript
  1 | import { StyleSheet, Dimensions } from 'react-native';
  2 | import { colors } from '../../../theme/colors';
  3 | 
  4 | const { width } = Dimensions.get('window');
  5 | 
  6 | export const styles = StyleSheet.create({
  7 |   container: {
  8 |     flex: 1,
  9 |     backgroundColor: colors.white,
 10 |     padding: 20,
 11 |   },
 12 |   scrollContainer: {
 13 |     flexGrow: 1,
 14 |     justifyContent: 'center',
 15 |   },
 16 |   logoContainer: {
 17 |     alignItems: 'center',
 18 |     marginBottom: 0,
 19 |   },
 20 |   logo: {
 21 |     width: width * 0.6,
 22 |     height: 200,
 23 |     resizeMode: 'contain',
 24 |   },
 25 |   title: {
 26 |     fontSize: 28,
 27 |     fontWeight: 'bold',
 28 |     color: colors.primary,
 29 |     marginBottom: 30,
 30 |     textAlign: 'center',
 31 |   },
 32 |   input: {
 33 |     height: 50,
 34 |     borderWidth: 1,
 35 |     borderColor: colors.dark,
 36 |     borderRadius: 8,
 37 |     paddingHorizontal: 15,
 38 |     marginBottom: 15,
 39 |     fontSize: 16,
 40 |     backgroundColor: colors.light,
 41 |     color: colors.primary,
 42 |   },
 43 |   errorText: {
 44 |     color: colors.danger,
 45 |     fontSize: 14,
 46 |     marginTop: -10,
 47 |     marginBottom: 10,
 48 |     marginLeft: 5,
 49 |   },
 50 |   checkboxContainer: {
 51 |     flexDirection: 'row',
 52 |     alignItems: 'center',
 53 |     marginBottom: 20,
 54 |   },
 55 |   customCheckbox: {
 56 |     width: 20,
 57 |     height: 20,
 58 |     borderRadius: 4,
 59 |     borderWidth: 2,
 60 |     borderColor: colors.dark,
 61 |     marginRight: 8,
 62 |     justifyContent: 'center',
 63 |     alignItems: 'center',
 64 |   },
 65 |   customCheckboxChecked: {
 66 |     backgroundColor: colors.primary,
 67 |   },
 68 |   checkboxLabel: {
 69 |     flex: 1,
 70 |     marginLeft: 8,
 71 |     color: colors.primary,
 72 |   },
 73 |   button: {
 74 |     backgroundColor: colors.primary,
 75 |     height: 50,
 76 |     borderRadius: 8,
 77 |     justifyContent: 'center',
 78 |     alignItems: 'center',
 79 |     marginBottom: 20,
 80 |   },
 81 |   buttonText: {
 82 |     color: colors.white,
 83 |     fontSize: 18,
 84 |     fontWeight: '600',
 85 |   },
 86 |   linkContainer: {
 87 |     flexDirection: 'row',
 88 |     justifyContent: 'center',
 89 |     marginTop: 10,
 90 |   },
 91 |   linkText: {
 92 |     color: colors.primary,
 93 |     fontSize: 16,
 94 |   },
 95 |   link: {
 96 |     color: colors.primary,
 97 |     textDecorationLine: 'underline',
 98 |     fontSize: 16,
 99 |     marginLeft: 5,
100 |   },
101 | });
102 | 
```

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

```typescript
 1 | import axiosRequest from './axiosRequest';
 2 | import {API} from './config';
 3 | import AsyncStorage from '@react-native-async-storage/async-storage';
 4 | import { LoginResponse, AuthError } from './types';
 5 | 
 6 | class AuthService {
 7 |   async login(email: string, password: string): Promise<LoginResponse> {
 8 |     try {
 9 |       console.log('Attempting login with:', { email });
10 | 
11 |       const data = {
12 |         email: email.trim(),
13 |         password: password
14 |       };
15 | 
16 |       console.log('Making request to:', API.ENDPOINTS.LOGIN, 'with data:', data);
17 | 
18 |       const response = await axiosRequest.post<LoginResponse>(
19 |         API.ENDPOINTS.LOGIN,
20 |         data
21 |       );
22 | 
23 |       console.log('Login response:', response);
24 | 
25 |       if (response?.loginInfo?.token) {
26 |         await AsyncStorage.setItem('userToken', response.loginInfo.token);
27 |         // Store data in the correct format expected by the profile screen
28 |         const userData = { loginInfo: response.loginInfo };
29 |         console.log('Storing userData in AuthService:', userData);
30 |         await AsyncStorage.setItem('userData', JSON.stringify(userData));
31 |       }
32 | 
33 |       return response;
34 |     } catch (error) {
35 |       console.error('Login error:', error);
36 |       throw error as AuthError;
37 |     }
38 |   }
39 | 
40 |   async logout(): Promise<void> {
41 |     try {
42 |       // Try to remove items individually first
43 |       const keys = ['userToken', 'userData', 'rememberMe'];
44 |       
45 |       for (const key of keys) {
46 |         try {
47 |           await AsyncStorage.removeItem(key);
48 |         } catch (err) {
49 |           console.warn(`Error removing ${key}:`, err);
50 |           // Continue with other keys even if one fails
51 |         }
52 |       }
53 |       
54 |       // If we're still here, try to perform any navigation or state resets
55 |       return;
56 |     } catch (error) {
57 |       console.error('Logout error:', error);
58 |       // Don't throw the error, just log it and continue
59 |       // This prevents the error from bubbling up to the UI
60 |       return;
61 |     }
62 |   }
63 | 
64 |   // Add other auth-related methods here
65 | }
66 | 
67 | export default new AuthService();
68 | 
```

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

```typescript
  1 | import { StyleSheet, ViewStyle, TextStyle, ImageStyle } from 'react-native';
  2 | import { colors } from '../../../theme/colors';
  3 | 
  4 | type Styles = {
  5 |     [key: string]: ViewStyle | TextStyle | ImageStyle;
  6 | };
  7 | 
  8 | export const styles = StyleSheet.create<Styles>({
  9 | container: {
 10 |     flex: 1,
 11 |     backgroundColor: colors.white,
 12 |   },
 13 |   centerContent: {
 14 |     justifyContent: 'center',
 15 |     alignItems: 'center',
 16 |   },
 17 |   header: {
 18 |     alignItems: 'center',
 19 |     padding: 20,
 20 |     backgroundColor: colors.light,
 21 |   },
 22 |   avatarContainer: {
 23 |     width: 120,
 24 |     height: 120,
 25 |     borderRadius: 60,
 26 |     overflow: 'hidden',
 27 |     marginBottom: 15,
 28 |     backgroundColor: colors.primary,
 29 |   },
 30 |   profileImage: {
 31 |     width: '100%',
 32 |     height: '100%',
 33 |   },
 34 |   name: {
 35 |     fontSize: 24,
 36 |     fontWeight: '600',
 37 |     color: '#000',
 38 |     marginBottom: 5,
 39 |   },
 40 |   location: {
 41 |     fontSize: 16,
 42 |     color: colors.dark,
 43 |     marginTop: 4,
 44 |   },
 45 |   infoSection: {
 46 |     padding: 20,
 47 |     backgroundColor: colors.white,
 48 |     borderRadius: 8,
 49 |     margin: 16,
 50 |     shadowColor: colors.black,
 51 |     shadowOffset: {
 52 |       width: 0,
 53 |       height: 2,
 54 |     },
 55 |     shadowOpacity: 0.1,
 56 |     shadowRadius: 4,
 57 |     elevation: 3,
 58 |   },
 59 |   infoItem: {
 60 |     flexDirection: 'row',
 61 |     alignItems: 'center',
 62 |     paddingVertical: 12,
 63 |     borderBottomWidth: 1,
 64 |     borderBottomColor: colors.light,
 65 |   },
 66 |   icon: {
 67 |     marginRight: 15,
 68 |   },
 69 |   label: {
 70 |     fontSize: 14,
 71 |     color: '#666',
 72 |     marginBottom: 4,
 73 |   },
 74 |   value: {
 75 |     fontSize: 16,
 76 |     color: '#000',
 77 |   },
 78 |   buttonContainer: {
 79 |     padding: 20,
 80 |     paddingTop: 0,
 81 |   },
 82 |   button: {
 83 |     backgroundColor: colors.primary,
 84 |     borderRadius: 8,
 85 |     padding: 15,
 86 |     alignItems: 'center',
 87 |     marginBottom: 10,
 88 |   },
 89 |   secondaryButton: {
 90 |     backgroundColor: colors.secondary,
 91 |     borderWidth: 1,
 92 |     borderColor: colors.light,
 93 |   },
 94 |   buttonText: {
 95 |     color: colors.white,
 96 |     fontSize: 16,
 97 |     fontWeight: '600',
 98 |   },
 99 |   secondaryButtonText: {
100 |     color: colors.white,
101 |   },
102 |   errorText: {
103 |     fontSize: 16,
104 |     color: '#ff3b30',
105 |     textAlign: 'center',
106 |   },
107 | });
108 | 
```

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

```typescript
 1 | /**
 2 |  * Type declarations for React Native
 3 |  * 
 4 |  * This file provides type definitions for React Native components and APIs
 5 |  * used in the theme examples. This allows TypeScript to understand React Native
 6 |  * types without requiring the full React Native package to be installed.
 7 |  */
 8 | 
 9 | declare module 'react-native' {
10 |   export interface TextStyle {
11 |     fontFamily?: string;
12 |     fontSize?: number;
13 |     fontStyle?: 'normal' | 'italic';
14 |     fontWeight?: string | number;
15 |     letterSpacing?: number;
16 |     lineHeight?: number;
17 |     textAlign?: 'auto' | 'left' | 'right' | 'center' | 'justify';
18 |     textDecorationLine?: 'none' | 'underline' | 'line-through' | 'underline line-through';
19 |     textDecorationStyle?: 'solid' | 'double' | 'dotted' | 'dashed';
20 |     textDecorationColor?: string;
21 |     textTransform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase';
22 |     color?: string;
23 |     includeFontPadding?: boolean;
24 |     textAlignVertical?: 'auto' | 'top' | 'bottom' | 'center';
25 |     fontVariant?: string[];
26 |     writingDirection?: 'auto' | 'ltr' | 'rtl';
27 |   }
28 | 
29 |   export interface ViewStyle {
30 |     backgroundColor?: string;
31 |     borderBottomColor?: string;
32 |     borderBottomEndRadius?: number;
33 |     borderBottomLeftRadius?: number;
34 |     borderBottomRightRadius?: number;
35 |     borderBottomStartRadius?: number;
36 |     borderBottomWidth?: number;
37 |     borderColor?: string;
38 |     borderEndColor?: string;
39 |     borderEndWidth?: number;
40 |     borderLeftColor?: string;
41 |     borderLeftWidth?: number;
42 |     borderRadius?: number;
43 |     borderRightColor?: string;
44 |     borderRightWidth?: number;
45 |     borderStartColor?: string;
46 |     borderStartWidth?: number;
47 |     borderStyle?: 'solid' | 'dotted' | 'dashed';
48 |     borderTopColor?: string;
49 |     borderTopEndRadius?: number;
50 |     borderTopLeftRadius?: number;
51 |     borderTopRightRadius?: number;
52 |     borderTopStartRadius?: number;
53 |     borderTopWidth?: number;
54 |     borderWidth?: number;
55 |     opacity?: number;
56 |     elevation?: number;
57 |     shadowColor?: string;
58 |     shadowOffset?: { width: number; height: number };
59 |     shadowOpacity?: number;
60 |     shadowRadius?: number;
61 |   }
62 | 
63 |   export const Platform: {
64 |     OS: 'ios' | 'android' | 'web';
65 |     select: <T extends Record<string, any>>(obj: T) => T[keyof T];
66 |   };
67 | }
68 | 
```

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

```typescript
 1 | import { storageService } from './storageService';
 2 | import { environment } from '../config/environment';
 3 | 
 4 | const BASE_URL = `https://${environment.server}/`;
 5 | const MOBILE_API = `${BASE_URL}wp-json/mobileapi/v1/`;
 6 | 
 7 | interface ApiResponse {
 8 |   status: string;
 9 |   errormsg: string;
10 |   error_code: string;
11 |   categories: Array<{
12 |     category_id: number;
13 |     category_name: string;
14 |     posts: Array<{
15 |       post_id: number;
16 |       post_title: string;
17 |       post_content: string;
18 |       post_date: string;
19 |       featured_image?: string;
20 |     }>;
21 |   }>;
22 | }
23 | 
24 | class ApiService {
25 |   async getData(endpoint: string) {
26 |     try {
27 |       console.log('Fetching from:', MOBILE_API + endpoint);
28 |       const response = await fetch(MOBILE_API + endpoint);
29 |       if (!response.ok) {
30 |         throw new Error(`HTTP error! status: ${response.status}`);
31 |       }
32 |       const data = await response.json();
33 |       return data;
34 |     } catch (error) {
35 |       console.error('Error fetching data:', error);
36 |       throw error;
37 |     }
38 |   }
39 | 
40 |   async sendData(endpoint: string, data: any) {
41 |     const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
42 |     const payload = {
43 |       ...(typeof data === 'object' ? data : { value: data }),
44 |       timezone,
45 |     };
46 | 
47 |     try {
48 |       const response = await fetch(MOBILE_API + endpoint, {
49 |         method: 'POST',
50 |         headers: {
51 |           'Content-Type': 'application/json',
52 |         },
53 |         body: JSON.stringify(payload),
54 |       });
55 | 
56 |       if (!response.ok) {
57 |         throw new Error(`HTTP error! status: ${response.status}`);
58 |       }
59 | 
60 |       const result = await response.json();
61 |       return result;
62 |     } catch (error) {
63 |       console.error('Error sending data:', error);
64 |       throw error;
65 |     }
66 |   }
67 | 
68 |   async fetchAndStorePosts() {
69 |     try {
70 |       const response = await this.getData('getPostsByCategories') as ApiResponse;
71 |       console.log('API Response:', response);
72 |       
73 |       if (response?.status === 'ok' && response?.categories) {
74 |         await storageService.set('posts', response.categories);
75 |         return response.categories;
76 |       }
77 |       return null;
78 |     } catch (error) {
79 |       console.error('Error fetching posts:', error);
80 |       throw error;
81 |     }
82 |   }
83 | }
84 | 
85 | export const apiService = new ApiService();
86 | 
```

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

```typescript
 1 | import React from 'react';
 2 | import { NavigationContainer } from '@react-navigation/native';
 3 | import { createNativeStackNavigator } from '@react-navigation/native-stack';
 4 | import LoginScreen from '../screens/PreLogin/Login/LoginScreen';
 5 | 
 6 | import ForgotPasswordScreen from '../screens/PreLogin/ForgotPassword/ForgotPasswordScreen';
 7 | import SignUpScreen from '../screens/PreLogin/SignUp/SignUpScreen';
 8 | import VerifyEmailScreen from '../screens/PreLogin/VerifyEmail/VerifyEmailScreen';
 9 | import DrawerNavigator from './DrawerNavigator';
10 | import TermsAndConditionsScreen from '../screens/PreLogin/Legal/TermsAndConditionsScreen';
11 | import PrivacyPolicyScreen from '../screens/PreLogin/Legal/PrivacyPolicyScreen';
12 | import { withNavigationWrapper } from './NavigationWrapper';
13 | 
14 | const Stack = createNativeStackNavigator();
15 | 
16 | // Wrap components with navigation wrapper
17 | const WrappedLoginScreen = withNavigationWrapper(LoginScreen);
18 | const WrappedSignUpScreen = withNavigationWrapper(SignUpScreen);
19 | const WrappedForgotPasswordScreen = withNavigationWrapper(ForgotPasswordScreen);
20 | const WrappedVerifyEmailScreen = withNavigationWrapper(VerifyEmailScreen);
21 | const WrappedTermsAndConditionsScreen = withNavigationWrapper(TermsAndConditionsScreen);
22 | const WrappedPrivacyPolicyScreen = withNavigationWrapper(PrivacyPolicyScreen);
23 | 
24 | const AppNavigator = () => {
25 |   return (
26 |     <NavigationContainer>
27 |       <Stack.Navigator
28 |         initialRouteName="Login"
29 |         screenOptions={{
30 |           headerShown: false,
31 |           gestureEnabled: true,
32 |           animation: 'default'
33 |         }}>
34 |         <Stack.Screen
35 |           name="Login"
36 |           component={WrappedLoginScreen}
37 |         />
38 |         <Stack.Screen
39 |           name="DrawerNavigator"
40 |           component={DrawerNavigator}
41 |         />
42 |         <Stack.Screen
43 |           name="SignUp"
44 |           component={WrappedSignUpScreen}
45 |           options={{
46 |             presentation: 'card'
47 |           }}
48 |         />
49 |         <Stack.Screen
50 |           name="ForgotPassword"
51 |           component={WrappedForgotPasswordScreen}
52 |           options={{
53 |             presentation: 'card'
54 |           }}
55 |         />
56 |         <Stack.Screen
57 |           name="VerifyEmail"
58 |           component={WrappedVerifyEmailScreen}
59 |           options={{
60 |             presentation: 'card'
61 |           }}
62 |         />
63 |         <Stack.Screen
64 |           name="TermsAndConditions"
65 |           component={WrappedTermsAndConditionsScreen}
66 |           options={{
67 |             presentation: 'modal'
68 |           }}
69 |         />
70 |         <Stack.Screen
71 |           name="PrivacyPolicy"
72 |           component={WrappedPrivacyPolicyScreen}
73 |           options={{
74 |             presentation: 'modal'
75 |           }}
76 |         />
77 |       </Stack.Navigator>
78 |     </NavigationContainer>
79 |   );
80 | };
81 | 
82 | export default AppNavigator;
83 | 
```

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

```typescript
  1 | import React, { useState, useEffect } from 'react';
  2 | import { View, Text, ScrollView, Image, ActivityIndicator, useWindowDimensions } from 'react-native';
  3 | import { useNavigation, useRoute } from '@react-navigation/native';
  4 | import RenderHtml from 'react-native-render-html';
  5 | import { storageService } from '../../../helper/storageService';
  6 | import { styles } from './PostStyles';
  7 | import { colors } from '../../../theme/colors';
  8 | 
  9 | interface Post {
 10 |   post_id: string;
 11 |   post_title: string;
 12 |   post_content: string;
 13 |   post_date: string;
 14 |   featured_image?: string;
 15 | }
 16 | 
 17 | const PostScreen = () => {
 18 |   const navigation = useNavigation();
 19 |   const route = useRoute();
 20 |   const { width } = useWindowDimensions();
 21 |   const [loading, setLoading] = useState(true);
 22 |   const [post, setPost] = useState<Post | null>(null);
 23 |   const postId = route.params?.id;
 24 | 
 25 |   useEffect(() => {
 26 |     loadPost();
 27 |   }, [postId]);
 28 | 
 29 |   const loadPost = async () => {
 30 |     try {
 31 |       const categories = await storageService.get('posts');
 32 |       if (categories && Array.isArray(categories)) {
 33 |         for (const category of categories) {
 34 |           const foundPost = category.posts.find(p => p.post_id.toString() === postId?.toString());
 35 |           if (foundPost) {
 36 |             setPost(foundPost);
 37 |             navigation.setOptions({
 38 |               headerTitle: foundPost.post_title,
 39 |             });
 40 |             break;
 41 |           }
 42 |         }
 43 |       }
 44 |     } catch (error) {
 45 |       console.error('Error loading post:', error);
 46 |     } finally {
 47 |       setLoading(false);
 48 |     }
 49 |   };
 50 | 
 51 |   if (loading) {
 52 |     return (
 53 |       <View style={styles.loadingContainer}>
 54 |         <ActivityIndicator size="large" color={colors.primary} />
 55 |       </View>
 56 |     );
 57 |   }
 58 | 
 59 |   if (!post) {
 60 |     return (
 61 |       <View style={styles.errorContainer}>
 62 |         <Text style={styles.errorText}>Post not found</Text>
 63 |       </View>
 64 |     );
 65 |   }
 66 | 
 67 |   const formatDate = (dateString: string) => {
 68 |     const date = new Date(dateString);
 69 |     return date.toLocaleDateString('en-US', {
 70 |       year: 'numeric',
 71 |       month: 'long',
 72 |       day: 'numeric',
 73 |     });
 74 |   };
 75 | 
 76 |   return (
 77 |     <ScrollView style={styles.container}>
 78 |       {post.featured_image && (
 79 |         <Image
 80 |           source={{ uri: post.featured_image }}
 81 |           style={styles.featuredImage}
 82 |           resizeMode="cover"
 83 |         />
 84 |       )}
 85 |       <View style={styles.content}>
 86 |         <Text style={styles.title}>{post.post_title}</Text>
 87 |         <Text style={styles.date}>{formatDate(post.post_date)}</Text>
 88 |         <RenderHtml
 89 |           contentWidth={width - 32}
 90 |           source={{ html: post.post_content }}
 91 |           tagsStyles={{
 92 |             body: {
 93 |               color: colors.black,
 94 |               fontSize: 16,
 95 |               lineHeight: 24,
 96 |             },
 97 |             a: {
 98 |               color: colors.primary,
 99 |               textDecorationLine: 'underline',
100 |             },
101 |           }}
102 |         />
103 |       </View>
104 |     </ScrollView>
105 |   );
106 | };
107 | 
108 | export default PostScreen;
109 | 
```

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

```typescript
 1 | import React, { useEffect, useState } from 'react';
 2 | import { Alert, View, Text, StyleSheet } from 'react-native';
 3 | import { NavigationMonitorService } from '../services/NavigationMonitorService';
 4 | 
 5 | interface NavigationProps {
 6 |   navigation: any;
 7 |   route: {
 8 |     name: string;
 9 |   };
10 | }
11 | 
12 | export const withNavigationWrapper = (WrappedComponent: React.ComponentType<any>) => {
13 |   return function WithNavigationWrapper(props: NavigationProps) {
14 |     const { navigation, route } = props;
15 |     const [error, setError] = useState<string | null>(null);
16 | 
17 |     useEffect(() => {
18 |       // Only check for updates if not an excluded route
19 |       if (!NavigationMonitorService.isExcludedRoute(route.name)) {
20 |         // Perform silent update checks without showing loading indicator
21 |         try {
22 |           checkForUpdates()
23 |             .catch(err => {
24 |               console.error('Error in checkForUpdates:', err);
25 |               setError(`Failed to check for updates: ${err.message}`);
26 |             });
27 |         } catch (error) {
28 |           console.error('Error in navigation wrapper:', error);
29 |           setError(`Navigation error: ${error instanceof Error ? error.message : String(error)}`);
30 |         }
31 |       }
32 |     }, [route]);
33 | 
34 |     const checkForUpdates = async () => {
35 |       try {
36 |         // Check for updates with improved error handling
37 |         const { termsNeedsUpdate, privacyNeedsUpdate } = await NavigationMonitorService.checkForUpdates();
38 |         
39 |         // Only show alert if updates are actually needed
40 |         if (termsNeedsUpdate || privacyNeedsUpdate) {
41 |           Alert.alert(
42 |             'Update Required',
43 |             `Please review and accept the ${termsNeedsUpdate ? 'Terms' : 'Privacy Policy'} updates to continue.`,
44 |             [
45 |               {
46 |                 text: 'Review',
47 |                 onPress: () => {
48 |                   navigation.navigate(
49 |                     termsNeedsUpdate ? 'TermsAndConditions' : 'PrivacyPolicy',
50 |                     { fromUpdate: true }
51 |                   );
52 |                 },
53 |               },
54 |             ],
55 |             { cancelable: false }
56 |           );
57 |         }
58 |         
59 |         return { termsNeedsUpdate, privacyNeedsUpdate };
60 |       } catch (error) {
61 |         console.error('Failed to check for terms/privacy updates:', error);
62 |         // Don't throw here, just log the error and continue
63 |         return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
64 |       }
65 |     };
66 | 
67 |     // If there's an error, show it but still render the component
68 |     if (error) {
69 |       console.warn('NavigationWrapper encountered an error:', error);
70 |       // We could show an error UI here, but for now we'll just log it and continue
71 |     }
72 | 
73 |     // Render the wrapped component without any loading overlay
74 |     return (
75 |       <View style={styles.container}>
76 |         <WrappedComponent {...props} />
77 |       </View>
78 |     );
79 |   };
80 | };
81 | 
82 | const styles = StyleSheet.create({
83 |   container: {
84 |     flex: 1,
85 |   },
86 | });
87 | 
88 | export default withNavigationWrapper;
89 | 
```

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

```markdown
 1 | # React Native Project Structure
 2 | 
 3 | BluestoneApps recommends the following project structure for React Native applications:
 4 | 
 5 | ```
 6 | project-name/
 7 | ├── src/                    # Source code
 8 | │   ├── assets/             # Static assets (images, fonts, etc.)
 9 | │   ├── components/         # Reusable UI components
10 | │   ├── config/             # Configuration files (API endpoints, constants)
11 | │   ├── hooks/              # Custom React hooks
12 | │   ├── navigation/         # Navigation configuration
13 | │   ├── screens/            # Screen components
14 | │   │   ├── PostLogin/      # Screens available after authentication
15 | │   │   └── PreLogin/       # Authentication and onboarding screens
16 | │   ├── services/           # Business logic services
17 | │   ├── theme/              # Theme definitions (colors, spacing, etc.)
18 | │   ├── types/              # TypeScript type definitions
19 | │   └── utils/              # Utility functions
20 | ├── App.tsx                 # Root component
21 | ├── index.js                # Entry point
22 | ├── package.json            # Dependencies and scripts
23 | └── README.md               # Project documentation
24 | ```
25 | 
26 | ## Key Directories
27 | 
28 | ### `src/assets`
29 | 
30 | Contains static assets such as images, fonts, and other media files used in the application.
31 | 
32 | ### `src/components`
33 | 
34 | Reusable UI components that can be used across different screens. Each component is typically defined in its own file with associated styles.
35 | 
36 | ### `src/config`
37 | 
38 | Configuration files for the application, including API endpoint definitions, environment variables, and other constants.
39 | 
40 | ### `src/hooks`
41 | 
42 | Custom React hooks for shared logic, state management, and side effects.
43 | 
44 | ### `src/navigation`
45 | 
46 | Navigation configuration using React Navigation, including drawer navigators, stack navigators, and navigation wrappers.
47 | 
48 | ### `src/screens`
49 | 
50 | Screen components organized by authentication state:
51 | - `PostLogin`: Screens that are accessible after user authentication
52 | - `PreLogin`: Authentication screens, onboarding, and public screens
53 | 
54 | Each screen may have its own subdirectory containing the main screen component and related files (e.g., styles, subcomponents).
55 | 
56 | ### `src/services`
57 | 
58 | Business logic, API communication, data transformation, and other services. Typically implemented as singleton classes with specific responsibilities.
59 | 
60 | ### `src/theme`
61 | 
62 | Theme definitions including colors, typography, spacing, and other styling constants.
63 | 
64 | ### `src/types`
65 | 
66 | 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.
67 | 
68 | ### `src/utils`
69 | 
70 | Utility functions and helpers, including API utilities, formatting functions, and other shared logic.
71 | 
72 | ## Best Practices
73 | 
74 | 1. Use TypeScript for type safety and better developer experience
75 | 2. Implement functional components with React hooks
76 | 3. Keep components small and focused on a single responsibility
77 | 4. Extract business logic into services
78 | 5. Use consistent naming conventions (PascalCase for components, camelCase for functions)
79 | 6. Implement proper error handling in API calls and async operations
80 | 7. Use environment-specific configuration when necessary
81 | 
```

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

```typescript
  1 | import React from 'react';
  2 | import { View, Text, ScrollView, StyleSheet, useWindowDimensions } from 'react-native';
  3 | import { useNavigation, useRoute } from '@react-navigation/native';
  4 | import RenderHtml, { defaultSystemFonts } from 'react-native-render-html';
  5 | import { styles } from './EventDetailsStyles';
  6 | import { colors } from '../../../theme/colors';
  7 | 
  8 | const EventDetails = () => {
  9 |   const navigation = useNavigation();
 10 |   const route = useRoute();
 11 |   const event = route.params?.event;
 12 |   const { width } = useWindowDimensions();
 13 | 
 14 |   const formatTime = (timeStr: string) => {
 15 |     const [hours, minutes] = timeStr.split(':');
 16 |     const date = new Date();
 17 |     date.setHours(parseInt(hours, 10));
 18 |     date.setMinutes(parseInt(minutes, 10));
 19 |     return date.toLocaleTimeString('en-US', {
 20 |       hour: 'numeric',
 21 |       minute: '2-digit',
 22 |       hour12: true
 23 |     });
 24 |   };
 25 | 
 26 |   const formatDate = (dateString: string) => {
 27 |     const [year, month, day] = dateString.split('-').map(num => parseInt(num, 10));
 28 |     const date = new Date(year, month - 1, day);
 29 |     return date.toLocaleDateString('en-US', {
 30 |       weekday: 'long',
 31 |       year: 'numeric',
 32 |       month: 'long',
 33 |       day: 'numeric'
 34 |     });
 35 |   };
 36 | 
 37 |   // Define default rendering options
 38 |   const renderersProps = {
 39 |     img: {
 40 |       enableExperimentalPercentWidth: true
 41 |     }
 42 |   };
 43 | 
 44 |   const tagsStyles = {
 45 |     body: {
 46 |       color: colors.black,
 47 |       fontSize: 16,
 48 |       lineHeight: 24,
 49 |     },
 50 |     a: {
 51 |       color: colors.primary,
 52 |       textDecorationLine: 'underline',
 53 |     }
 54 |   };
 55 | 
 56 |   return (
 57 |     <View style={styles.container}>
 58 |       <ScrollView style={styles.content}>
 59 |         <Text style={styles.title}>{event.event_title}</Text>
 60 |         <Text style={styles.date}>{formatDate(event.event_date)}</Text>
 61 |         <Text style={styles.time}>
 62 |           {formatTime(event.event_from_time)} - {formatTime(event.event_to_time)}
 63 |         </Text>
 64 |         
 65 |         <View style={styles.section}>
 66 |           <Text style={styles.sectionTitle}>Location</Text>
 67 |           <Text style={styles.location}>
 68 |             {event.event_street_address}
 69 |             {event.event_apt_suite ? `\n${event.event_apt_suite}` : ''}
 70 |             {'\n'}
 71 |             {[
 72 |               event.event_city,
 73 |               event.event_state,
 74 |               event.event_zip
 75 |             ].filter(Boolean).join(', ')}
 76 |           </Text>
 77 |         </View>
 78 | 
 79 |         {event.event_content && (
 80 |           <View style={styles.section}>
 81 |             <Text style={styles.sectionTitle}>Description</Text>
 82 |             <RenderHtml
 83 |               contentWidth={width - 40}
 84 |               source={{ html: event.event_content }}
 85 |               renderersProps={renderersProps}
 86 |               tagsStyles={tagsStyles}
 87 |               systemFonts={defaultSystemFonts}
 88 |               baseStyle={styles.description}
 89 |               defaultTextProps={{
 90 |                 selectable: true
 91 |               }}
 92 |             />
 93 |           </View>
 94 |         )}
 95 | 
 96 |         {event.event_price && (
 97 |           <View style={styles.section}>
 98 |             <Text style={styles.sectionTitle}>Price</Text>
 99 |             <Text style={styles.price}>${event.event_price}</Text>
100 |           </View>
101 |         )}
102 |       </ScrollView>
103 |     </View>
104 |   );
105 | };
106 | 
107 | export default EventDetails;
108 | 
```

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

```typescript
  1 | import React, { useState, useRef } from 'react';
  2 | import {
  3 |   View,
  4 |   Text,
  5 |   TextInput,
  6 |   TouchableOpacity,
  7 |   Alert,
  8 |   KeyboardAvoidingView,
  9 |   Platform,
 10 | } from 'react-native';
 11 | import axios from 'axios';
 12 | import { styles } from './Styles';
 13 | import AsyncStorage from '@react-native-async-storage/async-storage';
 14 | import { API } from '../../../config/apiConfig';
 15 | 
 16 | const VerifyEmailScreen = ({ route, navigation }: any) => {
 17 |   const { registerData, otp } = route.params;
 18 |   const [otpValue, setOtpValue] = useState('');
 19 |   const inputRefs = useRef<Array<TextInput | null>>([]);
 20 | 
 21 |   const handleOtpChange = (value: string, index: number) => {
 22 |     const newOtp = otpValue.split('');
 23 |     newOtp[index] = value;
 24 |     const newOtpString = newOtp.join('');
 25 |     setOtpValue(newOtpString);
 26 | 
 27 |     // Move to next input if value is entered
 28 |     if (value && index < 3) {
 29 |       inputRefs.current[index + 1]?.focus();
 30 |     }
 31 |   };
 32 | 
 33 |   const handleSubmit = async () => {
 34 |     if (!otpValue || otpValue.length !== 4) {
 35 |       Alert.alert('Error', 'Please enter the complete OTP');
 36 |       return;
 37 |     }
 38 | 
 39 |     if (parseInt(otpValue) !== parseInt(otp)) {
 40 |       Alert.alert('Error', 'OTP does not match. Please try again.');
 41 |       return;
 42 |     }
 43 | 
 44 |     try {
 45 |       const response = await axios.post(
 46 |         `${API.BASE_URL}${API.ENDPOINTS.MOBILEAPI}/v1/register`,
 47 |         {
 48 |           ...registerData,
 49 |           user_otp: otpValue,
 50 |           sent_opt: otp,
 51 |           signup_step1_email_otp: 'done',
 52 |         }
 53 |       );
 54 | 
 55 |       if (response.data.loginInfo) {
 56 |         // Store login info in AsyncStorage
 57 |         await AsyncStorage.setItem('userToken', response.data.loginInfo.token);
 58 |         await AsyncStorage.setItem('userData', JSON.stringify(response.data.loginInfo));
 59 | 
 60 |         // Navigate to DrawerNavigator
 61 |         navigation.reset({
 62 |           index: 0,
 63 |           routes: [{ name: 'DrawerNavigator' }],
 64 |         });
 65 |       }
 66 |     } catch (error: any) {
 67 |       Alert.alert(
 68 |         'Error',
 69 |         error.response?.data?.msg || 'Unable to verify OTP. Please try again later.'
 70 |       );
 71 |     }
 72 |   };
 73 | 
 74 |   return (
 75 |     <KeyboardAvoidingView
 76 |       style={styles.container}
 77 |       behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
 78 |     >
 79 |       <View style={styles.header}>
 80 |         <Text style={styles.title}>Verify Email</Text>
 81 |         <Text style={styles.subtitle}>
 82 |           Please enter the verification code sent to your email
 83 |         </Text>
 84 |       </View>
 85 | 
 86 |       <View style={styles.otpContainer}>
 87 |         {[0, 1, 2, 3].map((index) => (
 88 |           <TextInput
 89 |             key={index}
 90 |             ref={(ref) => (inputRefs.current[index] = ref)}
 91 |             style={styles.otpInput}
 92 |             maxLength={1}
 93 |             keyboardType="number-pad"
 94 |             onChangeText={(value) => handleOtpChange(value, index)}
 95 |             value={otpValue[index] || ''}
 96 |           />
 97 |         ))}
 98 |       </View>
 99 | 
100 |       <TouchableOpacity style={styles.button} onPress={handleSubmit}>
101 |         <Text style={styles.buttonText}>Verify</Text>
102 |       </TouchableOpacity>
103 | 
104 |       <TouchableOpacity
105 |         style={styles.backButton}
106 |         onPress={() => navigation.goBack()}
107 |       >
108 |         <Text style={styles.backButtonText}>Go Back</Text>
109 |       </TouchableOpacity>
110 |     </KeyboardAvoidingView>
111 |   );
112 | };
113 | 
114 | export default VerifyEmailScreen; 
```

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

```typescript
  1 | /**
  2 |  * Main theme configuration file
  3 |  * 
  4 |  * This file exports the complete theme object that combines all theme elements:
  5 |  * colors, typography, spacing, etc.
  6 |  */
  7 | 
  8 | import { colors } from './colors';
  9 | import { typography, typeScale } from './typography';
 10 | import { ViewStyle } from 'react-native';
 11 | 
 12 | // Spacing system in pixels
 13 | const spacing = {
 14 |   none: 0,
 15 |   xs: 4,
 16 |   sm: 8,
 17 |   md: 16,
 18 |   lg: 24,
 19 |   xl: 32,
 20 |   xxl: 48,
 21 |   xxxl: 64,
 22 | } as const;
 23 | 
 24 | // Border radius values
 25 | const borderRadius = {
 26 |   none: 0,
 27 |   xs: 2,
 28 |   sm: 4,
 29 |   md: 8,
 30 |   lg: 12,
 31 |   xl: 16,
 32 |   round: 9999, // For circular elements
 33 | } as const;
 34 | 
 35 | // Shadow styles
 36 | interface ShadowStyle {
 37 |   shadowColor: string;
 38 |   shadowOffset: { width: number; height: number };
 39 |   shadowOpacity: number;
 40 |   shadowRadius: number;
 41 |   elevation: number;
 42 | }
 43 | 
 44 | const shadows: Record<string, ShadowStyle> = {
 45 |   none: {
 46 |     shadowColor: 'transparent',
 47 |     shadowOffset: { width: 0, height: 0 },
 48 |     shadowOpacity: 0,
 49 |     shadowRadius: 0,
 50 |     elevation: 0,
 51 |   },
 52 |   xs: {
 53 |     shadowColor: colors.black,
 54 |     shadowOffset: { width: 0, height: 1 },
 55 |     shadowOpacity: 0.1,
 56 |     shadowRadius: 2,
 57 |     elevation: 1,
 58 |   },
 59 |   sm: {
 60 |     shadowColor: colors.black,
 61 |     shadowOffset: { width: 0, height: 2 },
 62 |     shadowOpacity: 0.1,
 63 |     shadowRadius: 4,
 64 |     elevation: 2,
 65 |   },
 66 |   md: {
 67 |     shadowColor: colors.black,
 68 |     shadowOffset: { width: 0, height: 3 },
 69 |     shadowOpacity: 0.2,
 70 |     shadowRadius: 6,
 71 |     elevation: 3,
 72 |   },
 73 |   lg: {
 74 |     shadowColor: colors.black,
 75 |     shadowOffset: { width: 0, height: 4 },
 76 |     shadowOpacity: 0.2,
 77 |     shadowRadius: 8,
 78 |     elevation: 4,
 79 |   },
 80 |   xl: {
 81 |     shadowColor: colors.black,
 82 |     shadowOffset: { width: 0, height: 6 },
 83 |     shadowOpacity: 0.3,
 84 |     shadowRadius: 12,
 85 |     elevation: 6,
 86 |   },
 87 | };
 88 | 
 89 | // Z-index values for stacking elements
 90 | const zIndex = {
 91 |   background: -1,
 92 |   default: 0,
 93 |   headerContent: 5,
 94 |   header: 10,
 95 |   modal: 20,
 96 |   toast: 30,
 97 |   tooltip: 40,
 98 |   overlay: 50,
 99 | } as const;
100 | 
101 | // Opacity values
102 | const opacity = {
103 |   none: 0,
104 |   light: 0.2,
105 |   medium: 0.5,
106 |   high: 0.8,
107 |   full: 1,
108 | } as const;
109 | 
110 | // Layout constants
111 | const layout = {
112 |   screenPadding: spacing.md,
113 |   headerHeight: 56,
114 |   tabBarHeight: 64,
115 |   maxContentWidth: 680, // Maximum width for content on large screens
116 | } as const;
117 | 
118 | // Animation timing constants
119 | const animation = {
120 |   durationShort: 150,
121 |   durationMedium: 300,
122 |   durationLong: 500,
123 |   easingDefault: 'ease',
124 |   easingAccelerate: 'ease-in',
125 |   easingDecelerate: 'ease-out',
126 | } as const;
127 | 
128 | // Screen size breakpoints
129 | const breakpoints = {
130 |   xs: 0,     // Extra small devices
131 |   sm: 375,   // Small devices (phones)
132 |   md: 768,   // Medium devices (tablets)
133 |   lg: 1024,  // Large devices (laptops/desktops)
134 |   xl: 1280,  // Extra large devices (large desktops)
135 | } as const;
136 | 
137 | // Export the complete theme object
138 | const theme = {
139 |   colors,
140 |   typography,
141 |   typeScale,
142 |   spacing,
143 |   borderRadius,
144 |   shadows,
145 |   zIndex,
146 |   opacity,
147 |   layout,
148 |   animation,
149 |   breakpoints,
150 | } as const;
151 | 
152 | export type Theme = typeof theme;
153 | export type SpacingKey = keyof typeof spacing;
154 | export type BorderRadiusKey = keyof typeof borderRadius;
155 | export type ShadowKey = keyof typeof shadows;
156 | export type ZIndexKey = keyof typeof zIndex;
157 | export type OpacityKey = keyof typeof opacity;
158 | export type BreakpointKey = keyof typeof breakpoints;
159 | 
160 | export default theme;
161 | 
```

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

```typescript
  1 | import React, { useState, useEffect } from 'react';
  2 | import { View, Text, TouchableOpacity, ScrollView, ActivityIndicator, RefreshControl } from 'react-native';
  3 | import { styles } from './Styles';
  4 | import { storageService } from '../../../helper/storageService';
  5 | import { apiService } from '../../../helper/apiService';
  6 | import { colors } from '../../../theme/colors';
  7 | 
  8 | interface Post {
  9 |   post_id: string;
 10 |   post_title: string;
 11 |   post_content: string;
 12 |   post_date: string;
 13 |   featured_image?: string;
 14 | }
 15 | 
 16 | interface Category {
 17 |   category_id: string;
 18 |   category_name: string;
 19 |   posts: Post[];
 20 | }
 21 | 
 22 | interface ApiResponse {
 23 |   status: string;
 24 |   categories: Category[];
 25 | }
 26 | 
 27 | const PostsScreen = ({ navigation }: any) => {
 28 |   const [groupedPosts, setGroupedPosts] = useState<Category[]>([]);
 29 |   const [loading, setLoading] = useState(true);
 30 |   const [refreshing, setRefreshing] = useState(false);
 31 | 
 32 |   const loadPosts = async (fromRefresh = false) => {
 33 |     try {
 34 |       // Try to get posts from storage first
 35 |       let posts = await storageService.get('posts');
 36 |       
 37 |       // If no posts in storage or this is a refresh, fetch from API
 38 |       if (!posts || fromRefresh) {
 39 |         const response = await apiService.fetchAndStorePosts();
 40 |         if (response) {
 41 |           posts = response;
 42 |         }
 43 |       }
 44 | 
 45 |       if (posts && Array.isArray(posts)) {
 46 |         setGroupedPosts(posts);
 47 |       } else {
 48 |         console.log('No posts found or invalid format');
 49 |         setGroupedPosts([]);
 50 |       }
 51 |     } catch (error) {
 52 |       console.error('Error getting posts:', error);
 53 |       setGroupedPosts([]);
 54 |     } finally {
 55 |       setLoading(false);
 56 |       setRefreshing(false);
 57 |     }
 58 |   };
 59 | 
 60 |   useEffect(() => {
 61 |     loadPosts();
 62 |   }, []);
 63 | 
 64 |   const onRefresh = () => {
 65 |     setRefreshing(true);
 66 |     loadPosts(true);
 67 |   };
 68 | 
 69 |   const handlePostPress = (post: Post) => {
 70 |     navigation.navigate('Post', { 
 71 |       id: post.post_id,
 72 |       title: post.post_title 
 73 |     });
 74 |   };
 75 | 
 76 |   if (loading) {
 77 |     return (
 78 |       <View style={styles.loadingContainer}>
 79 |         <ActivityIndicator size="large" color={colors.primary} />
 80 |       </View>
 81 |     );
 82 |   }
 83 | 
 84 |   return (
 85 |     <ScrollView 
 86 |       style={styles.container}
 87 |       refreshControl={
 88 |         <RefreshControl
 89 |           refreshing={refreshing}
 90 |           onRefresh={onRefresh}
 91 |           colors={[colors.dark]}
 92 |         />
 93 |       }
 94 |     >
 95 | 
 96 |       {groupedPosts.length > 0 ? (
 97 |         <View style={styles.postsContainer}>
 98 |           {groupedPosts.map((category) => (
 99 |             <View key={category.category_id} style={styles.categorySection}>
100 |               <Text style={styles.categoryTitle}>{category.category_name}</Text>
101 |               {category.posts.map((post) => (
102 |                 <TouchableOpacity
103 |                   key={post.post_id}
104 |                   style={styles.postCard}
105 |                   onPress={() => handlePostPress(post)}
106 |                 >
107 |                   <Text style={styles.postTitle}>{post.post_title}</Text>
108 |                   <Text style={styles.postDate}>
109 |                     {new Date(post.post_date).toLocaleDateString()}
110 |                   </Text>
111 |                 </TouchableOpacity>
112 |               ))}
113 |             </View>
114 |           ))}
115 |         </View>
116 |       ) : (
117 |         <View style={styles.emptyContainer}>
118 |           <Text style={styles.emptyText}>No posts available</Text>
119 |         </View>
120 |       )}
121 |     </ScrollView>
122 |   );
123 | };
124 | 
125 | export default PostsScreen;
126 | 
```

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

```typescript
  1 | import React from 'react';
  2 | import { View } from 'react-native';
  3 | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
  4 | import Icon from 'react-native-vector-icons/Ionicons';
  5 | import { DrawerActions, useNavigation, useRoute, NavigationProp, ParamListBase } from '@react-navigation/native';
  6 | import { colors } from '../theme/colors';
  7 | 
  8 | type TabParamList = {
  9 |   Home: undefined;
 10 |   ContactTab: undefined;
 11 |   ProfileTab: undefined;
 12 |   CalendarTab: undefined;
 13 |   Menu: undefined;
 14 | };
 15 | 
 16 | const Tab = createBottomTabNavigator<TabParamList>();
 17 | 
 18 | const TabNavigator = () => {
 19 |   const navigation = useNavigation<NavigationProp<TabParamList>>();
 20 |   const route = useRoute();
 21 | 
 22 |   return (
 23 |     <Tab.Navigator
 24 |       screenOptions={{
 25 |         headerShown: false,
 26 |         tabBarShowLabel: false,
 27 |         tabBarStyle: {
 28 |           backgroundColor: colors.footerBg,
 29 |           borderTopWidth: 1,
 30 |           borderTopColor: colors.light,
 31 |         },
 32 |         tabBarActiveTintColor: colors.secondary,
 33 |         tabBarInactiveTintColor: colors.footerBg,
 34 |       }}
 35 |     >
 36 |       <Tab.Screen
 37 |         name="ProfileTab"
 38 |         component={View}
 39 |         listeners={{
 40 |           tabPress: (e) => {
 41 |             e.preventDefault();
 42 |             navigation.navigate('MyProfile');
 43 |           },
 44 |         }}
 45 |         options={{
 46 |           tabBarIcon: ({ focused, color }) => (
 47 |             <Icon
 48 |               name={focused ? 'person-outline' : 'person-outline'}
 49 |               size={24}
 50 |               color={route.name === 'MyProfile' ? colors.secondary : colors.footerFont}
 51 |             />
 52 |           ),
 53 |         }}
 54 |       />
 55 |       <Tab.Screen
 56 |         name="ContactTab"
 57 |         component={View}
 58 |         listeners={{
 59 |           tabPress: (e) => {
 60 |             e.preventDefault();
 61 |             navigation.navigate('Contact');
 62 |           },
 63 |         }}
 64 |         options={{
 65 |           tabBarIcon: ({ focused, color }) => (
 66 |             <Icon
 67 |               name={focused ? 'mail' : 'mail-outline'}
 68 |               size={24}
 69 |               color={route.name === 'Contact' ? colors.secondary : colors.footerFont}
 70 |             />
 71 |           ),
 72 |         }}
 73 |       />
 74 |       <Tab.Screen
 75 |         name="HomeTab"
 76 |         component={View}
 77 |         listeners={{
 78 |           tabPress: (e) => {
 79 |             e.preventDefault();
 80 |             navigation.navigate('Home');
 81 |           },
 82 |         }}
 83 |         options={{
 84 |           tabBarIcon: ({ focused, color }) => (
 85 |             <Icon
 86 |               name={focused ? 'home' : 'home-outline'}
 87 |               size={24}
 88 |               color={route.name === 'Home' ? colors.secondary : colors.footerFont}
 89 |             />
 90 |           ),
 91 |         }}
 92 |       />
 93 |       <Tab.Screen
 94 |         name="CalendarTab"
 95 |         component={View}
 96 |         listeners={{
 97 |           tabPress: (e) => {
 98 |             e.preventDefault();
 99 |             navigation.navigate('Calendar');
100 |           },
101 |         }}
102 |         options={{
103 |           tabBarIcon: ({ focused, color }) => (
104 |             <Icon
105 |               name={focused ? 'calendar' : 'calendar-outline'}
106 |               size={24}
107 |               color={route.name === 'Calendar' ? colors.secondary : colors.footerFont}
108 |             />
109 |           ),
110 |         }}
111 |       />
112 |       <Tab.Screen
113 |         name="Menu"
114 |         component={View}
115 |         listeners={{
116 |           tabPress: (e) => {
117 |             e.preventDefault();
118 |             navigation.dispatch(DrawerActions.openDrawer());
119 |           },
120 |         }}
121 |         options={{
122 |           tabBarIcon: ({ focused, color }) => (
123 |             <Icon
124 |               name={focused ? 'menu' : 'menu-outline'}
125 |               size={24}
126 |               color={colors.footerFont}
127 |             />
128 |           ),
129 |         }}
130 |       />
131 |     </Tab.Navigator>
132 |   );
133 | };
134 | 
135 | export default TabNavigator;
136 | 
```

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

```typescript
  1 | import React, { Component, ErrorInfo, ReactNode } from 'react';
  2 | import {
  3 |   SafeAreaView,
  4 |   ScrollView,
  5 |   StyleSheet,
  6 |   Text,
  7 |   TouchableOpacity,
  8 |   View,
  9 | } from 'react-native';
 10 | 
 11 | interface Props {
 12 |   children: ReactNode;
 13 |   fallback?: ReactNode;
 14 | }
 15 | 
 16 | interface State {
 17 |   hasError: boolean;
 18 |   error: Error | null;
 19 |   errorInfo: ErrorInfo | null;
 20 | }
 21 | 
 22 | /**
 23 |  * ErrorBoundary component to catch JavaScript errors anywhere in the child component tree.
 24 |  * It logs the errors and displays a fallback UI instead of crashing the whole app.
 25 |  */
 26 | class ErrorBoundary extends Component<Props, State> {
 27 |   constructor(props: Props) {
 28 |     super(props);
 29 |     this.state = {
 30 |       hasError: false,
 31 |       error: null,
 32 |       errorInfo: null,
 33 |     };
 34 |   }
 35 | 
 36 |   static getDerivedStateFromError(error: Error): State {
 37 |     // Update state so the next render will show the fallback UI
 38 |     return {
 39 |       hasError: true,
 40 |       error,
 41 |       errorInfo: null,
 42 |     };
 43 |   }
 44 | 
 45 |   componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
 46 |     // Log the error to the console
 47 |     console.error('ErrorBoundary caught an error:', error, errorInfo);
 48 |     this.setState({
 49 |       errorInfo,
 50 |     });
 51 |     
 52 |     // You can also log the error to an error reporting service here
 53 |     // logErrorToService(error, errorInfo);
 54 |   }
 55 | 
 56 |   resetError = (): void => {
 57 |     this.setState({
 58 |       hasError: false,
 59 |       error: null,
 60 |       errorInfo: null,
 61 |     });
 62 |   };
 63 | 
 64 |   render(): ReactNode {
 65 |     if (this.state.hasError) {
 66 |       // Custom fallback UI
 67 |       if (this.props.fallback) {
 68 |         return this.props.fallback;
 69 |       }
 70 | 
 71 |       // Default fallback UI
 72 |       return (
 73 |         <SafeAreaView style={styles.container}>
 74 |           <ScrollView contentContainerStyle={styles.scrollContainer}>
 75 |             <View style={styles.errorContainer}>
 76 |               <Text style={styles.errorTitle}>Something went wrong</Text>
 77 |               
 78 |               <View style={styles.errorMessageContainer}>
 79 |                 <Text style={styles.errorMessage}>
 80 |                   {this.state.error?.toString() || 'An unknown error occurred'}
 81 |                 </Text>
 82 |               </View>
 83 |               
 84 |               {this.state.errorInfo && (
 85 |                 <View style={styles.componentStackContainer}>
 86 |                   <Text style={styles.componentStackTitle}>Component Stack:</Text>
 87 |                   <Text style={styles.componentStack}>
 88 |                     {this.state.errorInfo.componentStack}
 89 |                   </Text>
 90 |                 </View>
 91 |               )}
 92 |               
 93 |               <TouchableOpacity
 94 |                 style={styles.resetButton}
 95 |                 onPress={this.resetError}
 96 |               >
 97 |                 <Text style={styles.resetButtonText}>Try Again</Text>
 98 |               </TouchableOpacity>
 99 |             </View>
100 |           </ScrollView>
101 |         </SafeAreaView>
102 |       );
103 |     }
104 | 
105 |     return this.props.children;
106 |   }
107 | }
108 | 
109 | const styles = StyleSheet.create({
110 |   container: {
111 |     flex: 1,
112 |     backgroundColor: '#f8f9fa',
113 |   },
114 |   scrollContainer: {
115 |     flexGrow: 1,
116 |     padding: 20,
117 |   },
118 |   errorContainer: {
119 |     flex: 1,
120 |     justifyContent: 'center',
121 |     alignItems: 'center',
122 |   },
123 |   errorTitle: {
124 |     fontSize: 24,
125 |     fontWeight: 'bold',
126 |     color: '#dc3545',
127 |     marginBottom: 20,
128 |     textAlign: 'center',
129 |   },
130 |   errorMessageContainer: {
131 |     backgroundColor: '#fff',
132 |     borderRadius: 8,
133 |     padding: 15,
134 |     width: '100%',
135 |     marginBottom: 20,
136 |     borderWidth: 1,
137 |     borderColor: '#dee2e6',
138 |   },
139 |   errorMessage: {
140 |     fontSize: 16,
141 |     color: '#343a40',
142 |     lineHeight: 22,
143 |   },
144 |   componentStackContainer: {
145 |     backgroundColor: '#f1f3f5',
146 |     borderRadius: 8,
147 |     padding: 15,
148 |     width: '100%',
149 |     marginBottom: 20,
150 |     borderWidth: 1,
151 |     borderColor: '#dee2e6',
152 |   },
153 |   componentStackTitle: {
154 |     fontSize: 16,
155 |     fontWeight: 'bold',
156 |     color: '#495057',
157 |     marginBottom: 10,
158 |   },
159 |   componentStack: {
160 |     fontSize: 14,
161 |     color: '#6c757d',
162 |     fontFamily: 'Courier',
163 |   },
164 |   resetButton: {
165 |     backgroundColor: '#007bff',
166 |     paddingVertical: 12,
167 |     paddingHorizontal: 24,
168 |     borderRadius: 8,
169 |     marginTop: 10,
170 |   },
171 |   resetButtonText: {
172 |     color: '#fff',
173 |     fontSize: 16,
174 |     fontWeight: 'bold',
175 |   },
176 | });
177 | 
178 | export default ErrorBoundary;
179 | 
```

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

```typescript
  1 | import React, { useState, useEffect } from 'react';
  2 | import { View, Text, TextInput, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native';
  3 | import { styles } from './Styles';
  4 | import axiosRequest from '../../../helper/axiosRequest';
  5 | import { API } from '../../../helper/config';
  6 | import HTML from 'react-native-render-html';
  7 | import { useWindowDimensions } from 'react-native';
  8 | 
  9 | const defaultSystemFonts = [
 10 |   'Arial',
 11 |   'Helvetica',
 12 |   'Helvetica Neue',
 13 |   'System',
 14 |   '-apple-system',
 15 |   'sans-serif',
 16 | ];
 17 | 
 18 | const renderersProps = {
 19 |   img: {
 20 |     enableExperimentalPercentWidth: true,
 21 |   },
 22 | };
 23 | 
 24 | const BluestoneAppsAIScreen = ({ navigation }: any) => {
 25 |   const [showWelcomeMessage, setShowWelcomeMessage] = useState(true);
 26 |   const [question, setQuestion] = useState('');
 27 |   const [replyContent, setReplyContent] = useState('');
 28 |   const [aiWelcomeMessage, setAiWelcomeMessage] = useState('');
 29 |   const [isLoading, setIsLoading] = useState(false);
 30 |   const { width } = useWindowDimensions();
 31 | 
 32 |   useEffect(() => {
 33 |     getAIWelcome();
 34 |   }, []);
 35 | 
 36 |   const getAIWelcome = async () => {
 37 |     try {
 38 |       console.log('Fetching AI welcome message...');
 39 |       const response = await axiosRequest.get(
 40 |         `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.GET_AI_WELCOME}`
 41 |       );
 42 |       
 43 |       console.log('AI Welcome Response:', response?.data);
 44 |       if (response?.data?.status === "success") {
 45 |         console.log('Setting welcome message:', response.data.message);
 46 |         setAiWelcomeMessage(response.data.message);
 47 |       } else {
 48 |         console.log('No success status in response');
 49 |         setAiWelcomeMessage('Welcome to Bluestone AI! How can I help you today?');
 50 |       }
 51 |     } catch (error) {
 52 |       console.error('Error getting AI welcome message:', error);
 53 |       setAiWelcomeMessage('Welcome to Bluestone AI! How can I help you today?');
 54 |     }
 55 |   };
 56 | 
 57 |   const submitQuestion = async () => {
 58 |     if (!question.trim()) {
 59 |       return;
 60 |     }
 61 | 
 62 |     setIsLoading(true);
 63 |     try {
 64 |       console.log('Submitting question to ask_bluestoneai endpoint...');
 65 |       const response = await axiosRequest.post(
 66 |         `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.ASK_BLUESTONEAI}`,
 67 |         { question: question.trim() }
 68 |       );
 69 | 
 70 |       console.log('Question response:', response?.data);
 71 | 
 72 |       if (response?.data?.reply) {
 73 |         setReplyContent(response.data.reply);
 74 |         setShowWelcomeMessage(false);
 75 |         setQuestion('');
 76 |       } else {
 77 |         console.error('No reply in response');
 78 |       }
 79 |     } catch (error) {
 80 |       console.error('Error submitting question:', error);
 81 |     } finally {
 82 |       setIsLoading(false);
 83 |     }
 84 |   };
 85 | 
 86 |   const renderHtmlContent = (content: string) => {
 87 |     if (!content) return null;
 88 | 
 89 |     return (
 90 |       <HTML 
 91 |         source={{ html: content }} 
 92 |         contentWidth={width - 64}
 93 |         systemFonts={defaultSystemFonts}
 94 |         renderersProps={renderersProps}
 95 |         baseStyle={styles.htmlContent}
 96 |         tagsStyles={{
 97 |           p: styles.paragraph,
 98 |           h1: styles.heading1,
 99 |           h2: styles.heading2,
100 |           body: { color: '#333' },
101 |         }}
102 |         enableExperimentalBRCollapsing
103 |         enableExperimentalGhostLinesPrevention
104 |       />
105 |     );
106 |   };
107 | 
108 |   return (
109 |     <ScrollView style={styles.container}>
110 |       <View style={styles.content}>
111 |         {showWelcomeMessage ? (
112 |           <View style={styles.messageContainer}>
113 |             {aiWelcomeMessage ? (
114 |               renderHtmlContent(aiWelcomeMessage)
115 |             ) : (
116 |               <Text style={styles.loadingText}>Loading welcome message...</Text>
117 |             )}
118 |           </View>
119 |         ) : null}
120 | 
121 |         {replyContent ? (
122 |           <View style={styles.messageContainer}>
123 |             {renderHtmlContent(replyContent)}
124 |           </View>
125 |         ) : null}
126 | 
127 |         <View style={styles.inputContainer}>
128 |           <TextInput
129 |             style={styles.input}
130 |             value={question}
131 |             onChangeText={setQuestion}
132 |             placeholder="Ask a question"
133 |             multiline
134 |           />
135 |           <TouchableOpacity 
136 |             style={styles.submitButton}
137 |             onPress={submitQuestion}
138 |             disabled={isLoading}
139 |           >
140 |             {isLoading ? (
141 |               <ActivityIndicator color="#fff" />
142 |             ) : (
143 |               <Text style={styles.submitButtonText}>Submit</Text>
144 |             )}
145 |           </TouchableOpacity>
146 |         </View>
147 |       </View>
148 |     </ScrollView>
149 |   );
150 | };
151 | 
152 | export default BluestoneAppsAIScreen;
153 | 
```

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

```typescript
  1 | import React, { useState, useCallback } from 'react';
  2 | import { View, Text, Image, TouchableOpacity, ScrollView, ActivityIndicator } from 'react-native';
  3 | import AsyncStorage from '@react-native-async-storage/async-storage';
  4 | import { useFocusEffect } from '@react-navigation/native';
  5 | import Icon from 'react-native-vector-icons/Ionicons';
  6 | import { styles } from './Styles';
  7 | 
  8 | interface UserProfile {
  9 |   loginInfo: {
 10 |     first_name: string;
 11 |     last_name: string;
 12 |     email: string;
 13 |     phone: string;
 14 |     user_avatar?: string;
 15 |     display_name: string;
 16 |     city_state?: string;
 17 |   };
 18 | }
 19 | 
 20 | const MyProfileScreen = ({ navigation }: any) => {
 21 |   const [userInfo, setUserInfo] = useState<UserProfile | null>(null);
 22 |   const [isLoading, setIsLoading] = useState(true);
 23 | 
 24 |   const loadUserData = async () => {
 25 |     try {
 26 |       setIsLoading(true);
 27 |       console.log('Attempting to load user data...');
 28 |       
 29 |       const userDataString = await AsyncStorage.getItem('userData');
 30 |       console.log('Raw userData from AsyncStorage:', userDataString);
 31 |       
 32 |       if (!userDataString) {
 33 |         console.log('No userData found in AsyncStorage');
 34 |         setUserInfo(null);
 35 |         return;
 36 |       }
 37 | 
 38 |       const userData = JSON.parse(userDataString);
 39 |       console.log('Parsed userData:', userData);
 40 | 
 41 |       // Ensure the data has the expected structure
 42 |       if (!userData?.loginInfo) {
 43 |         console.error('Invalid user data structure:', userData);
 44 |         setUserInfo(null);
 45 |         return;
 46 |       }
 47 | 
 48 |       console.log('Setting valid user data:', userData);
 49 |       setUserInfo(userData);
 50 |     } catch (error) {
 51 |       console.error('Error loading user data:', error);
 52 |       setUserInfo(null);
 53 |     } finally {
 54 |       setIsLoading(false);
 55 |     }
 56 |   };
 57 | 
 58 |   useFocusEffect(
 59 |     useCallback(() => {
 60 |       loadUserData();
 61 |     }, [])
 62 |   );
 63 | 
 64 |   if (isLoading) {
 65 |     return (
 66 |       <View style={[styles.container, styles.centerContent]}>
 67 |         <ActivityIndicator size="large" color="#007AFF" />
 68 |       </View>
 69 |     );
 70 |   }
 71 | 
 72 |   if (!userInfo?.loginInfo) {
 73 |     return (
 74 |       <View style={[styles.container, styles.centerContent]}>
 75 |         <Text style={styles.errorText}>No user data available</Text>
 76 |       </View>
 77 |     );
 78 |   }
 79 | 
 80 |   const { loginInfo } = userInfo;
 81 | 
 82 |   return (
 83 |     <ScrollView style={styles.container}>
 84 |       <View style={styles.header}>
 85 |         <View style={styles.avatarContainer}>
 86 |           {loginInfo.user_avatar ? (
 87 |             <Image source={{ uri: loginInfo.user_avatar }} style={styles.profileImage} />
 88 |           ) : (
 89 |             <Image 
 90 |               source={require('../../../assets/images/default_profile_pic.png')} 
 91 |               style={styles.profileImage}
 92 |             />
 93 |           )}
 94 |         </View>
 95 |         <Text style={styles.name}>{loginInfo.display_name}</Text>
 96 |         {loginInfo.city_state && (
 97 |           <Text style={styles.location}>{loginInfo.city_state}</Text>
 98 |         )}
 99 |       </View>
100 | 
101 |       <View style={styles.infoSection}>
102 |         <View style={styles.infoItem}>
103 |           <Icon name="person-outline" size={24} color="#666" style={styles.icon} />
104 |           <View>
105 |             <Text style={styles.label}>Full Name</Text>
106 |             <Text style={styles.value}>
107 |               {`${loginInfo.first_name} ${loginInfo.last_name}`}
108 |             </Text>
109 |           </View>
110 |         </View>
111 | 
112 |         <View style={styles.infoItem}>
113 |           <Icon name="call-outline" size={24} color="#666" style={styles.icon} />
114 |           <View>
115 |             <Text style={styles.label}>Mobile Number</Text>
116 |             <Text style={styles.value}>{loginInfo.phone || 'Not provided'}</Text>
117 |           </View>
118 |         </View>
119 | 
120 |         <View style={styles.infoItem}>
121 |           <Icon name="mail-outline" size={24} color="#666" style={styles.icon} />
122 |           <View>
123 |             <Text style={styles.label}>Email</Text>
124 |             <Text style={styles.value}>{loginInfo.email}</Text>
125 |           </View>
126 |         </View>
127 |       </View>
128 | 
129 |       <View style={styles.buttonContainer}>
130 |         <TouchableOpacity
131 |           style={styles.button}
132 |           onPress={() => navigation.navigate('EditProfile')}
133 |         >
134 |           <Text style={styles.buttonText}>Edit Account</Text>
135 |         </TouchableOpacity>
136 | 
137 |         <TouchableOpacity
138 |           style={[styles.button, styles.secondaryButton]}
139 |           onPress={() => navigation.navigate('ChangePassword')}
140 |         >
141 |           <Text style={[styles.buttonText, styles.secondaryButtonText]}>Change Password</Text>
142 |         </TouchableOpacity>
143 |       </View>
144 |     </ScrollView>
145 |   );
146 | };
147 | 
148 | export default MyProfileScreen;
149 | 
```

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

```typescript
  1 | import React, { useState } from 'react';
  2 | import {
  3 |   View,
  4 |   Text,
  5 |   TextInput,
  6 |   TouchableOpacity,
  7 |   Alert,
  8 |   Image,
  9 | } from 'react-native';
 10 | import axios from 'axios';
 11 | import { styles } from './Styles';
 12 | import { environment } from '../../../config/environment';
 13 | 
 14 | const ForgotPasswordScreen = ({ navigation }: any) => {
 15 |   const [step, setStep] = useState(1);
 16 |   const [email, setEmail] = useState('');
 17 |   const [otp, setOtp] = useState('');
 18 |   const [password, setPassword] = useState('');
 19 |   const [confirmPassword, setConfirmPassword] = useState('');
 20 | 
 21 |   const handleSendEmail = async () => {
 22 |     try {
 23 |       const response = await axios.post(`${environment.apiURL}/custom/v1/forgotPassword`, {
 24 |         email: email
 25 |       });
 26 | 
 27 |       if (response.data.status === 'ok') {
 28 |         Alert.alert('Success', 'OTP sent to your email successfully!');
 29 |         setStep(2);
 30 |       } else {
 31 |         Alert.alert('Error', response.data.errormsg || 'Failed to send OTP');
 32 |       }
 33 |     } catch (error: any) {
 34 |       Alert.alert('Error', error.response?.data?.errormsg || 'An error occurred');
 35 |     }
 36 |   };
 37 | 
 38 |   const handleVerifyOTP = async () => {
 39 |     try {
 40 |       const response = await axios.post(`${environment.apiURL}/custom/v1/checkOtp`, {
 41 |         otp: otp,
 42 |         email: email
 43 |       });
 44 | 
 45 |       if (response.data.status === 'ok') {
 46 |         Alert.alert('Success', 'OTP verified successfully!');
 47 |         setStep(3);
 48 |       } else {
 49 |         Alert.alert('Error', response.data.errormsg || 'Invalid OTP');
 50 |       }
 51 |     } catch (error: any) {
 52 |       Alert.alert('Error', error.response?.data?.errormsg || 'An error occurred');
 53 |     }
 54 |   };
 55 | 
 56 |   const handleResetPassword = async () => {
 57 |     if (password !== confirmPassword) {
 58 |       Alert.alert('Error', 'Passwords do not match');
 59 |       return;
 60 |     }
 61 | 
 62 |     try {
 63 |       const response = await axios.post(`${environment.apiURL}/custom/v1/updatePassword`, {
 64 |         password: password,
 65 |         email: email
 66 |       });
 67 | 
 68 |       if (response.data.status === 'ok') {
 69 |         Alert.alert('Success', 'Password reset successfully!');
 70 |         navigation.navigate('Login');
 71 |       } else {
 72 |         Alert.alert('Error', response.data.errormsg || 'Failed to reset password');
 73 |       }
 74 |     } catch (error: any) {
 75 |       Alert.alert('Error', error.response?.data?.errormsg || 'An error occurred');
 76 |     }
 77 |   };
 78 | 
 79 |   return (
 80 |     <View style={styles.container}>
 81 |       <View style={styles.logoContainer}>
 82 |         <Image
 83 |           source={require('../../../assets/images/logo.png')}
 84 |           style={styles.logo}
 85 |         />
 86 |       </View>
 87 |       
 88 |       <Text style={styles.title}>Forgot Password</Text>
 89 | 
 90 |       {step === 1 && (
 91 |         <View>
 92 |           <TextInput
 93 |             style={styles.input}
 94 |             placeholder="Email"
 95 |             placeholderTextColor="#999"
 96 |             value={email}
 97 |             onChangeText={setEmail}
 98 |             keyboardType="email-address"
 99 |             autoCapitalize="none"
100 |           />
101 |           <TouchableOpacity style={styles.button} onPress={handleSendEmail}>
102 |             <Text style={styles.buttonText}>Send OTP</Text>
103 |           </TouchableOpacity>
104 |         </View>
105 |       )}
106 | 
107 |       {step === 2 && (
108 |         <View>
109 |           <TextInput
110 |             style={styles.input}
111 |             placeholder="Enter OTP"
112 |             placeholderTextColor="#999"
113 |             value={otp}
114 |             onChangeText={setOtp}
115 |             keyboardType="number-pad"
116 |           />
117 |           <TouchableOpacity style={styles.button} onPress={handleVerifyOTP}>
118 |             <Text style={styles.buttonText}>Verify OTP</Text>
119 |           </TouchableOpacity>
120 |         </View>
121 |       )}
122 | 
123 |       {step === 3 && (
124 |         <View>
125 |           <TextInput
126 |             style={styles.input}
127 |             placeholder="New Password"
128 |             placeholderTextColor="#999"
129 |             value={password}
130 |             onChangeText={setPassword}
131 |             secureTextEntry
132 |           />
133 |           <TextInput
134 |             style={styles.input}
135 |             placeholder="Confirm Password"
136 |             placeholderTextColor="#999"
137 |             value={confirmPassword}
138 |             onChangeText={setConfirmPassword}
139 |             secureTextEntry
140 |           />
141 |           <TouchableOpacity style={styles.button} onPress={handleResetPassword}>
142 |             <Text style={styles.buttonText}>Reset Password</Text>
143 |           </TouchableOpacity>
144 |         </View>
145 |       )}
146 | 
147 |       <TouchableOpacity
148 |         style={styles.backToLoginContainer}
149 |         onPress={() => navigation.navigate('Login')}
150 |       >
151 |         <Text style={styles.backToLoginText}>Back to Login</Text>
152 |       </TouchableOpacity>
153 |     </View>
154 |   );
155 | };
156 | 
157 | export default ForgotPasswordScreen;
158 | 
```

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

```typescript
  1 | import AsyncStorage from '@react-native-async-storage/async-storage';
  2 | import axiosRequest from '../helper/axiosRequest';
  3 | import { API } from '../helper/config';
  4 | 
  5 | const STORAGE_KEYS = {
  6 |   TERMS_DATE: 'accepted_terms_date',
  7 |   PRIVACY_DATE: 'accepted_privacy_date',
  8 |   INITIAL_CHECK_COMPLETED: 'terms_privacy_initial_check_completed'
  9 | };
 10 | 
 11 | const EXCLUDED_ROUTES = [
 12 |   'TermsAndConditions',
 13 |   'PrivacyPolicy',
 14 |   'Login',
 15 |   'SignUp',
 16 |   'ForgotPassword',
 17 |   'VerifyEmail'
 18 | ];
 19 | 
 20 | export class NavigationMonitorService {
 21 |   static isExcludedRoute(routeName: string): boolean {
 22 |     return EXCLUDED_ROUTES.includes(routeName);
 23 |   }
 24 | 
 25 |   /**
 26 |    * Check if terms and privacy policy need updates
 27 |    * Improved to handle API errors and prevent constant prompts
 28 |    */
 29 |   static async checkForUpdates() {
 30 |     try {
 31 |       // Check if we've already completed the initial check
 32 |       const initialCheckCompleted = await AsyncStorage.getItem(STORAGE_KEYS.INITIAL_CHECK_COMPLETED);
 33 |       
 34 |       // Get stored dates
 35 |       const [storedTermsDate, storedPrivacyDate] = await Promise.all([
 36 |         AsyncStorage.getItem(STORAGE_KEYS.TERMS_DATE),
 37 |         AsyncStorage.getItem(STORAGE_KEYS.PRIVACY_DATE)
 38 |       ]);
 39 |       
 40 |       // If this is the first time checking and no dates are stored, store current dates
 41 |       if (!initialCheckCompleted && (!storedTermsDate || !storedPrivacyDate)) {
 42 |         const currentDate = new Date().toISOString();
 43 |         
 44 |         // Store current date for both terms and privacy
 45 |         if (!storedTermsDate) {
 46 |           await AsyncStorage.setItem(STORAGE_KEYS.TERMS_DATE, currentDate);
 47 |         }
 48 |         
 49 |         if (!storedPrivacyDate) {
 50 |           await AsyncStorage.setItem(STORAGE_KEYS.PRIVACY_DATE, currentDate);
 51 |         }
 52 |         
 53 |         // Mark initial check as completed
 54 |         await AsyncStorage.setItem(STORAGE_KEYS.INITIAL_CHECK_COMPLETED, 'true');
 55 |         
 56 |         // Return false for both to prevent showing update prompt on first run
 57 |         return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
 58 |       }
 59 |       
 60 |       // Initialize with default values
 61 |       let termsDate = null;
 62 |       let privacyDate = null;
 63 |       let termsError = false;
 64 |       let privacyError = false;
 65 |       
 66 |       // Fetch terms date with error handling
 67 |       try {
 68 |         const termsResponse = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_TERMS_DATE}`);
 69 |         if (termsResponse && termsResponse.data && termsResponse.data.date) {
 70 |           termsDate = termsResponse.data.date;
 71 |         } else {
 72 |           termsError = true;
 73 |         }
 74 |       } catch (error) {
 75 |         termsError = true;
 76 |       }
 77 |       
 78 |       // Fetch privacy date with error handling
 79 |       try {
 80 |         const privacyResponse = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_PRIVACY_DATE}`);
 81 |         if (privacyResponse && privacyResponse.data && privacyResponse.data.date) {
 82 |           privacyDate = privacyResponse.data.date;
 83 |         } else {
 84 |           privacyError = true;
 85 |         }
 86 |       } catch (error) {
 87 |         privacyError = true;
 88 |       }
 89 |       
 90 |       // If both API calls failed, skip update check
 91 |       if (termsError && privacyError) {
 92 |         return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
 93 |       }
 94 |       
 95 |       // Compare dates to determine if updates are needed
 96 |       const termsNeedsUpdate = termsDate && storedTermsDate 
 97 |         ? new Date(termsDate) > new Date(storedTermsDate)
 98 |         : false;
 99 |         
100 |       const privacyNeedsUpdate = privacyDate && storedPrivacyDate
101 |         ? new Date(privacyDate) > new Date(storedPrivacyDate)
102 |         : false;
103 |       
104 |       return { termsNeedsUpdate, privacyNeedsUpdate };
105 |     } catch (error) {
106 |       // In case of any unexpected errors, return false to prevent blocking the user
107 |       return { termsNeedsUpdate: false, privacyNeedsUpdate: false };
108 |     }
109 |   }
110 | 
111 |   static async getTermsPublishedDate() {
112 |     try {
113 |       const response = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_TERMS_DATE}`);
114 |       return response.data.date;
115 |     } catch (error) {
116 |       console.error('Error getting terms date:', error);
117 |       return null; // Return null instead of current date as fallback
118 |     }
119 |   }
120 | 
121 |   static async getPrivacyPublishedDate() {
122 |     try {
123 |       const response = await axiosRequest.get(`${API.BASE_URL}/${API.ENDPOINTS.GET_PRIVACY_DATE}`);
124 |       return response.data.date;
125 |     } catch (error) {
126 |       console.error('Error getting privacy date:', error);
127 |       return null; // Return null instead of current date as fallback
128 |     }
129 |   }
130 | 
131 |   static async storeAcceptanceDate(type: 'terms' | 'privacy') {
132 |     const key = type === 'terms' ? STORAGE_KEYS.TERMS_DATE : STORAGE_KEYS.PRIVACY_DATE;
133 |     await AsyncStorage.setItem(key, new Date().toISOString());
134 |     console.log(`Stored ${type} acceptance date:`, new Date().toISOString());
135 |   }
136 | }
```

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

```typescript
  1 | import React, { useEffect, useState } from 'react';
  2 | import { View, Text } from 'react-native';
  3 | import axiosRequest from '../../../helper/axiosRequest';
  4 | import { API } from '../../../helper/config';
  5 | import { WebView } from 'react-native-webview';
  6 | import { LoadingSpinner } from '../../../components/LoadingSpinner';
  7 | import { styles } from './Styles';
  8 | 
  9 | const AboutUsScreen = () => {
 10 |   const [aboutUsContent, setAboutUsContent] = useState<string>('');
 11 |   const [isLoading, setIsLoading] = useState(false);
 12 | 
 13 |   useEffect(() => {
 14 |     getAboutUs();
 15 |   }, []);
 16 | 
 17 |   const cleanHtml = (html: string) => {
 18 |     // Extract content between <body> tags if present
 19 |     const bodyMatch = html.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
 20 |     let content = bodyMatch ? bodyMatch[1] : html;
 21 | 
 22 |     // Remove scripts, links, and styles
 23 |     content = content.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
 24 |     content = content.replace(/<link[^>]*>/gi, '');
 25 |     content = content.replace(/<style\b[^<]*(?:(?!<\/style>)<[^<]*)*<\/style>/gi, '');
 26 | 
 27 |     // Remove WordPress specific comments
 28 |     content = content.replace(/<!--[\s\S]*?-->/g, '');
 29 |     
 30 |     // Clean up image tags
 31 |     content = content.replace(/loading="lazy"\s/g, '');
 32 |     content = content.replace(/decoding="async"\s/g, '');
 33 |     content = content.replace(/\sonerror="[^"]*"/g, '');
 34 | 
 35 |     return content;
 36 |   };
 37 | 
 38 |   const getAboutUs = async () => {
 39 |     setIsLoading(true);
 40 |     try {
 41 |       const response = await axiosRequest.post(
 42 |         `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.GET_ABOUTUS}`,
 43 |         {},
 44 |         {
 45 |           headers: {
 46 |             'Accept': 'application/json',
 47 |             'Content-Type': 'application/json'
 48 |           }
 49 |         }
 50 |       );
 51 |       
 52 |       console.log('About Us API Response:', response);
 53 |       if (response?.data?.aboutus_content) {
 54 |         const cleanContent = cleanHtml(response.data.aboutus_content);
 55 |         const content = `
 56 |           <!DOCTYPE html>
 57 |           <html>
 58 |             <head>
 59 |               <meta charset="utf-8">
 60 |               <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
 61 |               <style>
 62 |                 * {
 63 |                   box-sizing: border-box;
 64 |                 }
 65 |                 body {
 66 |                   font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
 67 |                   padding: 16px;
 68 |                   margin: 0;
 69 |                   color: #333;
 70 |                   font-size: 16px;
 71 |                   line-height: 1.5;
 72 |                   background-color: #ffffff;
 73 |                 }
 74 |                 img {
 75 |                   max-width: 100%;
 76 |                   height: auto;
 77 |                   display: block;
 78 |                   margin: 16px auto;
 79 |                   border-radius: 8px;
 80 |                 }
 81 |                 h2, h3 {
 82 |                   color: #000;
 83 |                   margin: 24px 0 16px 0;
 84 |                   text-align: center;
 85 |                   font-weight: bold;
 86 |                 }
 87 |                 h2 {
 88 |                   font-size: 24px;
 89 |                 }
 90 |                 h3 {
 91 |                   font-size: 20px;
 92 |                 }
 93 |                 h4 {
 94 |                   font-size: 16px;
 95 |                   color: #666;
 96 |                   margin: 8px 0 24px 0;
 97 |                   text-align: center;
 98 |                   font-weight: normal;
 99 |                 }
100 |                 p {
101 |                   margin: 16px 0;
102 |                   color: #333;
103 |                 }
104 |                 .team-member {
105 |                   text-align: center;
106 |                   margin-bottom: 32px;
107 |                 }
108 |               </style>
109 |             </head>
110 |             <body>
111 |               <div class="content">
112 |                 ${cleanContent}
113 |               </div>
114 |             </body>
115 |           </html>
116 |         `;
117 |         console.log('Final HTML:', content);
118 |         setAboutUsContent(content);
119 |       }
120 |     } catch (error: any) {
121 |       console.error('Error getting about us content:', error);
122 |     } finally {
123 |       setIsLoading(false);
124 |     }
125 |   };
126 | 
127 |   if (isLoading) {
128 |     return <LoadingSpinner />;
129 |   }
130 | 
131 |   return (
132 |     <View style={styles.container}>
133 | 
134 |       <View style={styles.webViewContainer}>
135 |         {aboutUsContent ? (
136 |           <WebView
137 |             source={{ html: aboutUsContent }}
138 |             style={styles.webView}
139 |             originWhitelist={['*']}
140 |             onError={(syntheticEvent) => {
141 |               const { nativeEvent } = syntheticEvent;
142 |               console.warn('WebView error: ', nativeEvent);
143 |             }}
144 |             startInLoadingState={true}
145 |             renderLoading={() => <LoadingSpinner />}
146 |             showsVerticalScrollIndicator={true}
147 |             bounces={true}
148 |             automaticallyAdjustContentInsets={true}
149 |             injectedJavaScript={`
150 |               true; // Required by iOS
151 |             `}
152 |           />
153 |         ) : (
154 |           <Text style={styles.noContent}>No content available</Text>
155 |         )}
156 |       </View>
157 |     </View>
158 |   );
159 | };
160 | 
161 | export default AboutUsScreen;
162 | 
```

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

```typescript
  1 | import React, { useEffect, useState } from 'react';
  2 | import { View, Text, ScrollView, StyleSheet, TouchableOpacity, ActivityIndicator, Alert } from 'react-native';
  3 | import { SafeAreaView } from 'react-native-safe-area-context';
  4 | import { colors } from '../../../theme/colors';
  5 | import { API } from '../../../helper/config';
  6 | import { NavigationMonitorService } from '../../../helper/NavigationMonitorService';
  7 | import axiosRequest from '../../../helper/axiosRequest';
  8 | import HTML from 'react-native-render-html';
  9 | 
 10 | interface TermsResponse {
 11 |   status: number;
 12 |   terms_page: Array<{
 13 |     post_title: string;
 14 |     post_content: string;
 15 |   }>;
 16 | }
 17 | 
 18 | const TermsAndConditionsScreen = ({ navigation, route }: any) => {
 19 |   const [loading, setLoading] = useState(true);
 20 |   const [error, setError] = useState<string | null>(null);
 21 |   const [content, setContent] = useState<string>('');
 22 |   const [title, setTitle] = useState<string>('');
 23 |   const fromUpdate = route.params?.fromUpdate || false;
 24 |   useEffect(() => {
 25 |     fetchTermsContent();
 26 |   }, []);
 27 | 
 28 |   const fetchTermsContent = async () => {
 29 |     try {
 30 |       const response = await axiosRequest.get<TermsResponse>(`${API.BASE_URL}/${API.ENDPOINTS.GET_TERMS_PAGE}`);
 31 |       
 32 |       if (response.data?.terms_page?.[0]) {
 33 |         setTitle(response.data.terms_page[0].post_title);
 34 |         setContent(response.data.terms_page[0].post_content);
 35 |       } else {
 36 |         setError('No terms content found');
 37 |       }
 38 |     } catch (err) {
 39 |       setError('Failed to load terms content');
 40 |       console.error('Error fetching terms:', err);
 41 |     } finally {
 42 |       setLoading(false);
 43 |     }
 44 |   };
 45 | 
 46 |   const handleAccept = async () => {
 47 |     try {
 48 |       await NavigationMonitorService.storeAcceptanceDate('terms');
 49 |       
 50 |       if (fromUpdate) {
 51 |         navigation.goBack();
 52 |       }
 53 |     } catch (err) {
 54 |       console.error('Error saving acceptance date:', err);
 55 |       Alert.alert('Error', 'Failed to save your acceptance. Please try again.');
 56 |     }
 57 |   };
 58 | 
 59 |   if (loading) {
 60 |     return (
 61 |       <SafeAreaView style={styles.container}>
 62 |         <View style={styles.loadingContainer}>
 63 |           <ActivityIndicator size="large" color={colors.primary} />
 64 |         </View>
 65 |       </SafeAreaView>
 66 |     );
 67 |   }
 68 | 
 69 |   if (error) {
 70 |     return (
 71 |       <SafeAreaView style={styles.container}>
 72 |         <View style={styles.errorContainer}>
 73 |           <Text style={styles.errorText}>{error}</Text>
 74 |           <TouchableOpacity style={styles.retryButton} onPress={fetchTermsContent}>
 75 |             <Text style={styles.retryButtonText}>Retry</Text>
 76 |           </TouchableOpacity>
 77 |         </View>
 78 |       </SafeAreaView>
 79 |     );
 80 |   }
 81 | 
 82 |   return (
 83 |     <SafeAreaView style={styles.container}>
 84 |       <View style={styles.header}>
 85 |         <TouchableOpacity 
 86 |           style={styles.backButton} 
 87 |           onPress={() => navigation.goBack()}
 88 |         >
 89 |           <Text style={styles.backButtonText}>←</Text>
 90 |         </TouchableOpacity>
 91 |         <Text style={styles.headerTitle}>{title || 'Terms and Conditions'}</Text>
 92 |       </View>
 93 |       <ScrollView style={styles.scrollView}>
 94 |         <View style={styles.content}>
 95 |           <HTML source={{ html: content }} contentWidth={300} />
 96 |         </View>
 97 |       </ScrollView>
 98 |       {fromUpdate && (
 99 |         <TouchableOpacity style={styles.acceptButton} onPress={handleAccept}>
100 |           <Text style={styles.acceptButtonText}>Accept Terms</Text>
101 |         </TouchableOpacity>
102 |       )}
103 |     </SafeAreaView>
104 |   );
105 | };
106 | 
107 | const styles = StyleSheet.create({
108 |   loadingContainer: {
109 |     flex: 1,
110 |     justifyContent: 'center',
111 |     alignItems: 'center',
112 |   },
113 |   errorContainer: {
114 |     flex: 1,
115 |     justifyContent: 'center',
116 |     alignItems: 'center',
117 |     padding: 20,
118 |   },
119 |   errorText: {
120 |     fontSize: 16,
121 |     color: 'red',
122 |     textAlign: 'center',
123 |     marginBottom: 20,
124 |   },
125 |   retryButton: {
126 |     backgroundColor: colors.primary,
127 |     padding: 10,
128 |     borderRadius: 5,
129 |   },
130 |   retryButtonText: {
131 |     color: '#FFFFFF',
132 |     fontSize: 16,
133 |   },
134 |   acceptButton: {
135 |     backgroundColor: colors.primary,
136 |     padding: 16,
137 |     margin: 16,
138 |     borderRadius: 8,
139 |     alignItems: 'center',
140 |   },
141 |   acceptButtonText: {
142 |     color: '#FFFFFF',
143 |     fontSize: 16,
144 |     fontWeight: '600',
145 |   },
146 |   container: {
147 |     flex: 1,
148 |     backgroundColor: '#FFFFFF',
149 |   },
150 |   header: {
151 |     flexDirection: 'row',
152 |     alignItems: 'center',
153 |     padding: 16,
154 |     borderBottomWidth: 1,
155 |     borderBottomColor: '#E5E5E5',
156 |   },
157 |   backButton: {
158 |     padding: 8,
159 |   },
160 |   backButtonText: {
161 |     fontSize: 24,
162 |     color: colors.primary,
163 |   },
164 |   headerTitle: {
165 |     fontSize: 18,
166 |     fontWeight: '600',
167 |     marginLeft: 8,
168 |     color: colors.primary,
169 |   },
170 |   scrollView: {
171 |     flex: 1,
172 |   },
173 |   content: {
174 |     padding: 20,
175 |   },
176 |   title: {
177 |     fontSize: 24,
178 |     fontWeight: 'bold',
179 |     marginBottom: 10,
180 |     color: colors.primary,
181 |   },
182 |   lastUpdated: {
183 |     fontSize: 14,
184 |     color: '#666',
185 |     marginBottom: 20,
186 |   },
187 |   sectionTitle: {
188 |     fontSize: 18,
189 |     fontWeight: '600',
190 |     marginTop: 20,
191 |     marginBottom: 10,
192 |     color: colors.primary,
193 |   },
194 |   text: {
195 |     fontSize: 16,
196 |     lineHeight: 24,
197 |     color: colors.primary,
198 |     marginBottom: 15,
199 |   },
200 | });
201 | 
202 | export default TermsAndConditionsScreen;
203 | 
```

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

```typescript
  1 | import React, { useEffect, useState } from 'react';
  2 | import { View, Text, ScrollView, StyleSheet, TouchableOpacity, ActivityIndicator, Alert } from 'react-native';
  3 | import { SafeAreaView } from 'react-native-safe-area-context';
  4 | import { colors } from '../../../theme/colors';
  5 | import { API } from '../../../helper/config';
  6 | import { NavigationMonitorService } from '../../../helper/NavigationMonitorService';
  7 | import axiosRequest from '../../../helper/axiosRequest';
  8 | import HTML from 'react-native-render-html';
  9 | 
 10 | interface PrivacyResponse {
 11 |   status: number;
 12 |   privacy_page: Array<{
 13 |     post_title: string;
 14 |     post_content: string;
 15 |   }>;
 16 | }
 17 | 
 18 | const PrivacyPolicyScreen = ({ navigation, route }: any) => {
 19 |   const [loading, setLoading] = useState(true);
 20 |   const [error, setError] = useState<string | null>(null);
 21 |   const [content, setContent] = useState<string>('');
 22 |   const [title, setTitle] = useState<string>('');
 23 |   const fromUpdate = route.params?.fromUpdate || false;
 24 |   useEffect(() => {
 25 |     fetchPrivacyContent();
 26 |   }, []);
 27 | 
 28 |   const fetchPrivacyContent = async () => {
 29 |     try {
 30 |       const response = await axiosRequest.get<PrivacyResponse>(`${API.BASE_URL}/${API.ENDPOINTS.GET_PRIVACY_PAGE}`);
 31 |       
 32 |       if (response.data?.privacy_page?.[0]) {
 33 |         setTitle(response.data.privacy_page[0].post_title);
 34 |         setContent(response.data.privacy_page[0].post_content);
 35 |       } else {
 36 |         setError('No privacy policy content found');
 37 |       }
 38 |     } catch (err) {
 39 |       setError('Failed to load privacy policy content');
 40 |       console.error('Error fetching privacy policy:', err);
 41 |     } finally {
 42 |       setLoading(false);
 43 |     }
 44 |   };
 45 | 
 46 |   const handleAccept = async () => {
 47 |     try {
 48 |       await NavigationMonitorService.storeAcceptanceDate('privacy');
 49 |       
 50 |       if (fromUpdate) {
 51 |         navigation.goBack();
 52 |       }
 53 |     } catch (err) {
 54 |       console.error('Error saving acceptance date:', err);
 55 |       Alert.alert('Error', 'Failed to save your acceptance. Please try again.');
 56 |     }
 57 |   };
 58 | 
 59 |   if (loading) {
 60 |     return (
 61 |       <SafeAreaView style={styles.container}>
 62 |         <View style={styles.loadingContainer}>
 63 |           <ActivityIndicator size="large" color={colors.primary} />
 64 |         </View>
 65 |       </SafeAreaView>
 66 |     );
 67 |   }
 68 | 
 69 |   if (error) {
 70 |     return (
 71 |       <SafeAreaView style={styles.container}>
 72 |         <View style={styles.errorContainer}>
 73 |           <Text style={styles.errorText}>{error}</Text>
 74 |           <TouchableOpacity style={styles.retryButton} onPress={fetchPrivacyContent}>
 75 |             <Text style={styles.retryButtonText}>Retry</Text>
 76 |           </TouchableOpacity>
 77 |         </View>
 78 |       </SafeAreaView>
 79 |     );
 80 |   }
 81 | 
 82 |   return (
 83 |     <SafeAreaView style={styles.container}>
 84 |       <View style={styles.header}>
 85 |         <TouchableOpacity 
 86 |           style={styles.backButton} 
 87 |           onPress={() => navigation.goBack()}
 88 |         >
 89 |           <Text style={styles.backButtonText}>←</Text>
 90 |         </TouchableOpacity>
 91 |         <Text style={styles.headerTitle}>{title || 'Privacy Policy'}</Text>
 92 |       </View>
 93 |       <ScrollView style={styles.scrollView}>
 94 |         <View style={styles.content}>
 95 |           <HTML source={{ html: content }} contentWidth={300} />
 96 |         </View>
 97 |       </ScrollView>
 98 |       {fromUpdate && (
 99 |         <TouchableOpacity style={styles.acceptButton} onPress={handleAccept}>
100 |           <Text style={styles.acceptButtonText}>Accept Privacy Policy</Text>
101 |         </TouchableOpacity>
102 |       )}
103 |     </SafeAreaView>
104 |   );
105 | };
106 | 
107 | const styles = StyleSheet.create({
108 |   loadingContainer: {
109 |     flex: 1,
110 |     justifyContent: 'center',
111 |     alignItems: 'center',
112 |   },
113 |   errorContainer: {
114 |     flex: 1,
115 |     justifyContent: 'center',
116 |     alignItems: 'center',
117 |     padding: 20,
118 |   },
119 |   errorText: {
120 |     fontSize: 16,
121 |     color: 'red',
122 |     textAlign: 'center',
123 |     marginBottom: 20,
124 |   },
125 |   retryButton: {
126 |     backgroundColor: colors.primary,
127 |     padding: 10,
128 |     borderRadius: 5,
129 |   },
130 |   retryButtonText: {
131 |     color: '#FFFFFF',
132 |     fontSize: 16,
133 |   },
134 |   acceptButton: {
135 |     backgroundColor: colors.primary,
136 |     padding: 16,
137 |     margin: 16,
138 |     borderRadius: 8,
139 |     alignItems: 'center',
140 |   },
141 |   acceptButtonText: {
142 |     color: '#FFFFFF',
143 |     fontSize: 16,
144 |     fontWeight: '600',
145 |   },
146 |   container: {
147 |     flex: 1,
148 |     backgroundColor: '#FFFFFF',
149 |   },
150 |   header: {
151 |     flexDirection: 'row',
152 |     alignItems: 'center',
153 |     padding: 16,
154 |     borderBottomWidth: 1,
155 |     borderBottomColor: '#E5E5E5',
156 |   },
157 |   backButton: {
158 |     padding: 8,
159 |   },
160 |   backButtonText: {
161 |     fontSize: 24,
162 |     color: colors.primary,
163 |   },
164 |   headerTitle: {
165 |     fontSize: 18,
166 |     fontWeight: '600',
167 |     marginLeft: 8,
168 |     color: colors.primary,
169 |   },
170 |   scrollView: {
171 |     flex: 1,
172 |   },
173 |   content: {
174 |     padding: 20,
175 |   },
176 |   title: {
177 |     fontSize: 24,
178 |     fontWeight: 'bold',
179 |     marginBottom: 10,
180 |     color: colors.primary,
181 |   },
182 |   lastUpdated: {
183 |     fontSize: 14,
184 |     color: '#666',
185 |     marginBottom: 20,
186 |   },
187 |   sectionTitle: {
188 |     fontSize: 18,
189 |     fontWeight: '600',
190 |     marginTop: 20,
191 |     marginBottom: 10,
192 |     color: colors.primary,
193 |   },
194 |   text: {
195 |     fontSize: 16,
196 |     lineHeight: 24,
197 |     color: colors.primary,
198 |     marginBottom: 15,
199 |   },
200 | });
201 | 
202 | export default PrivacyPolicyScreen;
203 | 
```

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

```markdown
  1 | # Component Design Standards
  2 | 
  3 | BluestoneApps follows these standards for designing React Native components.
  4 | 
  5 | ## Component Structure
  6 | 
  7 | ### Flat Component Organization
  8 | 
  9 | We use a flat component organization structure with all reusable components placed directly in the components directory:
 10 | 
 11 | ```
 12 | src/
 13 | └── components/
 14 |     ├── Button.tsx
 15 |     ├── ErrorBoundary.tsx
 16 |     ├── LoadingSpinner.tsx
 17 |     └── UpdateModal.tsx
 18 | ```
 19 | 
 20 | Screen-specific components may be placed within their respective screen directories when they are not meant to be reused across the application.
 21 | 
 22 | ## Component Implementation
 23 | 
 24 | ### Functional Components with TypeScript
 25 | 
 26 | We use functional components with TypeScript interfaces for props:
 27 | 
 28 | ```typescript
 29 | // src/components/Button.tsx
 30 | import React from 'react';
 31 | import {
 32 |   TouchableOpacity,
 33 |   Text,
 34 |   StyleSheet,
 35 |   ViewStyle,
 36 |   TextStyle,
 37 |   ActivityIndicator,
 38 | } from 'react-native';
 39 | 
 40 | interface ButtonProps {
 41 |   title: string;
 42 |   onPress: () => void;
 43 |   style?: ViewStyle;
 44 |   textStyle?: TextStyle;
 45 |   loading?: boolean;
 46 |   disabled?: boolean;
 47 | }
 48 | 
 49 | export const Button: React.FC<ButtonProps> = ({
 50 |   title,
 51 |   onPress,
 52 |   style,
 53 |   textStyle,
 54 |   loading = false,
 55 |   disabled = false,
 56 | }) => {
 57 |   return (
 58 |     <TouchableOpacity
 59 |       style={[
 60 |         styles.button,
 61 |         style,
 62 |         disabled && styles.disabledButton,
 63 |       ]}
 64 |       onPress={onPress}
 65 |       disabled={disabled || loading}
 66 |     >
 67 |       {loading ? (
 68 |         <ActivityIndicator color="#fff" />
 69 |       ) : (
 70 |         <Text style={[styles.text, textStyle]}>{title}</Text>
 71 |       )}
 72 |     </TouchableOpacity>
 73 |   );
 74 | };
 75 | 
 76 | const styles = StyleSheet.create({
 77 |   button: {
 78 |     backgroundColor: '#007AFF',
 79 |     paddingVertical: 12,
 80 |     paddingHorizontal: 24,
 81 |     borderRadius: 8,
 82 |     alignItems: 'center',
 83 |     justifyContent: 'center',
 84 |   },
 85 |   text: {
 86 |     color: '#FFFFFF',
 87 |     fontSize: 16,
 88 |     fontWeight: '600',
 89 |   },
 90 |   disabledButton: {
 91 |     backgroundColor: '#CCCCCC',
 92 |   },
 93 | });
 94 | ```
 95 | 
 96 | ### Inline Styles
 97 | 
 98 | 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.
 99 | 
100 | ```typescript
101 | // Example of styles in a separate file (for a screen component)
102 | // src/screens/PostLogin/BluestoneAppsAI/Styles.ts
103 | import { StyleSheet } from 'react-native';
104 | 
105 | export const styles = StyleSheet.create({
106 |   container: {
107 |     flex: 1,
108 |     padding: 16,
109 |     backgroundColor: '#FFFFFF',
110 |   },
111 |   header: {
112 |     fontSize: 24,
113 |     fontWeight: 'bold',
114 |     marginBottom: 16,
115 |   },
116 |   // Other styles...
117 | });
118 | ```
119 | 
120 | ## Component Best Practices
121 | 
122 | ### 1. Props and TypeScript Interfaces
123 | 
124 | - Use TypeScript interfaces for prop typing
125 | - Provide default values for optional props
126 | - Use optional chaining and nullish coalescing for safer prop access
127 | 
128 | ```typescript
129 | // Example of proper TypeScript interface usage
130 | interface LoadingSpinnerProps {
131 |   size?: 'small' | 'large';
132 |   color?: string;
133 |   text?: string;
134 | }
135 | 
136 | export const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
137 |   size = 'large',
138 |   color = '#007AFF',
139 |   text,
140 | }) => {
141 |   // Component implementation
142 | };
143 | ```
144 | 
145 | ### 2. Error Handling
146 | 
147 | - Implement error boundaries to catch and handle component errors
148 | - Use try/catch blocks for error handling in async operations
149 | - Provide meaningful feedback to users when errors occur
150 | 
151 | ```typescript
152 | // Example of an error boundary component
153 | import React, { Component, ErrorInfo, ReactNode } from 'react';
154 | import { View, Text, StyleSheet } from 'react-native';
155 | 
156 | interface ErrorBoundaryProps {
157 |   children: ReactNode;
158 |   fallback?: ReactNode;
159 | }
160 | 
161 | interface ErrorBoundaryState {
162 |   hasError: boolean;
163 |   error: Error | null;
164 | }
165 | 
166 | export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
167 |   constructor(props: ErrorBoundaryProps) {
168 |     super(props);
169 |     this.state = { hasError: false, error: null };
170 |   }
171 | 
172 |   static getDerivedStateFromError(error: Error): ErrorBoundaryState {
173 |     return { hasError: true, error };
174 |   }
175 | 
176 |   componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
177 |     console.error('Component error:', error, errorInfo);
178 |   }
179 | 
180 |   render(): ReactNode {
181 |     if (this.state.hasError) {
182 |       if (this.props.fallback) {
183 |         return this.props.fallback;
184 |       }
185 |       return (
186 |         <View style={styles.errorContainer}>
187 |           <Text style={styles.errorText}>Something went wrong</Text>
188 |         </View>
189 |       );
190 |     }
191 |     return this.props.children;
192 |   }
193 | }
194 | ```
195 | 
196 | ### 3. State Management
197 | 
198 | - Use useState and useEffect hooks for component-level state
199 | - Extract complex state logic into custom hooks
200 | - Use AsyncStorage for persistent data storage
201 | - Consider context API for state that needs to be shared across components
202 | 
203 | ### 4. Performance Considerations
204 | 
205 | - Memoize expensive calculations with useMemo
206 | - Use useCallback for event handlers passed to child components
207 | - Implement proper list rendering with FlatList or SectionList
208 | - Avoid unnecessary re-renders by using React.memo when appropriate
209 | 
210 | ### 5. Accessibility
211 | 
212 | - Provide accessible labels for interactive elements
213 | - Ensure sufficient color contrast
214 | - Support dynamic text sizes
215 | - Test with screen readers
216 | - Ensure adequate color contrast
217 | 
218 | ### 6. Testing
219 | 
220 | - Write unit tests for component logic
221 | - Use snapshot testing for UI consistency
222 | - Test user interactions
223 | 
224 | ## Component Documentation
225 | 
226 | Document components with JSDoc comments:
227 | 
228 | ```typescript
229 | /**
230 |  * Primary button component for user actions.
231 |  * 
232 |  * @example
233 |  * <Button 
234 |  *   title="Sign Up" 
235 |  *   onPress={handleSignUp} 
236 |  *   variant="primary" 
237 |  * />
238 |  */
239 | export const Button: React.FC<ButtonProps> = (/* ... */) => {
240 |   // ...
241 | };
242 | ```
243 | 
```

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

```markdown
  1 | # API Communication Standards
  2 | 
  3 | BluestoneApps follows these standards for API communication in React Native applications.
  4 | 
  5 | ## Structure
  6 | 
  7 | ### API Configuration and Utilities
  8 | 
  9 | We use a structured approach to API communication with the following key files:
 10 | 
 11 | ```
 12 | src/
 13 | ├── config/
 14 | │   ├── apiConfig.ts       # API endpoint definitions and configuration
 15 | │   └── environment.ts     # Environment-specific configuration
 16 | ├── services/
 17 |     ├── apiService.ts      # Core API service with fetch methods
 18 |     ├── authService.ts     # Authentication-related API calls
 19 |     ├── userService.ts     # User-related API calls
 20 |     └── ...                # Other domain-specific services
 21 | ```
 22 | 
 23 | ## API Configuration
 24 | 
 25 | We define API endpoints and configuration in dedicated files:
 26 | 
 27 | ```typescript
 28 | // src/config/environment.ts
 29 | export const environment = {
 30 |   server: 'api.example.com',
 31 |   isProduction: true,
 32 |   version: '1.0.0',
 33 | };
 34 | 
 35 | // src/config/apiConfig.ts
 36 | import { environment } from './environment';
 37 | 
 38 | export const API = {
 39 |   BASE_URL: `https://${environment.server}/`,
 40 |   ENDPOINTS: {
 41 |     LOGIN: 'auth/login',
 42 |     REGISTER: 'auth/register',
 43 |     USER_PROFILE: 'user/profile',
 44 |     MOBILE_API: 'wp-json/mobileapi/v1/',
 45 |     // Other endpoints
 46 |   },
 47 |   TIMEOUT: 30000,
 48 | };
 49 | 
 50 | // Optional: Define types for API responses
 51 | export interface ApiResponse<T> {
 52 |   status: string;
 53 |   message?: string;
 54 |   data?: T;
 55 | }
 56 | ```
 57 | 
 58 | ## API Service Implementation
 59 | 
 60 | We use a centralized API service with fetch-based methods:
 61 | 
 62 | ```typescript
 63 | // src/services/apiService.ts
 64 | import { storageService } from './storageService';
 65 | import { environment } from '../config/environment';
 66 | 
 67 | const BASE_URL = `https://${environment.server}/`;
 68 | const MOBILE_API = `${BASE_URL}wp-json/mobileapi/v1/`;
 69 | 
 70 | interface ApiResponse {
 71 |   status: string;
 72 |   errormsg: string;
 73 |   error_code: string;
 74 |   data?: any;
 75 | }
 76 | 
 77 | class ApiService {
 78 |   async getData(endpoint: string) {
 79 |     try {
 80 |       console.log('Fetching from:', MOBILE_API + endpoint);
 81 |       const response = await fetch(MOBILE_API + endpoint);
 82 |       if (!response.ok) {
 83 |         throw new Error(`HTTP error! status: ${response.status}`);
 84 |       }
 85 |       const data = await response.json();
 86 |       return data;
 87 |     } catch (error) {
 88 |       console.error('Error fetching data:', error);
 89 |       throw error;
 90 |     }
 91 |   }
 92 | 
 93 |   async sendData(endpoint: string, data: any) {
 94 |     const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
 95 |     const payload = {
 96 |       ...(typeof data === 'object' ? data : { value: data }),
 97 |       timezone,
 98 |     };
 99 | 
100 |     try {
101 |       const response = await fetch(MOBILE_API + endpoint, {
102 |         method: 'POST',
103 |         headers: {
104 |           'Content-Type': 'application/json',
105 |         },
106 |         body: JSON.stringify(payload),
107 |       });
108 | 
109 |       if (!response.ok) {
110 |         throw new Error(`HTTP error! status: ${response.status}`);
111 |       }
112 | 
113 |       const result = await response.json();
114 |       return result;
115 |     } catch (error) {
116 |       console.error('Error sending data:', error);
117 |       throw error;
118 |     }
119 |   }
120 | }
121 | 
122 | export const apiService = new ApiService();
123 | ```
124 | 
125 | ## Domain-Specific Services
126 | 
127 | We create separate service files for different domains:
128 | 
129 | ```typescript
130 | // src/services/authService.ts
131 | import { apiService } from './apiService';
132 | import { storageService } from './storageService';
133 | 
134 | class AuthService {
135 |   async login(email: string, password: string) {
136 |     try {
137 |       const response = await apiService.sendData('login', { email, password });
138 |       
139 |       if (response.status === 'ok' && response.token) {
140 |         await storageService.set('userToken', response.token);
141 |         await storageService.set('user', response.user);
142 |         return response;
143 |       }
144 |       
145 |       throw new Error(response.errormsg || 'Login failed');
146 |     } catch (error) {
147 |       console.error('Login error:', error);
148 |       throw error;
149 |     }
150 |   }
151 | 
152 |   async logout() {
153 |     try {
154 |       await storageService.remove('userToken');
155 |       await storageService.remove('user');
156 |       return true;
157 |     } catch (error) {
158 |       console.error('Logout error:', error);
159 |       throw error;
160 |     }
161 |   }
162 | }
163 | 
164 | export const authService = new AuthService();
165 | ```
166 | 
167 | ## Error Handling
168 | 
169 | We implement consistent error handling across all API calls:
170 | 
171 | 1. Log errors for debugging
172 | 2. Use try/catch blocks for all async operations
173 | 3. Provide meaningful error messages
174 | 4. Handle specific error types appropriately
175 | 
176 | ## Example Usage in Components
177 | 
178 | ```typescript
179 | // Example in a screen component
180 | import React, { useState } from 'react';
181 | import { View, Alert } from 'react-native';
182 | import { authService } from '../services/authService';
183 | import { Button } from '../components/Button';
184 | 
185 | const LoginScreen = ({ navigation }) => {
186 |   const [loading, setLoading] = useState(false);
187 | 
188 |   const handleLogin = async (email: string, password: string) => {
189 |     try {
190 |       setLoading(true);
191 |       await authService.login(email, password);
192 |       navigation.navigate('Home');
193 |     } catch (error) {
194 |       Alert.alert('Login Failed', error instanceof Error ? error.message : 'Unknown error');
195 |     } finally {
196 |       setLoading(false);
197 |     }
198 |   };
199 | 
200 |   return (
201 |     <View>
202 |       {/* Form fields */}
203 |       <Button 
204 |         title="Login" 
205 |         onPress={() => handleLogin('[email protected]', 'password')} 
206 |         loading={loading} 
207 |       />
208 |     </View>
209 |   );
210 | };
211 | ```
212 | 
213 | ## Best Practices
214 | 
215 | 1. Use TypeScript interfaces for request and response types
216 | 2. Implement proper error handling for all API calls
217 | 3. Store authentication tokens securely
218 | 4. Use environment-specific configuration
219 | 5. Log API calls and errors for debugging
220 | 6. Implement retry logic for important operations
221 | 7. Handle offline scenarios gracefully
222 | 
```

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

```typescript
  1 | import React, { useEffect, useState } from 'react';
  2 | import { View, Text, ScrollView, StyleSheet, Alert } from 'react-native';
  3 | import { useNavigation } from '@react-navigation/native';
  4 | import AsyncStorage from '@react-native-async-storage/async-storage';
  5 | import axiosRequest from '../helper/axiosRequest';
  6 | import { API } from '../helper/config';
  7 | import { Button } from '../components/Button';
  8 | import HTML from 'react-native-render-html';
  9 | import { useWindowDimensions } from 'react-native';
 10 | import { LoadingSpinner } from '../components/LoadingSpinner';
 11 | 
 12 | export const AboutUs = () => {
 13 |   const [aboutUsContent, setAboutUsContent] = useState<string>('');
 14 |   const [userId, setUserId] = useState<string | null>(null);
 15 |   const [isLoading, setIsLoading] = useState(false);
 16 |   const navigation = useNavigation();
 17 |   const { width } = useWindowDimensions();
 18 | 
 19 |   useEffect(() => {
 20 |     getAboutUs();
 21 |     getUserData();
 22 |   }, []);
 23 | 
 24 |   const getUserData = async () => {
 25 |     try {
 26 |       const userDataString = await AsyncStorage.getItem('userData');
 27 |       if (userDataString) {
 28 |         const userData = JSON.parse(userDataString);
 29 |         setUserId(userData.user_id);
 30 |       }
 31 |     } catch (error) {
 32 |       console.error('Error getting user data:', error);
 33 |     }
 34 |   };
 35 | 
 36 |   const getAboutUs = async () => {
 37 |     setIsLoading(true);
 38 |     try {
 39 |       const response = await axiosRequest.post(
 40 |         `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.GET_ABOUTUS}`,
 41 |         {},
 42 |         {
 43 |           headers: {
 44 |             'Accept': 'application/json',
 45 |             'Content-Type': 'application/json'
 46 |           }
 47 |         }
 48 |       );
 49 |       setAboutUsContent(response.aboutus_content);
 50 |     } catch (error: any) {
 51 |       console.error('Error getting about us content:', error);
 52 |       Alert.alert('Error', 'Failed to load about us content');
 53 |     } finally {
 54 |       setIsLoading(false);
 55 |     }
 56 |   };
 57 | 
 58 |   const confirmDeleteAccount = () => {
 59 |     Alert.alert(
 60 |       'Delete Account',
 61 |       'This action cannot be undone. Are you sure you want to delete your account?',
 62 |       [
 63 |         {
 64 |           text: 'Cancel',
 65 |           style: 'cancel'
 66 |         },
 67 |         {
 68 |           text: 'Delete',
 69 |           onPress: deleteAccount,
 70 |           style: 'destructive'
 71 |         }
 72 |       ]
 73 |     );
 74 |   };
 75 | 
 76 |   const deleteAccount = async () => {
 77 |     if (!userId) {
 78 |       Alert.alert('Error', 'User ID not found');
 79 |       return;
 80 |     }
 81 | 
 82 |     setIsLoading(true);
 83 |     try {
 84 |       const response = await axiosRequest.post(
 85 |         `${API.ENDPOINTS.MOBILEAPI}/${API.ENDPOINTS.DELETE_USER}`,
 86 |         { user_id: userId },
 87 |         {
 88 |           headers: {
 89 |             'Accept': 'application/json',
 90 |             'Content-Type': 'application/json'
 91 |           }
 92 |         }
 93 |       );
 94 | 
 95 |       if (response.status === 'success') {
 96 |         Alert.alert(
 97 |           'Account Deleted',
 98 |           'Thank you for using our app.',
 99 |           [
100 |             {
101 |               text: 'OK',
102 |               onPress: async () => {
103 |                 try {
104 |                   await AsyncStorage.clear();
105 |                 } catch (err) {
106 |                   console.warn('Error clearing storage:', err);
107 |                   // Continue even if clearing fails
108 |                 } finally {
109 |                   navigation.reset({
110 |                     index: 0,
111 |                     routes: [{ name: 'Login' }],
112 |                   });
113 |                 }
114 |               }
115 |             }
116 |           ]
117 |         );
118 |       } else {
119 |         throw new Error(response.message || 'Failed to delete account');
120 |       }
121 |     } catch (error: any) {
122 |       console.error('Error deleting account:', error);
123 |       Alert.alert('Error', 'Something went wrong. Please try again later.');
124 |       try {
125 |         await AsyncStorage.clear();
126 |       } catch (err) {
127 |         console.warn('Error clearing storage:', err);
128 |         // Continue even if clearing fails
129 |       } finally {
130 |         navigation.reset({
131 |           index: 0,
132 |           routes: [{ name: 'Login' }],
133 |         });
134 |       }
135 |     } finally {
136 |       setIsLoading(false);
137 |     }
138 |   };
139 | 
140 |   if (isLoading) {
141 |     return <LoadingSpinner />;
142 |   }
143 | 
144 |   return (
145 |     <View style={styles.container}>
146 |       <ScrollView contentContainerStyle={styles.scrollContent}>
147 |         {aboutUsContent ? (
148 |           <HTML 
149 |             source={{ html: aboutUsContent }} 
150 |             contentWidth={width}
151 |             tagsStyles={{
152 |               p: styles.paragraph,
153 |               h1: styles.heading,
154 |               h2: styles.heading,
155 |               h3: styles.heading,
156 |               a: styles.link
157 |             }}
158 |           />
159 |         ) : (
160 |           <Text style={styles.noContent}>No content available</Text>
161 |         )}
162 |       </ScrollView>
163 |       <View style={styles.buttonContainer}>
164 |         <Button 
165 |           title="Delete Account" 
166 |           onPress={confirmDeleteAccount}
167 |           style={styles.deleteButton}
168 |           textStyle={styles.deleteButtonText}
169 |         />
170 |       </View>
171 |     </View>
172 |   );
173 | };
174 | 
175 | const styles = StyleSheet.create({
176 |   container: {
177 |     flex: 1,
178 |     backgroundColor: '#fff'
179 |   },
180 |   scrollContent: {
181 |     padding: 16,
182 |     paddingBottom: 80
183 |   },
184 |   paragraph: {
185 |     fontSize: 16,
186 |     lineHeight: 24,
187 |     color: '#333',
188 |     marginBottom: 16
189 |   },
190 |   heading: {
191 |     fontSize: 20,
192 |     fontWeight: 'bold',
193 |     color: '#000',
194 |     marginBottom: 16,
195 |     marginTop: 8
196 |   },
197 |   link: {
198 |     color: '#007AFF'
199 |   },
200 |   noContent: {
201 |     fontSize: 16,
202 |     color: '#666',
203 |     textAlign: 'center',
204 |     marginTop: 20
205 |   },
206 |   buttonContainer: {
207 |     padding: 16,
208 |     backgroundColor: '#fff',
209 |     borderTopWidth: 1,
210 |     borderTopColor: '#eee',
211 |     position: 'absolute',
212 |     bottom: 0,
213 |     left: 0,
214 |     right: 0
215 |   },
216 |   deleteButton: {
217 |     backgroundColor: '#FF3B30'
218 |   },
219 |   deleteButtonText: {
220 |     color: '#fff'
221 |   }
222 | });
223 | 
```

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

```typescript
  1 | import { useState, useCallback, useMemo } from 'react';
  2 | 
  3 | /**
  4 |  * Form field configuration
  5 |  */
  6 | interface FormField<T> {
  7 |   value: T;
  8 |   error?: string;
  9 |   touched: boolean;
 10 |   required?: boolean;
 11 |   validator?: (value: T) => string | undefined;
 12 | }
 13 | 
 14 | /**
 15 |  * Form state containing fields
 16 |  */
 17 | type FormState<T extends Record<string, any>> = {
 18 |   [K in keyof T]: FormField<T[K]>;
 19 | };
 20 | 
 21 | /**
 22 |  * Form values extracted from form state
 23 |  */
 24 | type FormValues<T extends Record<string, any>> = {
 25 |   [K in keyof T]: T[K];
 26 | };
 27 | 
 28 | /**
 29 |  * Form errors extracted from form state
 30 |  */
 31 | type FormErrors<T extends Record<string, any>> = {
 32 |   [K in keyof T]?: string;
 33 | };
 34 | 
 35 | /**
 36 |  * Custom hook for form state management
 37 |  * 
 38 |  * @param initialValues Initial values for the form
 39 |  * @param validators Optional validators for form fields
 40 |  * @returns Form state and helper functions
 41 |  * 
 42 |  * @example
 43 |  * ```tsx
 44 |  * const { values, errors, touched, handleChange, handleBlur, handleSubmit, isValid } = useForm({
 45 |  *   email: '',
 46 |  *   password: '',
 47 |  * }, {
 48 |  *   email: (value) => (!value ? 'Email is required' : !isValidEmail(value) ? 'Invalid email format' : undefined),
 49 |  *   password: (value) => (!value ? 'Password is required' : value.length < 6 ? 'Password too short' : undefined),
 50 |  * });
 51 |  * ```
 52 |  */
 53 | function useForm<T extends Record<string, any>>(
 54 |   initialValues: T,
 55 |   validators?: Partial<Record<keyof T, (value: any) => string | undefined>>,
 56 |   requiredFields?: Array<keyof T>
 57 | ) {
 58 |   // Create initial form state
 59 |   const createInitialState = (): FormState<T> => {
 60 |     const state: Partial<FormState<T>> = {};
 61 |     
 62 |     for (const key in initialValues) {
 63 |       if (Object.prototype.hasOwnProperty.call(initialValues, key)) {
 64 |         state[key] = {
 65 |           value: initialValues[key],
 66 |           touched: false,
 67 |           required: requiredFields?.includes(key) ?? false,
 68 |           validator: validators?.[key],
 69 |         };
 70 |       }
 71 |     }
 72 |     
 73 |     return state as FormState<T>;
 74 |   };
 75 |   
 76 |   // State for form fields
 77 |   const [formState, setFormState] = useState<FormState<T>>(createInitialState());
 78 |   
 79 |   // Extract values from form state
 80 |   const values = useMemo(() => {
 81 |     const result: Partial<FormValues<T>> = {};
 82 |     
 83 |     for (const key in formState) {
 84 |       if (Object.prototype.hasOwnProperty.call(formState, key)) {
 85 |         result[key] = formState[key].value;
 86 |       }
 87 |     }
 88 |     
 89 |     return result as FormValues<T>;
 90 |   }, [formState]);
 91 |   
 92 |   // Extract errors from form state
 93 |   const errors = useMemo(() => {
 94 |     const result: Partial<FormErrors<T>> = {};
 95 |     
 96 |     for (const key in formState) {
 97 |       if (Object.prototype.hasOwnProperty.call(formState, key) && formState[key].error) {
 98 |         result[key] = formState[key].error;
 99 |       }
100 |     }
101 |     
102 |     return result as FormErrors<T>;
103 |   }, [formState]);
104 |   
105 |   // Extract touched state from form state
106 |   const touched = useMemo(() => {
107 |     const result: Partial<Record<keyof T, boolean>> = {};
108 |     
109 |     for (const key in formState) {
110 |       if (Object.prototype.hasOwnProperty.call(formState, key)) {
111 |         result[key] = formState[key].touched;
112 |       }
113 |     }
114 |     
115 |     return result as Record<keyof T, boolean>;
116 |   }, [formState]);
117 |   
118 |   // Validate a single field
119 |   const validateField = useCallback((name: keyof T, value: any): string | undefined => {
120 |     const field = formState[name];
121 |     
122 |     // Required field validation
123 |     if (field.required && (value === '' || value === null || value === undefined)) {
124 |       return `${String(name)} is required`;
125 |     }
126 |     
127 |     // Custom validator
128 |     if (field.validator) {
129 |       return field.validator(value);
130 |     }
131 |     
132 |     return undefined;
133 |   }, [formState]);
134 |   
135 |   // Handle field change
136 |   const handleChange = useCallback((name: keyof T, value: any) => {
137 |     setFormState(prev => ({
138 |       ...prev,
139 |       [name]: {
140 |         ...prev[name],
141 |         value,
142 |         error: validateField(name, value),
143 |       },
144 |     }));
145 |   }, [validateField]);
146 |   
147 |   // Handle field blur
148 |   const handleBlur = useCallback((name: keyof T) => {
149 |     setFormState(prev => ({
150 |       ...prev,
151 |       [name]: {
152 |         ...prev[name],
153 |         touched: true,
154 |         error: validateField(name, prev[name].value),
155 |       },
156 |     }));
157 |   }, [validateField]);
158 |   
159 |   // Reset form to initial values
160 |   const resetForm = useCallback(() => {
161 |     setFormState(createInitialState());
162 |   }, []);
163 |   
164 |   // Validate all fields
165 |   const validateForm = useCallback((): boolean => {
166 |     let isValid = true;
167 |     const newState = { ...formState };
168 |     
169 |     for (const key in formState) {
170 |       if (Object.prototype.hasOwnProperty.call(formState, key)) {
171 |         const error = validateField(key, formState[key].value);
172 |         newState[key] = {
173 |           ...newState[key],
174 |           error,
175 |           touched: true,
176 |         };
177 |         
178 |         if (error) {
179 |           isValid = false;
180 |         }
181 |       }
182 |     }
183 |     
184 |     setFormState(newState);
185 |     return isValid;
186 |   }, [formState, validateField]);
187 |   
188 |   // Handle form submission
189 |   const handleSubmit = useCallback((onSubmit: (values: FormValues<T>) => void) => {
190 |     return (e?: React.FormEvent) => {
191 |       if (e) {
192 |         e.preventDefault();
193 |       }
194 |       
195 |       const isValid = validateForm();
196 |       
197 |       if (isValid) {
198 |         onSubmit(values);
199 |       }
200 |     };
201 |   }, [validateForm, values]);
202 |   
203 |   // Check if form is valid
204 |   const isValid = useMemo(() => {
205 |     for (const key in formState) {
206 |       if (Object.prototype.hasOwnProperty.call(formState, key)) {
207 |         if (formState[key].error) {
208 |           return false;
209 |         }
210 |         
211 |         if (formState[key].required && 
212 |             (formState[key].value === '' || 
213 |              formState[key].value === null || 
214 |              formState[key].value === undefined)) {
215 |           return false;
216 |         }
217 |       }
218 |     }
219 |     
220 |     return true;
221 |   }, [formState]);
222 |   
223 |   return {
224 |     values,
225 |     errors,
226 |     touched,
227 |     handleChange,
228 |     handleBlur,
229 |     handleSubmit,
230 |     resetForm,
231 |     validateForm,
232 |     isValid,
233 |   };
234 | }
235 | 
236 | export default useForm;
237 | 
```
Page 1/2FirstPrevNextLast