> ## Documentation Index
> Fetch the complete documentation index at: https://docs.gameball.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Show Profile Widget

> Display the Gameball customer profile widget in your React Native app

# Show Profile Widget

Display the Gameball customer profile widget that contains customer details, available reward campaigns, leaderboard, and more.

## Basic Usage

<div className="security-banner">
  <div className="security-banner-icon">🔒</div>

  <div className="security-banner-content">
    <strong>Secure API Access:</strong> To benefit from v4.1 secure API endpoints, pass the <code>sessionToken</code> parameter when showing the profile widget (required in upcoming SDK v4). This enables automatic routing to v4.1 secure endpoints. <a href="/api-reference/introduction-v4.1">Learn more about v4.1 →</a>
  </div>
</div>

```typescript theme={null}
import { GameballApp, ShowProfileRequest } from 'react-native-gameball';

const profileRequest: ShowProfileRequest = {
  customerId: 'customer-123',       // Optional (omit for guest mode)
  showCloseButton: true,            // Optional
  openDetail: 'rewards',            // Optional
  hideNavigation: false,            // Optional
  closeButtonColor: '#FF6B6B',      // Optional
};

// Using async/await
try {
  await GameballApp.getInstance().showProfile(profileRequest);
} catch (error) {
  console.error('Error showing profile:', error);
}

// With session token override
try {
  await GameballApp.getInstance().showProfile(profileRequest, undefined, 'customer-token');
} catch (error) {
  console.error('Error:', error);
}

// Using callbacks
GameballApp.getInstance().showProfile(profileRequest, {
  onSuccess: () => console.log('Profile shown'),
  onError: (error) => console.error('Error:', error.message)
});
```

## Request Parameters

<ParamField body="customerId" type="string">
  Unique identifier for the customer whose profile to display (optional for guest mode).
</ParamField>

<ParamField body="showCloseButton" type="boolean">
  Show a close button in the widget. Defaults to `false`.
</ParamField>

<ParamField body="openDetail" type="string">
  Specific widget section to open: 'profile', 'achievements', 'rewards'. Opens the main view by default.
</ParamField>

<ParamField body="hideNavigation" type="boolean">
  Hide widget navigation elements. Defaults to `false`.
</ParamField>

<ParamField body="closeButtonColor" type="string">
  Close button color in hex format (e.g., '#FF6B6B'). Only applies if `showCloseButton` is `true`.
</ParamField>

<ParamField body="sessionToken" type="string">
  Optional session token to override the global token for this specific request. Required in upcoming SDK v4.
</ParamField>

<Info>
  In React Native SDK, passing a sessionToken parameter updates the global session token. Pass `undefined` to clear the global token, or omit it to use the current global token.
</Info>

### Validation Rules

**ShowProfileRequest notes:**

* `customerId` is optional; omit it to show the widget in guest mode

## Advanced Configuration

### Open Specific Section

Open a specific section of the profile widget directly:

```typescript theme={null}
const profileRequest: ShowProfileRequest = {
  customerId: 'customer-123',
  openDetail: 'rewards',  // Open the rewards section
};

await GameballApp.getInstance().showProfile(profileRequest);
```

### Custom Close Button

Add a custom-styled close button:

```typescript theme={null}
const profileRequest: ShowProfileRequest = {
  customerId: 'customer-123',
  showCloseButton: true,
  closeButtonColor: '#FF6B6B',
};

await GameballApp.getInstance().showProfile(profileRequest);
```

### Hide Navigation

<Tip>
  Hide navigation works best when combined with `openDetail` to lead users to a specific section.
</Tip>

Display the widget without navigation controls:

```typescript theme={null}
const profileRequest: ShowProfileRequest = {
  customerId: 'customer-123',
  hideNavigation: true,
  openDetail: 'rewards',
};

await GameballApp.getInstance().showProfile(profileRequest);
```

### Guest Mode

Show the widget without authenticating a customer:

```typescript theme={null}
const guestRequest: ShowProfileRequest = {
  showCloseButton: true,
  closeButtonColor: '#4CAF50',
};

await GameballApp.getInstance().showProfile(guestRequest);
```

## Implementation Examples

### Show Profile Button

Display the profile widget when user taps a button:

```typescript theme={null}
import React from 'react';
import { View, Button, Alert } from 'react-native';
import { GameballApp, ShowProfileRequest } from 'react-native-gameball';

interface ProfileScreenProps {
  customerId: string;
}

const ProfileScreen: React.FC<ProfileScreenProps> = ({ customerId }) => {
  const handleShowProfile = async () => {
    const profileRequest: ShowProfileRequest = {
      customerId,
      showCloseButton: true,
      closeButtonColor: '#4CAF50',
    };

    try {
      await GameballApp.getInstance().showProfile(profileRequest);
    } catch (error) {
      Alert.alert('Error', 'Failed to show profile');
    }
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Button
        title="View Rewards & Achievements"
        onPress={handleShowProfile}
      />
    </View>
  );
};

export default ProfileScreen;
```

### Tab Navigator Integration

Integrate with React Navigation tab navigator:

```typescript theme={null}
import React from 'react';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { GameballApp, ShowProfileRequest } from 'react-native-gameball';
import Icon from 'react-native-vector-icons/Ionicons';

const Tab = createBottomTabNavigator();

const RewardsTabScreen = () => {
  React.useEffect(() => {
    showGameballProfile();
  }, []);

  const showGameballProfile = async () => {
    const profileRequest: ShowProfileRequest = {
      customerId: 'customer-123',
    };

    try {
      await GameballApp.getInstance().showProfile(profileRequest);
    } catch (error) {
      console.error('Error showing profile:', error);
    }
  };

  return null; // Profile widget will overlay
};

const MainNavigator = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen 
        name="Home" 
        component={HomeScreen}
        options={{
          tabBarIcon: ({ color, size }) => (
            <Icon name="home" size={size} color={color} />
          ),
        }}
      />
      <Tab.Screen 
        name="Shop" 
        component={ShopScreen}
        options={{
          tabBarIcon: ({ color, size }) => (
            <Icon name="cart" size={size} color={color} />
          ),
        }}
      />
      <Tab.Screen 
        name="Rewards" 
        component={RewardsTabScreen}
        options={{
          tabBarIcon: ({ color, size }) => (
            <Icon name="gift" size={size} color={color} />
          ),
        }}
      />
    </Tab.Navigator>
  );
};
```

### Context-Based Profile

Show different sections based on user context:

```typescript theme={null}
import React from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { GameballApp, ShowProfileRequest } from 'react-native-gameball';

const RewardsActions: React.FC = () => {
  const showSection = async (section: string) => {
    const profileRequest: ShowProfileRequest = {
      customerId: 'customer-123',
      openDetail: section,
      showCloseButton: true,
    };

    try {
      await GameballApp.getInstance().showProfile(profileRequest);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <View>
      <TouchableOpacity onPress={() => showSection('profile')}>
        <Text>View My Profile</Text>
      </TouchableOpacity>
      
      <TouchableOpacity onPress={() => showSection('rewards')}>
        <Text>Available Rewards</Text>
      </TouchableOpacity>
      
      <TouchableOpacity onPress={() => showSection('achievements')}>
        <Text>My Achievements</Text>
      </TouchableOpacity>
    </View>
  );
};
```

### Floating Action Button

Add a rewards button as a floating action button:

```typescript theme={null}
import React from 'react';
import { View, TouchableOpacity, StyleSheet } from 'react-native';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import { GameballApp, ShowProfileRequest } from 'react-native-gameball';

const HomeScreen: React.FC = () => {
  const handleShowRewards = async () => {
    const profileRequest: ShowProfileRequest = {
      customerId: 'customer-123',
      openDetail: 'rewards',
    };

    try {
      await GameballApp.getInstance().showProfile(profileRequest);
    } catch (error) {
      console.error('Error:', error);
    }
  };

  return (
    <View style={styles.container}>
      {/* Your main content */}
      
      <TouchableOpacity 
        style={styles.fab}
        onPress={handleShowRewards}
      >
        <Icon name="gift" size={24} color="white" />
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  fab: {
    position: 'absolute',
    right: 20,
    bottom: 20,
    width: 56,
    height: 56,
    borderRadius: 28,
    backgroundColor: '#4CAF50',
    justifyContent: 'center',
    alignItems: 'center',
    elevation: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25,
    shadowRadius: 3.84,
  },
});

export default HomeScreen;
```

## Widget Content

The profile widget displays:

<CardGroup cols={2}>
  <Card title="Customer Info" icon="user">
    Display name, points balance, tier level, and customer status
  </Card>

  <Card title="Reward Campaigns" icon="gift">
    Available rewards, challenges, and how to earn them
  </Card>

  <Card title="Leaderboard" icon="trophy">
    Customer ranking, top performers, and competitive standings
  </Card>

  <Card title="Transaction History" icon="clock-rotate-left">
    Points earned and redeemed history with detailed breakdown
  </Card>
</CardGroup>

<Info>
  The widget content, design, and branding can be fully customized from your Gameball dashboard.
</Info>

## Error Handling

```typescript theme={null}
const showProfileWithErrorHandling = async (customerId: string) => {
  const profileRequest: ShowProfileRequest = {
    customerId,
    showCloseButton: true,
  };

  try {
    await GameballApp.getInstance().showProfile(profileRequest);
  } catch (error) {
    if (error.message.includes('HTTP 401')) {
      // Handle authentication error
      console.error('Authentication failed');
    } else if (error.message.includes('HTTP 500')) {
      // Handle server error
      console.error('Server error occurred');
    } else {
      // Handle general error
      console.error('Failed to show profile:', error.message);
    }
  }
};
```

## Best Practices

<Steps>
  <Step title="Prominent Access">
    Place the profile widget button in an easily accessible location (e.g., main navigation, profile screen, bottom tab bar).
  </Step>

  <Step title="Badge Indicators">
    Show badge notifications when customers earn new rewards or achievements to increase engagement.
  </Step>

  <Step title="Deep Linking">
    Use the `openDetail` parameter to deep link to specific sections based on user context (e.g., open rewards after purchase).
  </Step>

  <Step title="Consistent Styling">
    Match the close button color with your app's theme using `closeButtonColor` for a cohesive user experience.
  </Step>

  <Step title="Error Handling">
    Always implement proper error handling to provide feedback when the widget fails to load.
  </Step>

  <Step title="Loading States">
    Consider showing a loading indicator while the widget is being displayed.
  </Step>
</Steps>

<Tip>
  Consider showing the profile widget after a customer earns points to increase engagement and encourage repeat purchases. Users are more likely to interact with the widget when they've just been rewarded.
</Tip>

<Warning>
  Ensure you've initialized the customer with `initializeCustomer()` before calling `showProfile()` to guarantee the widget displays accurate customer data. Also, make sure `react-native-webview` is properly installed as the widget depends on it.
</Warning>

## Next Steps

* [Go-Live Checklist](/installation-guides/v3/react-native/go-live-checklist)
* [Migration Notes](/installation-guides/v3/react-native/migration-notes)
