Skip to content

Theme update and code refactoring - #33

Merged
dev-rathore merged 11 commits into
masterfrom
dev
Nov 22, 2024
Merged

dev-rathore merged 11 commits into
masterfrom
dev

Conversation

@dev-rathore

@dev-rathore dev-rathore commented Nov 22, 2024 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a new Select component for item selection with multi-selection support.
    • Added CollaborationHeader and OverviewTabContent components for improved collaboration details display.
    • Implemented a CarouselNative component for enhanced media display.
  • User Interface Enhancements

    • Updated button styles for various components to improve visual consistency.
    • Enhanced the EmptyState component for better user feedback when no data is available.
  • Bug Fixes

    • Removed unused imports and components, streamlining the codebase.
    • Improved error handling in several components to enhance user experience.
  • Chores

    • Updated dependencies in package.json to include Font Awesome icons.
    • Cleaned up and refactored styles across multiple components for better maintainability.

@dev-rathore dev-rathore self-assigned this Nov 22, 2024
@coderabbitai

coderabbitai Bot commented Nov 22, 2024 •

Copy link
Copy Markdown

Walkthrough

The pull request introduces a series of modifications across multiple files, primarily focusing on the removal of the Toast component from various screens, affecting user notifications. Additionally, it includes updates to button styles, imports, and the introduction of new components and styles, particularly for collaboration and influencer management. The changes aim to streamline user interface elements and enhance the overall structure of the application.

Changes

File Change Summary
app/(auth)/create-new-account.tsx Removed Toast import and component, changed button label from "SIGN UP" to "Signup", and removed styling properties.
app/(auth)/forget-password.tsx Removed Toast import and component, modified button properties.
app/(auth)/login.tsx Removed Toast import and component, modified button properties.
app/(main)/(drawer)/(tabs)/_layout.tsx Replaced FontAwesome with FontAwesomeIcon, removed TabBarIcon, updated tab icons and styles.
app/(main)/(screens)/CollaborationHistory.tsx Simplified imports, removed unused components, replaced layout with ScreenHeader.
app/(main)/(screens)/_layout.tsx Removed multiple Stack.Screen components, altering navigation structure.
app/(main)/(screens)/collaboration-details/[pageID].tsx Updated imports, removed state management for collaboration data, simplified rendering logic.
app/(main)/_layout.tsx Removed BrandContextProvider import.
app/(modal)/create-collaboration.tsx Updated imports, modified state management, and restructured UI for collaboration creation.
app/(modal)/create-collaboration.web.tsx Removed the entire component file.
app/(onboarding)/onboarding-brand-preference.tsx Updated button modes and properties, maintaining logic for user preferences.
app/(onboarding)/onboarding-get-started.tsx Rearranged imports, updated button properties, and modified error handling.
app/(onboarding)/onboarding-your-brand.tsx Replaced TouchableOpacity with Pressable, updated placeholder colors, and removed Toast.
app/(public)/pre-signin.tsx Updated button structure for "Skip" functionality, removed unused imports.
components/BottomSheetActions.tsx Updated error handling and UI spacing adjustments.
components/FilterModal.tsx Updated imports and added visibility control for the Bottom Sheet.
components/InfluencerCard.tsx Refactored state management, updated rendering logic, and replaced components for UI consistency.
components/SearchComponent.tsx Replaced TouchableOpacity with Pressable, updated styles for dynamic theming.
components/channel/channel-list.tsx Adjusted padding and updated Searchbar styles.
components/collaboration/CollaborationCard.tsx Updated imports, removed local state, and modified rendering logic.
components/collaboration/collaboration-details/ApplicationsTabContent.tsx Renamed component and updated rendering logic for empty states.
components/collaboration/collaboration-details/InvitationsTabContent.tsx Renamed component and streamlined state management.
components/collaboration/collaboration-details/OverviewTabContent.tsx New component added for displaying collaboration details.
components/collaboration/collaboration-details/SettingsTabContent.tsx New component added for settings placeholder.
components/collaboration/collaboration-details/index.tsx New component added for managing collaboration details with tabs.
components/collaboration/create-collaboration/CreateCollaborationMap.tsx New component added for map functionality in collaboration creation.
components/collaborations/index.tsx Updated tab management to use TopTabNavigation for improved organization.
components/drawer-layout/BrandItem.tsx Replaced IconButton with Pressable and updated icon usage.
components/drawer-layout/DrawerMenuContent.tsx Updated layout and icon usage for menu items.
components/drawer-layout/DrawerMenuItem.tsx Updated icon property type for better type safety.
components/explore-influencers/index.tsx Enhanced layout and theming capabilities for influencer exploration.
components/notifications/index.tsx Restructured return statement for improved layout and handling of notifications.
components/notifications/notification-icon.tsx Updated icon rendering to use FontAwesome.
components/proposals/Applications.tsx Updated rendering logic for proposals with EmptyState.
components/proposals/Invitations.tsx Enhanced display logic for invitations with EmptyState.
components/ui/brand-switcher/index.tsx Replaced icon component for brand switcher button.
components/ui/carousel/carousel.tsx New component added for native carousel implementation.
components/ui/carousel/carousel.web.tsx New component added for web carousel implementation.
components/ui/carousel/render-media-item.tsx New component added for rendering media items in carousel.
components/ui/empty-state/index.tsx Updated props for EmptyState to enhance flexibility.
components/ui/menu-icon/index.tsx Updated icon rendering to use FontAwesome.
components/ui/modal/DocumentUploadModal.tsx Updated button usage to use react-native-paper.
components/ui/modal/ImageUploadModal.tsx Updated button usage to use react-native-paper.
components/ui/select/index.tsx New component added for item selection with support for multi-selection.
components/ui/tag/index.tsx New component added for tag representation.
components/ui/top-tab-navigation/index.tsx New component added for top tab navigation.
constants/Colors.ts Updated color constants for dark and light themes.
constants/CreateCollaborationForm.ts Added new constant arrays for collaboration types, promotion types, and platform types.
constants/Influencers.ts Added unique IDs to influencer objects.
constants/Themes/Theme.ts Restructured color properties within the theme.
hooks/request/index.ts Added export for useInfluencers hook.
hooks/request/use-influencers.tsx New hook added for managing influencer data fetching.
layouts/app-layout/index.tsx Added Toast component for notifications in the layout.
package.json Added Font Awesome dependencies and updated react-native-svg version.
styles/CollaborationCard.styles.tsx Modified styles for CollaborationCard.
styles/FilterModal.styles.tsx Adjusted padding properties in FilterModal.
styles/InfluencerCard.styles.tsx Updated styles for InfluencerCard.
styles/NotificationCard.styles.tsx Enhanced layout and spacing for notification cards.
styles/Proposal.styles.tsx Updated color assignment for titleActive style.
styles/brand-item/BrandItem.styles.tsx Adjusted padding properties in BrandItem styles.
styles/collaboration-details/CollaborationDetails.styles.tsx Removed and updated styles for collaboration details.
styles/collaboration-details/CollaborationHeader.styles.tsx New styles defined for collaboration header.
styles/empty-state/EmptyState.styles.tsx Modified layout and removed action styling from EmptyState.
styles/forget-password.styles.tsx Removed background color and text color from button styles.
styles/login.styles.tsx Commented out button background and text color properties.
styles/modal/UploadModal.styles.tsx Added new styles for button and layout in upload modal.
styles/onboarding/brand.styles.tsx Updated border color for autocomplete input.
styles/onboarding/preference.styles.tsx Removed color property from submit button label style.
styles/signup.styles.tsx Removed dynamic color assignment for button styles.
styles/tab1.styles.tsx Renamed skip button style and removed associated properties.
styles/tag/Tag.styles.tsx New styles defined for tag component.
styles/top-tab-navigation/TopTabNavigation.styles.tsx New styles defined for top tab navigation component.
utils/conversion.ts New utility function for converting numbers to 'k' units.
utils/url.ts New utility function for handling image URLs.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant Backend

    User->>App: Sign Up
    App->>Backend: Create Account
    Backend-->>App: Account Created
    App-->>User: Show Confirmation
Loading

Possibly related PRs

  • added firebase auth #7: Modifies create-new-account.tsx by removing the Toast component, indicating a direct relationship in notification handling.
  • bug fixes #10: Involves UI updates in InfluencerCard, affecting user interactions similar to changes in create-new-account.tsx.
  • fixed ui changes #13: Focuses on UI improvements in create-new-account.tsx, aligning with the main PR's user experience enhancements.
  • Bug fix/UI feedback color changes #20: Modifies routing logic, indirectly relating to user experience improvements aimed at in the main PR.
  • bug fixes #22: Changes in onboarding-brand-preference.tsx, part of the onboarding flow similar to changes in user sign-up processes.
  • Carousel for web #30: Involves UI improvements in InfluencerCard, indicating ongoing enhancements in user interface components.

Suggested reviewers

  • Manan-Sharma-5

Poem

🐇 In a world of code, we hop and play,
With buttons and screens, we pave the way.
Toasts are gone, but joy remains,
Simplified paths, like gentle rains.
Collaboration blooms, and styles align,
In this coding garden, everything's fine! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 66

🧹 Outside diff range and nitpick comments (124)
utils/conversion.ts (1)

1-6: Consider enhancing for broader application usage

Since this is a utility function used across components, consider these improvements:

  1. Support for larger units (M, B)
  2. Configurable decimal places
  3. Explicit return type
-export const convertToKUnits = (num: number) => {
+export const convertToKUnits = (
+  num: number,
+  decimalPlaces: number = 1
+): string => {
+  if (!Number.isFinite(num)) return 'N/A';
+  
+  const units = ['', 'k', 'M', 'B'];
+  const absNum = Math.abs(num);
+  const unitIndex = absNum === 0 ? 0 : Math.floor(Math.log10(absNum) / 3);
+  
+  if (unitIndex === 0) return num.toString();
+  
+  const sign = num < 0 ? '-' : '';
+  const value = absNum / Math.pow(1000, unitIndex);
+  return `${sign}${value.toFixed(decimalPlaces)}${units[unitIndex]}`;
 };
styles/tag/Tag.styles.tsx (3)

1-3: Consider using type imports for better type safety

Since Theme is a type, it should be imported using the type keyword to ensure it's removed during compilation and to make the type dependencies explicit.

import { StyleSheet } from "react-native";
-import { Theme } from "@react-navigation/native";
+import type { Theme } from "@react-navigation/native";
import Colors from "@/constants/Colors";

5-16: Add TypeScript return type annotation for better type safety

The stylesFn function should have an explicit return type annotation for better type safety and documentation.

-export const stylesFn = (theme: Theme) => StyleSheet.create({
+export const stylesFn = (theme: Theme): ReturnType<typeof StyleSheet.create> => StyleSheet.create({

12-15: Consider extracting magic numbers to constants

The font size and border radius values are hardcoded. Consider extracting these to a constants file or theme configuration for better maintainability and consistency across the application.

 tagText: {
-  fontSize: 12,
+  fontSize: theme.fonts?.regular?.fontSize ?? 12,
   color: Colors(theme).tagForeground,
+  flexShrink: 1,
 },
components/ui/tag/index.tsx (3)

5-8: Consider adding prop types documentation

While the component inherits ChipProps, adding JSDoc comments would improve component discoverability and usage understanding.

+/**
+ * A themed tag component wrapping react-native-paper's Chip
+ * @param {ChipProps} props - All props supported by react-native-paper's Chip component
+ */
const Tag: React.FC<ChipProps> = ({

13-19: Consider memoizing the component for performance

Since this is a UI component that might be rendered frequently in lists or grids, consider wrapping it with React.memo to prevent unnecessary re-renders.

-const Tag: React.FC<ChipProps> = ({
+const Tag: React.FC<ChipProps> = React.memo(({
   children,
   ...props
-}) => {
+}) => {
   const theme = useTheme();
   const styles = stylesFn(theme);

   return (
     <Chip
       style={styles.tag}
       textStyle={styles.tagText}
       {...props}
     >
       {children}
     </Chip>
   );
-};
+});

14-16: Consider making styles customizable

The component could be more flexible by allowing style overrides while maintaining default themed styles.

 <Chip
-  style={styles.tag}
-  textStyle={styles.tagText}
+  style={[styles.tag, props.style]}
+  textStyle={[styles.tagText, props.textStyle]}
   {...props}
 >
styles/Proposal.styles.tsx (1)

19-19: Great improvement using theme-based color!

Replacing the hardcoded RGB value with Colors(theme).primary enhances maintainability and consistency with the theming system.

This change promotes better maintainability by:

  • Centralizing color management
  • Supporting dynamic theme changes
  • Ensuring consistent color usage across the application
styles/brand-item/BrandItem.styles.tsx (1)

15-15: LGTM! Consider documenting the padding increase

The increased vertical padding (12px) improves component spacing and touch targets. Consider adding a comment explaining the rationale for future maintainers.

    borderBottomColor: Colors(theme).aliceBlue,
    paddingLeft: 14,
    paddingRight: 8,
+   // Increased padding for better touch targets and visual spacing
    paddingVertical: 12,
styles/empty-state/EmptyState.styles.tsx (1)

20-21: Consider using responsive dimensions for different screen sizes.

While the fixed maximum dimensions work well, you might want to consider using responsive values (e.g., percentage of screen width) for better adaptability across different device sizes.

   image: {
     borderRadius: 10,
-    maxWidth: 256,
-    maxHeight: 256,
+    maxWidth: '70%',
+    maxHeight: 256,
   },
utils/url.ts (1)

3-6: Enhance URL validation logic.

The current URL validation is basic and might allow invalid URLs. Consider using a more robust URL validation approach.

   if (
     image &&
     typeof image === "string" &&
-    (image.startsWith("http") || image.startsWith("ph://"))
+    (
+      /^https?:\/\/.+/.test(image) || 
+      /^ph:\/\/.+/.test(image)
+    )
   ) {
constants/Themes/Theme.ts (1)

18-20: Consider expanding the elevation system

The current elevation system only defines level1. For a more comprehensive Material Design implementation, consider adding more elevation levels.

 elevation: {
   level1: Colors(theme).white,
+  level2: Colors(theme).white,
+  level3: Colors(theme).white,
+  level4: Colors(theme).white,
+  level5: Colors(theme).white,
 },

This would provide more flexibility for different surface elevations in your UI components.

components/collaborations/index.tsx (3)

1-5: Consider using absolute imports consistently.

The relative import path ../ui/top-tab-navigation could be replaced with an absolute import @/components/ui/top-tab-navigation to maintain consistency with other imports.

-import TopTabNavigation from "../ui/top-tab-navigation";
+import TopTabNavigation from "@/components/ui/top-tab-navigation";

7-18: Consider optimizing component rendering and adding type safety.

  1. Directly instantiating components in the tabs configuration might cause unnecessary re-renders.
  2. Adding TypeScript interfaces would improve type safety and maintainability.

Consider this improvement:

interface Tab {
  id: string;
  title: string;
  component: React.ComponentType;
}

const tabs: Tab[] = [
  {
    id: "Active",
    title: "Active",
    component: Applications,
  },
  {
    id: "Past",
    title: "Past",
    component: Invitations,
  },
];

// In TopTabNavigation, render the component like:
// const Component = tab.component;
// return <Component />;

20-34: Implementation looks good with minor suggestions.

The component is well-structured and follows React best practices. Consider these minor improvements:

  1. Add proper prop types definition for the component
  2. Consider using theme-based spacing instead of hardcoded padding values

Example improvement:

interface CollaborationsProps {
  // Add any props if needed in the future
}

const Collaborations: React.FC<CollaborationsProps> = () => {
  return (
    <AppLayout>
      <View
        style={{
          flex: 1,
          paddingTop: theme.spacing.medium, // Use theme-based spacing
        }}
      >
        <TopTabNavigation tabs={tabs} />
      </View>
    </AppLayout>
  );
};
components/contracts/index.tsx (2)

1-4: Consider adding TypeScript interface for component props

The imports look good, but since this is a TypeScript file, it would be beneficial to define explicit types for the component's props (if any are planned to be added in the future).

interface ContractsProps {
  // Add any future props here
}

22-24: Implement contract list view

The current implementation for displaying contracts is a placeholder. Consider implementing a proper list view with contract details.

Would you like me to help create a basic contract list implementation with proper TypeScript types and styling?

styles/NotificationCard.styles.tsx (1)

16-19: Consider shadow visibility impact

While the padding and border radius changes improve the card's appearance, setting shadowColor to transparent removes the visual depth. This might affect:

  • Visual hierarchy
  • Card distinction from background
  • Accessibility (visual separation)

Consider maintaining a subtle shadow for better visual distinction.

-    shadowColor: Colors(theme).transparent,
+    shadowColor: Colors(theme).text,
+    shadowOpacity: 0.1,
+    shadowOffset: { width: 0, height: 2 },
+    shadowRadius: 4,
+    elevation: 3, // for Android
layouts/app-layout/index.tsx (1)

27-27: Consider Toast positioning and z-index handling.

While centralizing Toast in AppLayout is a good architectural decision, placing it within SafeAreaView might cause positioning issues on some devices, especially with full-screen modals or keyboards.

Consider these improvements:

  1. Move Toast outside SafeAreaView to ensure it's always visible
  2. Add appropriate z-index styling
const AppLayout: React.FC<AppLayoutProps> = ({ children }) => {
  const theme = useTheme();
  const isAndroid = useMemo(() => Platform.OS === "android", []);

  return (
-   <SafeAreaView
-     style={[
-       styles.container,
-       {
-         backgroundColor: Colors(theme).background,
-         paddingTop: isAndroid ? StatusBar.currentHeight : 0,
-       },
-     ]}
-   >
-     {children}
-     <ExpoStatusBar style={!theme.dark ? "dark" : "light"} />
-     <Toast />
-   </SafeAreaView>
+   <>
+     <SafeAreaView
+       style={[
+         styles.container,
+         {
+           backgroundColor: Colors(theme).background,
+           paddingTop: isAndroid ? StatusBar.currentHeight : 0,
+         },
+       ]}
+     >
+       {children}
+       <ExpoStatusBar style={!theme.dark ? "dark" : "light"} />
+     </SafeAreaView>
+     <Toast topOffset={isAndroid ? StatusBar.currentHeight : 0} />
+   </>
  );
};
app/(main)/(screens)/collaboration-details/[pageID].tsx (1)

9-10: Consider creating a typed variable for pageID

To improve type safety and reduce repetition, consider extracting the type-cast pageID into a variable.

  const [isVisible, setIsVisible] = useState(false);
- const pageID = useLocalSearchParams().pageID;
+ const { pageID } = useLocalSearchParams();
+ const typedPageID = pageID as string;

Then use typedPageID in the component props to avoid repeated type casting.

styles/collaboration-details/CollaborationHeader.styles.tsx (2)

5-10: Consider extracting magic numbers to constants.

While the styles are well-structured, consider extracting the hardcoded values (16, 600) to named constants. This would improve maintainability and make it easier to maintain consistent spacing across the app.

+const SPACING = {
+  DEFAULT: 16,
+  CONTAINER_MAX_WIDTH: 600,
+};
+
 export const stylesFn = (theme: Theme) => StyleSheet.create({
   container: {
-    paddingHorizontal: 16,
-    paddingBottom: 16,
-    maxWidth: 600,
+    paddingHorizontal: SPACING.DEFAULT,
+    paddingBottom: SPACING.DEFAULT,
+    maxWidth: SPACING.CONTAINER_MAX_WIDTH,
   },

25-38: Consider using typography constants for better consistency.

While the theme-aware colors are good, consider:

  1. Using a typography system with semantic constants for font sizes
  2. Using semantic font weights (e.g., 'bold' instead of '600') for better readability
+const TYPOGRAPHY = {
+  HEADING: 18,
+  BODY: 14,
+};

 title: {
-  fontSize: 18,
-  fontWeight: '600',
+  fontSize: TYPOGRAPHY.HEADING,
+  fontWeight: 'bold',
   color: Colors(theme).text,
 },
components/ui/menu-icon/index.tsx (2)

Line range hint 2-2: Remove unused FontAwesome import

The FontAwesome import from @expo/vector-icons is no longer used after switching to @fortawesome/react-native-fontawesome.

-import { FontAwesome } from "@expo/vector-icons";

Also applies to: 7-8


23-26: Consider adding accessibility label

The icon implementation looks good, but since this is a navigation element, consider adding an accessibility label for screen readers.

 <FontAwesomeIcon
   color={Colors(theme).text}
   icon={faNavicon}
   size={24}
+  accessibilityLabel="Open menu"
   style={{
     zIndex: 0,
     opacity: pressed ? 0.5 : 1,
   }}
 />
styles/CollaborationCard.styles.tsx (1)

51-52: LGTM! Modern spacing approach

Using the gap property is a cleaner approach to spacing elements compared to individual margins. However, consider adding a comment explaining the spacing values for better maintainability.

 chipRow: {
   flexDirection: "row",
   flexWrap: "wrap",
+  // Vertical spacing from other elements
   marginTop: 12,
+  // Consistent spacing between chips
   gap: 16,
 },
styles/top-tab-navigation/TopTabNavigation.styles.tsx (4)

1-5: Consider adding type definition for Colors utility.

The Colors utility is imported but its type is not explicitly defined. Consider adding a type definition to improve type safety and documentation.

+// Add to a types file or above the import
+type ColorUtility = (theme: Theme) => Record<string, string>;
 import Colors from "@/constants/Colors";

6-19: Consider using dimension constants for better maintainability.

The styles use hardcoded values for dimensions and padding. Consider:

  1. Using dimension constants for better maintainability
  2. Ensuring consistent padding values (8 vs 24)
+// Add to a constants file
+const SPACING = {
+  DEFAULT: 8,
+  LARGE: 24,
+};
+const DIMENSIONS = {
+  TAB_SCROLL_HEIGHT: 68,
+};

 tabScroll: {
-  maxHeight: 68,
-  padding: 8,
+  maxHeight: DIMENSIONS.TAB_SCROLL_HEIGHT,
+  padding: SPACING.DEFAULT,
   paddingTop: 0,
 },
 tabScrollContainer: {
-  paddingLeft: 8,
-  paddingRight: 24,
+  paddingLeft: SPACING.DEFAULT,
+  paddingRight: SPACING.LARGE,
 },

20-34: Review positioning and border radius consistency.

A few observations about the styles:

  1. position: 'relative' seems unnecessary without any absolutely positioned children
  2. Border radius values are inconsistent (15 for container, 10 for tabs)
+const BORDER_RADIUS = {
+  LARGE: 15,
+  MEDIUM: 10,
+};

 tabContainer: {
   flexDirection: 'row',
   gap: 8,
   paddingHorizontal: 8,
   paddingVertical: 8,
-  borderRadius: 15,
+  borderRadius: BORDER_RADIUS.LARGE,
   backgroundColor: theme?.dark ? Colors(theme).card : Colors(theme).aliceBlue,
-  position: 'relative',
 },
 tab: {
   paddingHorizontal: 24,
   paddingVertical: 8,
   justifyContent: 'center',
-  borderRadius: 10,
+  borderRadius: BORDER_RADIUS.MEDIUM,
 },

35-42: Enhance typography consistency and active state visibility.

Consider:

  1. Using typography constants for consistent font sizes and weights
  2. Adding more visual emphasis to the active state (e.g., font weight)
+const TYPOGRAPHY = {
+  SIZES: {
+    REGULAR: 16,
+    SMALL: 14,
+  },
+  WEIGHTS: {
+    MEDIUM: '500',
+    BOLD: '700',
+  },
+};

 tabText: {
-  fontSize: 16,
+  fontSize: TYPOGRAPHY.SIZES.REGULAR,
   color: Colors(theme).primary,
-  fontWeight: '500',
+  fontWeight: TYPOGRAPHY.WEIGHTS.MEDIUM,
 },
 activeTabText: {
   color: Colors(theme).white,
+  fontWeight: TYPOGRAPHY.WEIGHTS.BOLD,
 },
constants/Colors.ts (1)

28-31: Consider refactoring shared color values.

The light theme implementation could be improved:

  1. Similar to dark theme, primary and onSurface share the same value (#054463).
  2. The tag colors are correctly inverted from dark theme, but consider extracting these repeated values into named constants.

Consider refactoring shared values:

+ const TAG_LIGHT = "#f1f3f4";
+ const TAG_DARK = "#5f6368";
+ const PRIMARY_LIGHT = "#054463";
+ const PRIMARY_DARK = "#538BA6";

  export default (theme: Theme) => ({
    ...(theme.dark
      ? {
-         primary: "#538BA6",
-         onSurface: "#538BA6",
-         tag: "#5f6368",
-         tagForeground: "#f1f3f4",
+         primary: PRIMARY_DARK,
+         onSurface: PRIMARY_DARK,
+         tag: TAG_DARK,
+         tagForeground: TAG_LIGHT,
      }
      : {
-         primary: "#054463",
-         onSurface: "#054463",
-         tag: "#f1f3f4",
-         tagForeground: "#5f6368",
+         primary: PRIMARY_LIGHT,
+         onSurface: PRIMARY_LIGHT,
+         tag: TAG_LIGHT,
+         tagForeground: TAG_DARK,
      })
components/ui/carousel/carousel.web.tsx (4)

1-7: Consider importing and using proper types for data props

The component uses any type which reduces type safety. Consider defining proper types for the data structure.

+import { MediaItem } from '@/types/media';  // Adjust the import path as needed

 interface CarouselWebProps {
-  data: any
+  data: MediaItem[]
   onImagePress: (uri: string) => void;
 }

19-20: Improve ref typing and consider cleanup

The video refs could benefit from more specific typing and cleanup on unmount.

-  const videoRefs = useRef<{ [key: number]: any }>({});
+  const videoRefs = useRef<{ [key: number]: HTMLVideoElement | null }>({});
+
+  useEffect(() => {
+    return () => {
+      // Cleanup video refs on unmount
+      Object.values(videoRefs.current).forEach(videoRef => {
+        if (videoRef) {
+          videoRef.pause();
+        }
+      });
+    };
+  }, []);

22-26: Remove redundant null check

The null check for onImagePress is unnecessary as TypeScript ensures the prop is provided.

 const handleImagePress = (uri: string) => {
-  if (onImagePress) {
-    onImagePress(uri);
-  }
+  onImagePress(uri);
 };

13-57: Consider performance optimizations

A few architectural suggestions:

  1. Memoize the RenderMediaItem component to prevent unnecessary re-renders
  2. Consider lazy loading for videos that are not in the current view
  3. Add swiper callbacks to pause/play videos when sliding
+const MemoizedRenderMediaItem = React.memo(RenderMediaItem);
+
 const CarouselWeb: React.FC<CarouselWebProps> = ({
   // ... props
 }) => {
   // ... existing code
+
+  const handleIndexChanged = (index: number) => {
+    // Pause all videos except current
+    Object.entries(videoRefs.current).forEach(([key, video]) => {
+      if (video && Number(key) !== index) {
+        video.pause();
+      }
+    });
+  };
+
   return (
     <Swiper
       // ... existing props
+      onIndexChanged={handleIndexChanged}
     >
       {data.map((item, index) => (
-        <RenderMediaItem
+        <MemoizedRenderMediaItem
           // ... props
         />
       ))}
     </Swiper>
   );
 };
components/notifications/notification-icon.tsx (1)

Line range hint 3-3: Remove unused import

The FontAwesome import from "@expo/vector-icons" is no longer used after switching to FontAwesomeIcon.

-import { FontAwesome } from "@expo/vector-icons";
components/ui/empty-state/index.tsx (3)

15-15: Consider using a more specific type for the style prop

Using any type reduces type safety. Consider using ViewStyle or StyleProp<ViewStyle> from React Native.

-  style?: any;
+  style?: StyleProp<ViewStyle>;

44-47: Consider the style spreading order

The current style spreading order might not allow proper style overrides. Consider moving the base styles last to ensure custom styles take precedence.

      style={[
-       styles.container,
        style,
+       styles.container,
      ]}

51-56: Consider using typed dimensions for Image component

The width and height props should be properly typed, and consider making them configurable through props for better reusability.

+type EmptyStateProps = {
+  imageWidth?: number;
+  imageHeight?: number;
+  // ... other props
+};

  <Image
    source={imageUrl(image)}
-   width={256}
-   height={256}
+   width={imageWidth ?? 256}
+   height={imageHeight ?? 256}
    style={styles.image}
  />
styles/tab1.styles.tsx (1)

16-19: Consider adding JSDoc comments for the style

Since this style is part of what appears to be an onboarding/tutorial UI, consider adding documentation to explain its purpose and expected usage.

+    /**
+     * Container for the skip button positioned at the top-right corner
+     * of the onboarding/tutorial screen.
+     */
     skipButtonContainer: {
       position: "absolute",
       top: 10,
       right: 20,
     },
components/drawer-layout/DrawerMenuItem.tsx (2)

Line range hint 27-27: Remove or justify the @ts-ignore comment

The presence of @ts-ignore suggests a potential type issue that should be addressed rather than suppressed. Could you investigate why this is needed and either fix the underlying type issue or add a comment explaining why it's necessary?


42-53: Consider simplifying icon styling

The icon has both a size prop and a style with width. Since size already controls the icon dimensions, the additional width style might be redundant.

Consider this simplified version:

 <FontAwesomeIcon
   icon={tab.icon}
   color={
     tab.href.includes(pathname)
       ? Colors(theme).white
       : Colors(theme).gray100
   }
   size={28}
-  style={{
-    width: 32,
-  }}
 />
components/collaboration/CollaborationHeader.tsx (1)

13-63: Optimize component performance with memoization

The component could benefit from memoization to prevent unnecessary re-renders.

Consider applying these optimizations:

-const CollaborationHeader: React.FC<ColloborationHeaderProps> = ({
+const CollaborationHeader: React.FC<ColloborationHeaderProps> = React.memo(({
   collaboration,
-}) => {
+}) => {
   const theme = useTheme();
   const styles = stylesFn(theme);
   
   return (
     // ... existing JSX
   );
-};
+});

Also, consider extracting the tags section into a separate memoized component if this component re-renders frequently.

components/ui/brand-switcher/index.tsx (1)

40-43: Remove redundant color styling

The color is currently defined twice - both in the color prop and in the style object. Since FontAwesomeIcon already handles color through its dedicated prop, the style-based color definition is redundant.

 <FontAwesomeIcon
   color={Colors(theme).text}
   icon={faRightLeft}
   size={24}
   style={{
     marginLeft: 14,
-    color: Colors(theme).text,
     marginBottom: -2,
   }}
 />
constants/Influencers.ts (2)

Line range hint 1-56: Add TypeScript interfaces for better type safety

The data structure is complex but lacks type definitions. Consider adding TypeScript interfaces to ensure type safety and better code maintainability.

Add these type definitions at the beginning of the file:

interface Media {
  type: 'video' | 'image';
  uri: string;
}

interface Influencer {
  id: string;
  name: string;
  handle: string;
  followers: number;
  reach: number;
  rating: string;
  bio: string;
  jobsCompleted: number;
  successRate: string;
  profilePic: string;
  collaborationType: 'Paid' | 'Sponsored';
  engagement: number;
  media: Media[];
}

export const influencers: Influencer[] = [
  // ... existing data
];

Line range hint 1-56: Consider moving sample data to a separate file

This appears to be sample/mock data in a constants file. Consider:

  1. Moving this data to a dedicated mock data file (e.g., mocks/influencerData.ts)
  2. Using environment variables or configuration files for production data
  3. Adding a comment indicating this is sample data if it's meant for development
styles/InfluencerCard.styles.tsx (1)

21-33: Consider extracting common spacing values

The layout changes look good, but consider extracting common values like padding and gap sizes into theme constants for better maintainability.

+ // In your theme constants file
+ export const spacing = {
+   small: 8,
+   medium: 16,
+   gap: {
+     small: 2,
+     medium: 10
+   }
+ };

  content: {
-     paddingTop: 8,
-     paddingHorizontal: 16,
+     paddingTop: spacing.small,
+     paddingHorizontal: spacing.medium,
  },
styles/collaboration-details/CollaborationDetails.styles.tsx (1)

23-26: LGTM! Consider responsive sizing for different screen sizes.

The profile image styling changes look good, with proper spacing and rounded corners that create a card-like appearance.

Consider using responsive sizing for the height to ensure consistent appearance across different device sizes:

-      height: 160,
+      height: '40%',  // or use dynamic calculation based on screen height
components/SearchComponent.tsx (2)

42-53: Consider adding press feedback states and accessibility improvements

While the Pressable implementation is correct, it could benefit from visual feedback states and accessibility improvements.

Consider this enhancement:

 <Pressable
   onPress={() => {
     if (ToggleModal) ToggleModal(true);
   }}
   style={styles.filterButton}
+  android_ripple={{ color: 'rgba(255, 255, 255, 0.2)' }}
+  accessibilityRole="button"
+  accessibilityLabel="Filter search results"
+  style={({ pressed }) => [
+    styles.filterButton,
+    pressed && { opacity: 0.8 }
+  ]}
 >
   <FontAwesomeIcon
     color={Colors(theme).white}
     icon={faSliders}
     size={24}
   />
 </Pressable>

69-69: Consider standardizing border radius and padding values

For better maintainability and consistency:

  • The border radius values differ between searchInput (15) and searchContainer (25)
  • The filter button's padding could be simplified

Consider this refinement:

 searchInput: {
   flex: 1,
   fontSize: 16,
-  borderRadius: 15,
+  borderRadius: 25,  // Match container radius
   backgroundColor: Colors(theme).aliceBlue,
 },
 filterButton: {
-  borderRadius: 15,
-  paddingVertical: 16,
-  paddingHorizontal: 18,
+  borderRadius: 25,  // Match container radius
+  padding: 16,      // Simplified padding
   alignItems: "center",

Also applies to: 73-73, 74-74, 75-75

components/notifications/index.tsx (1)

31-36: Minor improvements needed in EmptyState configuration

  1. Consider moving the image path to a constants file for better maintainability
  2. Remove the trailing space in the title prop
  <EmptyState
    hideAction
-   image={require("@/assets/images/illustration2.png")}
+   image={EMPTY_STATE_IMAGES.NO_NOTIFICATIONS}
-   title="You are all caught up! "
+   title="You are all caught up!"
    subtitle="We have no notifications for you today!"
  />
components/collaboration/create-collaboration/CreateCollaborationMap.tsx (3)

20-22: Consider consolidating map region state

Having separate state variables for web and native platforms increases complexity. Consider using a single state variable since both platforms use the same structure.

-const [nativeMapRegion, setNativeMapRegion] = useState(mapRegion);
-const [webMapRegion, setWebMapRegion] = useState(mapRegion);
+const [currentMapRegion, setCurrentMapRegion] = useState(mapRegion);

43-49: Optimize effect dependencies

The current implementation could cause unnecessary re-renders. Consider moving the platform check outside and watching only the relevant state.

+const mapRegion = Platform.OS === 'web' ? webMapRegion : nativeMapRegion;
+
 useEffect(() => {
-  if (Platform.OS === 'web') {
-    onMapLocationChange(webMapRegion);
-  } else {
-    onMapLocationChange(nativeMapRegion);
-  }
-}, [nativeMapRegion, webMapRegion]);
+  onMapLocationChange(mapRegion);
+}, [mapRegion]);

16-77: Consider architectural improvements

To enhance maintainability and performance:

  1. Extract platform-specific logic into custom hooks
  2. Memoize the component to prevent unnecessary re-renders
  3. Consider implementing a map context for deeper component trees

Example implementation:

// hooks/useMapRegion.ts
const useMapRegion = (initialRegion: MapRegion) => {
  const [region, setRegion] = useState(initialRegion);
  
  const handleRegionChange = useCallback((newRegion: MapRegion) => {
    setRegion(newRegion);
  }, []);
  
  return { region, handleRegionChange };
};

// CreateCollaborationMap.tsx
const CreateCollaborationMap = memo(({ mapRegion, onMapRegionChange }: CreateCollaborationMapProps) => {
  const { region, handleRegionChange } = useMapRegion(mapRegion);
  
  useEffect(() => {
    onMapRegionChange(region);
  }, [region, onMapRegionChange]);

  return Platform.OS === 'web' ? <WebMap region={region} onChange={handleRegionChange} /> 
                              : <NativeMap region={region} onChange={handleRegionChange} />;
});
components/ui/carousel/render-media-item.tsx (3)

36-60: Add error handling for image loading

Consider adding error handling and loading states for better user experience.

 <Image
   source={imageUrl(item.url || item.uri)}
   style={[styles.media, { height: height || 250, width: width || "100%" }]}
   resizeMode="stretch"
+  onError={(error) => console.error('Image loading error:', error)}
+  loadingIndicatorSource={require('@/assets/images/placeholder.png')}
 />

69-75: Consider extracting hardcoded values

The fallback video path should be moved to a constants file for better maintainability.

+// In constants/media.ts
+export const DEFAULT_VIDEO_PATH = '@/assets/videos/ForBiggerJoyrides.mp4';

-require("@/assets/videos/ForBiggerJoyrides.mp4")
+require(DEFAULT_VIDEO_PATH)

83-88: Improve video error handling and playback configuration

The current implementation could benefit from:

  1. User-facing error handling
  2. Configurable video playback options

Consider making these properties configurable through props:

+interface RenderMediaItemProps {
+  // ... existing props
+  videoConfig?: {
+    isLooping?: boolean;
+    shouldPlay?: boolean;
+    useNativeControls?: boolean;
+  };
+}

 <Video
   // ... existing props
-  isLooping={false}
-  shouldPlay={false}
-  useNativeControls
+  isLooping={videoConfig?.isLooping ?? false}
+  shouldPlay={videoConfig?.shouldPlay ?? false}
+  useNativeControls={videoConfig?.useNativeControls ?? true}
   onError={(error) => {
-    console.error("Video Error:", error)
+    console.error("Video Error:", error);
+    // Consider adding a callback prop for error handling
+    onVideoError?.(error);
   }}
 />
components/ui/carousel/carousel.tsx (5)

25-25: Improve type safety for video refs

The video refs could benefit from a more specific type definition.

-  const videoRefs = useRef<{ [key: number]: any }>({});
+  const videoRefs = useRef<{ [key: number]: { seek: (time: number) => void } }>({});

43-49: Consider a more concise implementation

The image press handler can be simplified while maintaining the same functionality.

-  const handleImagePress = (uri: string) => {
-    if (!isSwiping) {
-      if (onImagePress) {
-        onImagePress(uri);
-      }
-    }
-  };
+  const handleImagePress = (uri: string) => {
+    if (!isSwiping && onImagePress) {
+      onImagePress(uri);
+    }
+  };

56-56: Consider making the carousel height configurable

The hardcoded height of 250 pixels might not be suitable for all use cases.

+interface CarouselProps {
+  data: CarouselItem[];
+  onImagePress?: (data: CarouselItem) => void;
+  height?: number;
+}

 const CarouselNative: React.FC<CarouselProps> = ({
   data,
   onImagePress,
+  height = 250,
 }) => {
   // ...
   <Carousel
     loop
     width={Dimensions.get("window").width}
-    height={250}
+    height={height}
     // ...
   />

73-73: Remove unnecessary type annotations

The map operation doesn't need explicit any types since the types can be inferred.

-        {data.map((_: any, index: any) => (
+        {data.map((_, index) => (

17-85: Consider performance optimizations

For better performance, especially with large datasets:

  1. Memoize the handleImagePress callback using useCallback
  2. Wrap the RenderMediaItem component with React.memo
+import { useCallback } from 'react';

 const CarouselNative: React.FC<CarouselProps> = ({
   // ...
 }) => {
-  const handleImagePress = (uri: string) => {
+  const handleImagePress = useCallback((uri: string) => {
     if (!isSwiping && onImagePress) {
       onImagePress(uri);
     }
-  };
+  }, [isSwiping, onImagePress]);

   // ... rest of the component
 };

-export default CarouselNative;
+export default React.memo(CarouselNative);
🧰 Tools
🪛 Biome (1.9.4)

[error] 36-36: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

components/ui/select/index.tsx (3)

11-16: Consider improving the value prop type definition

The value prop type could be more specific by using SelectItem[] instead of SelectItem[] | [] since an empty array is already included in SelectItem[].

-  value: SelectItem[] | [];
+  value: SelectItem[];

26-42: Optimize selection handler performance

The current implementation creates multiple array copies. Consider optimizing the multi-select logic:

 const handleSelect = (item: SelectItem) => {
   if (multiselect) {
-    const index = value.findIndex(
-      (selectedItem) => selectedItem.value === item.value,
-    );
-    if (index === -1) {
-      onSelect([...value, item]);
-    } else {
-      onSelect([
-        ...value.slice(0, index),
-        ...value.slice(index + 1),
-      ]);
-    }
+    const isSelected = value.some(selectedItem => selectedItem.value === item.value);
+    onSelect(isSelected 
+      ? value.filter(selectedItem => selectedItem.value !== item.value)
+      : [...value, item]
+    );
   } else {
     onSelect([item]);
   }
 };

18-23: Enhance accessibility and user experience

Consider adding the following improvements:

  1. Accessibility props for screen readers
  2. Loading and error states
  3. Empty state handling

Example implementation:

interface SelectProps {
  items: SelectItem[];
  multiselect?: boolean;
  onSelect: (selectedItems: SelectItem[]) => void;
  value: SelectItem[];
  // Add these props
  isLoading?: boolean;
  error?: string;
  placeholder?: string;
  disabled?: boolean;
  ariaLabel?: string;
}
styles/modal/UploadModal.styles.tsx (2)

58-64: Consider refining the iconButton style properties

The style definition has a few potential improvements:

  • The color property won't affect the button's background. If this is meant for the icon, it should be moved to a separate icon style.
  • marginHorizontal: 0 is redundant as it's the default value.
 iconButton: {
   backgroundColor: Colors(theme).primary,
   borderRadius: 10,
-  marginHorizontal: 0,
-  color: Colors(theme).white,
   padding: 8,
 },
+iconText: {
+  color: Colors(theme).white,
+},

117-119: Consider extracting common spacing values

The spacing values (16, 8) are used multiple times across different styles. Consider extracting these into theme constants for better maintainability.

Example:

// In your theme constants
const spacing = {
  small: 8,
  medium: 16,
} as const;

// Then use them in styles
gap: spacing.medium,
margin: spacing.medium,
borderRadius: spacing.small,
components/ui/modal/DocumentUploadModal.tsx (2)

92-96: Button implementation follows react-native-paper best practices.

The updated Button implementation:

  • Uses the recommended children prop pattern instead of title
  • Properly implements the Material Design "contained" mode
  • Maintains the same functionality

Consider adding a color prop to match your theme:

 <Button
   mode="contained"
+  color={theme.colors.primary}
   onPress={() => setVisible(false)}
 >
   Cancel
 </Button>

Line range hint 31-36: Enhance permission denial handling and user messaging.

The current permission handling could be more user-friendly and provide clearer guidance.

Consider this improvement:

 const openGallery = async () => {
   const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
   if (status !== 'granted') {
-    alert('Media library access is required to select images, videos, or documents');
+    Alert.alert(
+      "Permission Required",
+      "To upload media, please enable access to your library in your device settings.",
+      [
+        { text: "Cancel", style: "cancel" },
+        { text: "Open Settings", onPress: () => Linking.openSettings() }
+      ]
+    );
     return;
   }

Don't forget to add the necessary imports:

import { Alert, Linking } from 'react-native';
components/ui/modal/ImageUploadModal.tsx (2)

103-107: Consider renaming removeImage function to match the Cancel action

The function name removeImage doesn't clearly reflect its usage as a cancel action. This could be confusing for maintainers as the button's label suggests cancellation while the function name suggests image removal.

-  const removeImage = () => {
+  const handleCancel = () => {
     onImageUpload('');
     setVisible(false);
   };

   // ...
   <Button
     mode="contained"
-    onPress={removeImage}
+    onPress={handleCancel}
   >
     Cancel
   </Button>

103-107: Add accessibility props to the Cancel button

To improve accessibility for screen readers, consider adding appropriate accessibility props.

   <Button
     mode="contained"
     onPress={removeImage}
+    accessibilityLabel="Cancel image upload"
+    accessibilityHint="Closes the image upload modal without selecting an image"
   >
     Cancel
   </Button>
components/collaboration/collaboration-details/OverviewTabContent.tsx (3)

24-36: Move inline styles to stylesFn

The ScrollView contains inline styles that should be moved to the stylesFn for better maintainability and reusability. Also, paddingBottom is defined twice in different style objects.

Consider refactoring to:

// In stylesFn
scrollViewContainer: {
  flex: 1,
  paddingTop: 8,
  paddingHorizontal: 16,
  paddingBottom: 16,
},
scrollViewContent: {
  gap: 16,
  paddingBottom: 16,
},

// In component
<ScrollView
  style={styles.scrollViewContainer}
  showsVerticalScrollIndicator={false}
  contentContainerStyle={styles.scrollViewContent}
>

54-55: Remove unnecessary string concatenation

The empty string concatenation {" "} before {collaboration.description} is unnecessary.

-          <Paragraph style={styles.brandName}>
-            {" "}
-            {collaboration.description}
-          </Paragraph>
+          <Paragraph style={styles.brandName}>
+            {collaboration.description}
+          </Paragraph>

1-106: Add accessibility support and test coverage

The component lacks accessibility attributes and test coverage.

Consider:

  1. Adding accessibility labels to interactive elements
  2. Creating a test file (OverviewTabContent.test.tsx) to cover:
    • Rendering with different prop combinations
    • Null/undefined handling
    • User interactions
    • Accessibility features

Would you like me to help generate the test file and accessibility improvements?

app/(public)/pre-signin.tsx (1)

62-73: Add accessibility support and optimize the button implementation

While the Button upgrade aligns with the theme update, consider these improvements:

  1. Add accessibility props for better user experience
  2. Simplify the onPress handler by directly using skipToConnect

Apply this diff:

 <Button
   mode="contained"
-  onPress={() => {
-    skipToConnect();
-  }}
+  onPress={skipToConnect}
+  accessibilityLabel="Skip to connect screen"
+  accessibilityHint="Navigates to the connection options"
 >
   Skip
 </Button>
components/ui/top-tab-navigation/index.tsx (3)

7-14: Enhance type safety and documentation of the interface

Consider improving the interface definition with better type safety and documentation:

+/**
+ * Props for the TopTabNavigation component
+ * @property {Array<{id: string, title: string, component: React.ReactNode}>} tabs - Array of tab configurations
+ * @property {"compact" | "default"} [size="default"] - Size variant of the tabs
+ */
 interface TopTabNavigationProps {
   tabs: {
     id: string;
     title: string;
     component: React.ReactNode;
   }[];
-  size?: "compact" | "default";
+  size?: 'compact' | 'default';  // Using string literals for better type safety
 }

27-29: Consider preserving active tab state across tab updates

The current implementation resets to the first tab whenever tabs change, which might disrupt user experience. Consider preserving the active tab if it still exists in the new tabs array:

 useEffect(() => {
-  setActiveTab(tabs[0]);
+  const currentTabStillExists = tabs.find(tab => tab.id === activeTab.id);
+  setActiveTab(currentTabStillExists || tabs[0]);
 }, [tabs]);

31-45: Simplify renderTabContent function

The current implementation can be simplified by removing unnecessary complexity:

 const renderTabContent = () => (
   <View style={[styles.tabContent]}>
-    {(() => {
-      let content
-      content = activeTab.component;
-      return content;
-    })()}
+    {activeTab.component}
   </View>
 );
components/collaboration/CollaborationCard.tsx (2)

76-84: Consider adding accessibility labels to Tags

While the Tag implementation looks cleaner, consider enhancing accessibility for screen readers.

Add accessibility props to the Tags:

-          <Tag>
+          <Tag accessibilityLabel={`${props.applications} applications`}>
            Applied: {props.applications}
           </Tag>
-          <Tag>
+          <Tag accessibilityLabel={`${props.invitations} invitations`}>
            Invited: {props.invitations}
           </Tag>
-          <Tag>
+          <Tag accessibilityLabel={`${props.acceptedApplications} shortlisted`}>
            Shortlisted: {props.acceptedApplications}
           </Tag>

Line range hint 27-27: Consider renaming JobCard to CollaborationCard for consistency

The component name JobCard doesn't match the file name CollaborationCard.tsx. This could lead to confusion. Consider renaming for better maintainability.

-const JobCard = (props: CollaborationAdCardProps) => {
+const CollaborationCard = (props: CollaborationAdCardProps) => {

-export default JobCard;
+export default CollaborationCard;
components/collaboration/collaboration-details/ApplicationsTabContent.tsx (5)

15-15: Consider adding proper TypeScript interface for props.

Using any type reduces type safety. Consider creating a proper interface for the component props.

-const ApplicationsTabContent = (props: any) => {
+interface ApplicationsTabContentProps {
+  pageID: string;
+  collaboration: any; // TODO: Define proper type
+}
+
+const ApplicationsTabContent = (props: ApplicationsTabContentProps) => {

77-85: Consider moving the image path to constants.

The empty state implementation looks good, but consider moving the image path to a constants file for better maintainability.

+// In constants/images.ts
+export const ILLUSTRATIONS = {
+  NO_APPLICATIONS: require("@/assets/images/illustration6.png")
+};

// In component
-        image={require("@/assets/images/illustration6.png")}
+        image={ILLUSTRATIONS.NO_APPLICATIONS}

Line range hint 95-107: Remove hardcoded values in influencer data.

Several properties appear to use hardcoded values which could be misleading:

  • Default handle "@handle"
  • Hardcoded bio "I am a content creator"
  • Static jobsCompleted and successRate values
              id: item.id,
              profilePic: item.profileImage,
              name: item.name,
-              handle: item.handle || "@handle",
+              handle: item.handle || `@${item.name?.toLowerCase().replace(/\s+/g, '')}`,
              media: item.attachments,
              followers: item.backend ? item.backend.followers : 1000,
              reach: item.backend ? item.backend.reach : 10000,
              rating: item.backend ? item.backend.rating : 4.5,
-              bio: "I am a content creator",
+              bio: item.bio || '',
-              jobsCompleted: 12,
-              successRate: 100,
+              jobsCompleted: item.jobsCompleted || 0,
+              successRate: item.successRate || 0,

121-130: Consider extracting styles and separator component.

The ItemSeparatorComponent and its styles could be extracted for better code organization and reusability.

+const ListSeparator = () => {
+  const theme = useTheme();
+  return (
+    <View
+      style={[
+        styles.separator,
+        {
+          backgroundColor: theme.dark ? Colors(theme).background : Colors(theme).aliceBlue,
+        }
+      ]}
+    />
+  );
+};
+
+const styles = StyleSheet.create({
+  separator: {
+    height: 16,
+  },
+});

// In FlatList
-        ItemSeparatorComponent={() => (...)}
+        ItemSeparatorComponent={ListSeparator}

132-146: Simplify BottomSheetActions rendering and improve props handling.

The current implementation could be simplified and made more type-safe.

-      {
-        isVisible && (
-          <BottomSheetActions
-            cardType="applicationCard"
-            data={{
-              collaboration: props.collaboration
-            }}
-            isVisible={isVisible}
-            onClose={() => setIsVisible(false)}
-            snapPointsRange={["30%", "50%"]}
-            cardId={selectedApplication}
-            key={selectedApplication?.applicationID}
-          />
-        )
-      }
+      <BottomSheetActions
+        cardType="applicationCard"
+        data={{ collaboration: props.collaboration }}
+        isVisible={isVisible}
+        onClose={() => setIsVisible(false)}
+        snapPointsRange={["30%", "50%"]}
+        cardId={selectedApplication}
+        key={selectedApplication?.applicationID}
+      />
app/(main)/(drawer)/(tabs)/_layout.tsx (2)

52-56: Maintain consistent icon sizes across tabs.

The Explore Influencers tab uses a 28px icon while other tabs use 24px. This inconsistency might affect visual harmony.

-              size={28}
+              size={24}

Line range hint 64-73: Remove redundant color style.

The color is defined twice for the drawer toggle icon - both in the color prop and in the style object.

                    color={Colors(theme).text}
                    icon={faRightLeft}
                    size={24}
                    style={{
                      marginLeft: 14,
-                     color: Colors(theme).text,
                      marginBottom: -2,
                    }}
components/explore-influencers/index.tsx (3)

76-85: LGTM: Well-implemented separator with theme support

The separator implementation correctly uses theme context and maintains consistent spacing. Consider adding type safety for the theme parameter.

-backgroundColor: theme.dark ? Colors(theme).background : Colors(theme).aliceBlue,
+backgroundColor: theme.dark 
  ? Colors(theme as Theme).background 
  : Colors(theme as Theme).aliceBlue,

87-96: LGTM: Improved layout consistency

The SearchComponent wrapper improves layout consistency. Consider extracting the padding value 16 to a constant since it's used in multiple places.

+const SPACING = 16;
+
 const ExploreInfluencers = () => {
   // ... existing code ...
   
   return (
     <AppLayout>
       <FlatList
         // ... other props ...
         contentContainerStyle={{
-          paddingTop: 16,
-          paddingBottom: 16,
+          paddingTop: SPACING,
+          paddingBottom: SPACING,
         }}
         ItemSeparatorComponent={() => (
           <View
             style={{
-              height: 16,
+              height: SPACING,
               backgroundColor: theme.dark ? Colors(theme).background : Colors(theme).aliceBlue,
             }}
           />
         )}
         ListHeaderComponent={
           <View
             style={{
-              paddingHorizontal: 16,
+              paddingHorizontal: SPACING,
             }}
           >
             <SearchComponent
               // ... props ...
             />
           </View>
         }
       />
     </AppLayout>
   );
 };

Line range hint 33-35: Clean up or document commented influencer type filtering

There's commented code for isInfluencerTypeMatch. If this feature is planned for future implementation, consider adding a TODO comment with the ticket reference. If it's no longer needed, consider removing it.

components/drawer-layout/DrawerMenuContent.tsx (4)

11-11: Consider virtualizing the scroll view for better performance

The switch to ScrollView might impact performance with large lists. Consider using FlatList or VirtualizedList instead, especially for the brands list view, as these components implement windowing and recycling of list items.

-import { Platform, ScrollView } from "react-native";
+import { Platform, FlatList } from "react-native";

-      <ScrollView
-        style={{
-          flex: 1,
-          gap: 6,
-        }}
-      >
+      <FlatList
+        style={{
+          flex: 1,
+        }}
+        contentContainerStyle={{
+          gap: 6
+        }}
+        data={xl ? DRAWER_MENU_CONTENT_ITEMS : filteredBrands}
+        renderItem={({ item }) => xl ? (
+          <DrawerMenuItem tab={item} />
+        ) : (
+          <BrandItem
+            active={selectedBrand?.id === item.id}
+            image={item.image}
+            key={item.id.toString()}
+            menu={true}
+            onPress={() => handleBrandChange(item)}
+            showImage={true}
+            title={item.name}
+          />
+        )}
+        keyExtractor={(item) => xl ? item.href : item.id.toString()}
+      >

Also applies to: 126-131


Line range hint 156-158: Fix Platform.OS condition in marginBottom style

The Platform.OS check in the marginBottom calculation has a potential syntax error that could lead to unexpected behavior.

-          marginBottom: bottom + Platform.OS === 'android' ? 24 : 44,
+          marginBottom: bottom + (Platform.OS === 'android' ? 24 : 44),

Line range hint 77-86: Consider debouncing the search functionality

The current implementation updates the filtered results on every keystroke, which might cause performance issues with large lists.

Consider using a debounce utility:

import { useMemo } from 'react';
import debounce from 'lodash/debounce';

// Inside component
const debouncedSearch = useMemo(
  () => debounce((text: string) => {
    if (!text) {
      setFilteredBrands(brands);
      return;
    }
    setFilteredBrands(brands.filter(brand => 
      brand.name.toLowerCase().includes(text.toLowerCase())
    ));
  }, 300),
  [brands]
);

const handleSearchChange = (text: string) => {
  setSearch(text);
  debouncedSearch(text);
};
🧰 Tools
🪛 Biome (1.9.4)

[error] 25-26: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


91-92: Consider extracting magic numbers into theme constants

The hardcoded padding and font size values should be moved to a theme configuration for better maintainability and consistency.

+ // In your theme file
+ export const spacing = {
+   headerPaddingTop: {
+     web: 12,
+     native: 64
+   },
+   contentPadding: 24,
+ };
+ export const typography = {
+   headerSize: 24,
+ };

- paddingTop: Platform.OS === 'web' ? 12 : 64,
+ paddingTop: spacing.headerPaddingTop[Platform.OS === 'web' ? 'web' : 'native'],

- paddingHorizontal: 24,
- fontSize: 24,
+ paddingHorizontal: spacing.contentPadding,
+ fontSize: typography.headerSize,

Also applies to: 98-102

app/(onboarding)/onboarding-get-started.tsx (2)

75-75: Enhance error handling with user feedback

While using console.error is better than console.log, consider adding:

  1. User-friendly error messages
  2. Error tracking/monitoring
- console.error(error);
+ console.error('Failed to submit onboarding survey:', error);
+ // Show error message to user
+ showErrorMessage('Something went wrong. Please try again.');
+ // Optional: Track error for monitoring
+ errorTracker.capture(error);

Line range hint 41-77: Consider adding form validation and state management

The survey submission logic could benefit from:

  1. Form validation before submission (all fields required?)
  2. Loading states during submission
  3. Proper state management for the survey data

Consider implementing form validation:

const isFormValid = () => {
  return hearAboutUs && useFor && volumeOfCollaboration;
};

const handleSubmit = async () => {
  if (!isFormValid()) {
    showErrorMessage('Please fill in all fields');
    return;
  }
  // ... rest of the submission logic
};
components/proposals/Invitations.tsx (3)

134-140: Fix typo in EmptyState subtitle

There's a typo in the subtitle text: "woudl" should be "would".

-            subtitle="Start building your profile today to have better reach. If any brand invites you to collaborate we woudl show it here"
+            subtitle="Start building your profile today to have better reach. If any brand invites you to collaborate we would show it here"

193-203: Consider using dynamic snap points

The snap points are currently hardcoded to ["20%", "50%"]. Consider making these dynamic based on screen size or content height for better adaptability across different devices.

-            snapPointsRange={["20%", "50%"]}
+            snapPointsRange={[
+              Math.min(screenHeight * 0.2, contentHeight),
+              Math.min(screenHeight * 0.5, contentHeight)
+            ]}

Line range hint 46-84: Enhance error handling with user feedback

The current error handling only logs to console. Consider adding user feedback for error states.

 } catch (error) {
   console.error("Error fetching proposals: ", error);
+  // Show error feedback to user
+  setError("Failed to fetch proposals. Please try again.");
 } finally {
   setIsLoading(false);
 }
components/proposals/Applications.tsx (2)

Line range hint 25-27: Consider co-locating the bottom sheet state.

The selectedCollabId state is only used by the BottomSheetActions component. Consider moving this state and its handlers into a separate bottom sheet component to improve code organization and reduce the main component's complexity.

- const [isVisible, setIsVisible] = useState(false);
- const [selectedCollabId, setSelectedCollabId] = useState<string | null>(null);

+ const BottomSheetWrapper = ({ children }) => {
+   const [isVisible, setIsVisible] = useState(false);
+   const [selectedCollabId, setSelectedCollabId] = useState<string | null>(null);
+   
+   const openBottomSheet = (id: string) => {
+     setIsVisible(true);
+     setSelectedCollabId(id);
+   };
+   const closeBottomSheet = () => setIsVisible(false);
+   
+   return (
+     <>
+       {children(openBottomSheet)}
+       {isVisible && (
+         <BottomSheetActions
+           cardId={selectedCollabId || ""}
+           cardType="activeCollab"
+           isVisible={isVisible}
+           onClose={closeBottomSheet}
+           snapPointsRange={["20%", "50%"]}
+           key={selectedCollabId}
+         />
+       )}
+     </>
+   );
+ };

Line range hint 44-102: Consider optimizing the data fetching strategy.

The current implementation makes multiple nested Firestore queries for each collaboration, which could lead to performance issues with larger datasets. Consider:

  1. Using composite queries to fetch related data
  2. Implementing pagination
  3. Caching frequently accessed data

Here's a suggested approach using batch operations:

const fetchProposals = async () => {
  if (!selectedBrand) return;
  
  try {
    // 1. Fetch collaborations with pagination
    const BATCH_SIZE = 10;
    const collaborationQuery = query(
      collection(FirestoreDB, "collaborations"),
      where("brandId", "==", selectedBrand?.id),
      orderBy("timeStamp", "desc"),
      limit(BATCH_SIZE)
    );

    // 2. Use batched reads for applications and invitations
    const fetchRelatedData = async (collabId: string) => {
      const batch = FirestoreDB.batch();
      const appRef = collection(FirestoreDB, "collaborations", collabId, "applications");
      const invRef = collection(FirestoreDB, "collaborations", collabId, "invitations");
      return Promise.all([
        getDocs(query(appRef, limit(100))),
        getDocs(query(invRef, limit(100)))
      ]);
    };

    // 3. Process in smaller batches
    const processCollaborations = async (snapshot: QuerySnapshot) => {
      const batchPromises = snapshot.docs.map(async (doc) => {
        const [appSnapshot, invSnapshot] = await fetchRelatedData(doc.id);
        return {
          ...doc.data(),
          id: doc.id,
          applications: appSnapshot.size,
          invitations: invSnapshot.size,
          acceptedApplications: appSnapshot.docs.filter(
            d => d.data().status === "accepted"
          ).length
        };
      });

      return Promise.all(batchPromises);
    };

    const snapshot = await getDocs(collaborationQuery);
    const proposals = await processCollaborations(snapshot);
    setProposals(proposals);
  } catch (error) {
    console.error("Error fetching proposals: ", error);
  } finally {
    setIsLoading(false);
  }
};
app/(onboarding)/onboarding-your-brand.tsx (1)

163-163: Consider moving inline styles to the styles object.

While the implementation is correct, the inline backgroundColor style in the Pressable component could be moved to the styles object for better maintainability and reusability.

// In the styles object
+ pressableItem: {
+   backgroundColor: Colors(theme).background,
+ },

// In the component
- style={{
-   backgroundColor: Colors(theme).background,
- }}
+ style={styles.pressableItem}

Also applies to: 168-179

components/BottomSheetActions.tsx (4)

103-103: Enhance error handling with proper error types and detailed messages

While changing to console.error is good, consider these improvements:

  1. Add proper error typing
  2. Include specific error details in toast messages
  3. Implement error tracking
- console.error(error);
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
+ console.error('Operation failed:', errorMessage);
+ // Consider adding error tracking here
+ Toaster.error(`Failed to complete operation: ${errorMessage}`);

Also applies to: 125-125, 141-141


Line range hint 13-19: Improve type safety by removing 'any' types and @ts-ignore comments

The component has several type safety issues that should be addressed:

  1. The data prop needs proper typing
  2. @ts-ignore comments should be replaced with proper type assertions

Consider defining proper interfaces:

interface CollaborationData {
  collaboration: {
    id: string;
    name: string;
  };
}

interface CardIds {
  collaborationID: string;
  applicationID: string;
  influencerID: string;
}

interface BottomSheetActionsProps {
  cardType: 'influencerType' | 'promotionType' | 'influencerCard' | 'applicationCard' | 'invitationCard' | 'activeCollab';
  data?: CollaborationData;
  cardId?: CardIds;
  isVisible: boolean;
  snapPointsRange: [string, string];
  onClose: () => void;
}

174-174: Consolidate repeated padding styles

The paddingBottom: 28 style is repeated across multiple List.Section components. Consider extracting this to a shared style.

const styles = StyleSheet.create({
  // ... existing styles ...
+ listSection: {
+   paddingBottom: 28,
+ },
});

- <List.Section style={{ paddingBottom: 28 }}>
+ <List.Section style={styles.listSection}>

Also applies to: 198-198, 222-222, 245-245


Line range hint 1-313: Consider breaking down the component and extracting logic

The component handles multiple responsibilities and could benefit from some architectural improvements:

  1. Extract card-specific components to reduce the switch statement complexity
  2. Move async operations to custom hooks
  3. Add loading states for async operations

Consider this structure:

// hooks/useCollaborationActions.ts
export const useCollaborationActions = () => {
  const handleAcceptApplication = async () => { /* ... */ };
  const handleRejectApplication = async () => { /* ... */ };
  const delistCollaboration = async () => { /* ... */ };
  return { handleAcceptApplication, handleRejectApplication, delistCollaboration };
};

// components/CardContents/InfluencerCardContent.tsx
export const InfluencerCardContent = ({ onClose }) => (
  <List.Section style={styles.listSection}>
    {/* ... */}
  </List.Section>
);

// Similar components for other card types
components/FilterModal.tsx (1)

164-166: Consider extracting repeated slider styles

The selectedStyle configuration is duplicated across three MultiSlider components. Consider extracting it to a constant or style object for better maintainability.

+ const sliderSelectedStyle = {
+   backgroundColor: Colors(theme).primary,
+ };

- selectedStyle={{
-   backgroundColor: Colors(theme).primary,
- }}
+ selectedStyle={sliderSelectedStyle}

Also applies to: 189-191, 216-218

hooks/request/use-influencers.tsx (4)

12-12: Specify the type of influencers state for better type safety

Currently, influencers is typed as any[], which bypasses the benefits of TypeScript's static type checking. Defining a specific interface for your influencer data will enhance type safety and reduce potential runtime errors.

Example:

+interface Influencer {
+  id: string;
+  name: string;
+  // Add other influencer properties here
+}

-const [influencers, setInfluencers] = useState<any[]>([]);
+const [influencers, setInfluencers] = useState<Influencer[]>([]);

103-103: Simplify the cleanup function using optional chaining

Instead of unsubscribe && unsubscribe(), you can use optional chaining unsubscribe?.() for a cleaner and more concise syntax.

Apply this diff:

-return () => unsubscribe && unsubscribe();
+return () => unsubscribe?.();
🧰 Tools
🪛 Biome (1.9.4)

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


83-99: Add error handling in checkIfAlreadyInvited

The checkIfAlreadyInvited function performs asynchronous operations but lacks error handling. Incorporating a try-catch block will help manage potential errors during the getDocs call.

Apply this diff:

 const checkIfAlreadyInvited = async (influencerID: string) => {
+  try {
     const invitationsRef = collection(
       FirestoreDB,
       "collaborations",
       pageID,
       "invitations"
     );

     const influencersQuery = query(
       invitationsRef,
       where("userId", "==", influencerID)
     );

     const invitedInfluencer = await getDocs(influencersQuery);

     return invitedInfluencer.docs.length > 0;
+  } catch (error) {
+    console.error("Error checking if influencer is already invited:", error);
+    return false;
+  }
 };

20-48: Assess the necessity of real-time updates in fetchInitialInfluencers

The fetchInitialInfluencers function uses onSnapshot to set up a real-time listener. If real-time updates are not required for the initial influencers list, consider using getDocs to fetch data once. This change can reduce resource consumption and simplify the data fetching logic.

components/collaboration/collaboration-details/index.tsx (4)

63-65: Utilize the collaboration logo if available

The logo prop is currently commented out and an empty string is passed. If the logo is available in the collaboration data, you should use it to enhance the user interface.

Update the OverviewTabContent component props:

          collaboration={collaboration as Collaboration}
-         // logo={collaboration?.logo}
-         logo={""}
+         logo={collaboration?.logo || ""}

74-79: Ensure collaboration object passed to ApplicationsTabContent is complete

You're currently passing an object with id and name properties. If collaboration.name is undefined, name will be undefined. It might be better to ensure that all necessary properties are provided or handle undefined values within the ApplicationsTabContent component.

Consider passing the entire collaboration object if needed:

          pageID={pageID}
-         collaboration={{
-           id: pageID,
-           name: collaboration?.name,
-         }}
+         collaboration={collaboration as Collaboration}

35-35: Remove unnecessary type assertion for pageID

Since pageID is already typed as a string in CollaborationDetailsProps, the type assertion as string is redundant.

Simplify the doc calls:

-     const collabRef = doc(FirestoreDB, "collaborations", pageID as string);
+     const collabRef = doc(FirestoreDB, "collaborations", pageID);
...
-     const brandRef = doc(FirestoreDB, "brands", data.brandId);
+     const brandRef = doc(FirestoreDB, "brands", data.brandId);

100-102: Include fetchCollaboration in the useEffect dependency array or define it inside

The useEffect hook depends on fetchCollaboration, which is defined outside the hook. To prevent potential stale closures or linting warnings, include fetchCollaboration in the dependency array or define it within the useEffect.

Option 1: Include fetchCollaboration in dependencies:

  useEffect(() => {
    fetchCollaboration();
- }, [pageID]);
+ }, [pageID, fetchCollaboration]);

Option 2: Define fetchCollaboration inside the useEffect:

- const fetchCollaboration = async () => {
+ useEffect(() => {
+   const fetchCollaboration = async () => {
      // ... existing code ...
    };
    fetchCollaboration();
- }, [pageID]);
+ }, [pageID]);
components/collaboration/collaboration-details/InvitationsTabContent.tsx (3)

Line range hint 47-72: Use consistent async/await syntax and improve error handling

Mixing async/await with .then() can reduce code readability. It's recommended to use async/await consistently for better error handling and clarity.

Apply this diff to refactor the code:

      setIsInviting(true);
-     await addDoc(invitationRef, invitationPayload).then(() => {
-       setIsMessageModalVisible(false);
-       Toaster.success("Invitation sent successfully");
-     });
+     await addDoc(invitationRef, invitationPayload);
+     setIsMessageModalVisible(false);
+     Toaster.success("Invitation sent successfully");

Consider improving the error message to include the error details:

    } catch (error) {
      console.error(error);
-     Toaster.error("Failed to send invitation");
+     Toaster.error(`Failed to send invitation: ${error.message}`);
    } finally {
      setMessage("");
      setIsInviting(false);
    }

106-107: Avoid clearing influencers state before fetching

Clearing the influencers state with setInfluencers([]); before fetching new data may cause unnecessary UI updates or flicker. Let fetchInitialInfluencers() handle updating the state.

Apply this diff to remove the unnecessary state clearing:

onRefresh={() => {
-   setInfluencers([]);
    fetchInitialInfluencers();
}}

25-25: Specify prop types for InvitationsTabContent component

Currently, props is typed as any. Defining proper prop types enhances code maintainability and type safety.

Consider defining an interface for props:

interface InvitationsTabContentProps {
  pageID: string;
  // Add other prop definitions here
}

const InvitationsTabContent = (props: InvitationsTabContentProps) => {
  // ...
};
components/InfluencerCard.tsx (3)

207-212: Add user interaction to the message icon

The message icon currently does not respond to user interactions. If the intent is to allow users to send messages or initiate chats with the influencer, consider wrapping the icon with a TouchableOpacity and adding an onPress handler.

Apply this diff:

<View style={styles.statItem}>
+   <TouchableOpacity onPress={() => {
+       // Implement message functionality
+       if (props.ToggleMessageModal) {
+           props.ToggleMessageModal();
+       }
+   }}>
        <FontAwesomeIcon
            icon={faMessage}
            color={Colors(theme).primary}
            size={18}
        />
+   </TouchableOpacity>
</View>

173-205: Improve accessibility by adding descriptive labels to icons

For better accessibility, consider adding accessibilityLabel and accessible props to the icons so that screen readers can provide meaningful descriptions.

Apply this diff:

<FontAwesomeIcon
    icon={faUsers}
    color={Colors(theme).primary}
    size={20}
+   accessible={true}
+   accessibilityLabel="Followers"
/>

Repeat for other icons like faBullseye and faStar, providing appropriate labels like "Reach" and "Rating".


215-219: Enhance the bio expansion for better user experience

Currently, tapping on the bio text toggles the expansion. However, if the bio text is short, tapping might not change anything. Consider adding a "Read more" or "Show less" link to indicate that the text can be expanded or collapsed.

Apply this diff:

<TouchableOpacity onPress={() => setBioExpanded(!bioExpanded)}>
    <Text numberOfLines={bioExpanded ? undefined : 2} style={styles.bio}>
        {influencer.bio}
+       {!bioExpanded && influencer.bio.length > 100 ? (
+           <Text style={styles.readMore}> Read more</Text>
+       ) : bioExpanded ? (
+           <Text style={styles.readLess}> Show less</Text>
+       ) : null}
    </Text>
</TouchableOpacity>

You may need to adjust the character limit and style accordingly.

app/(modal)/create-collaboration.tsx (4)

Line range hint 291-303: Validation May Not Detect Empty Selections

In the validation before moving to the next screen, you're checking if promotionType, collabType, and platform are truthy. Since empty arrays are truthy in JavaScript, this check won't detect if the user hasn't made a selection.

Update the validation to check the length of these arrays:

if (
  !collaborationName ||
  !aboutCollab ||
  !budgetMin ||
  !budgetMax ||
  !numInfluencers ||
-  !promotionType ||
-  !collabType ||
-  !platform
+  promotionType.length === 0 ||
+  collabType.length === 0 ||
+  platform.length === 0
) {
  Toaster.error("Please fill all fields");
  return;
}

346-366: Consider Using 'Select' Component for Location Selection

For consistency with the rest of the form, consider replacing the RadioButton.Group for the Location field with the Select component.

This will provide a uniform user experience and maintain consistency across the form inputs.

-<RadioButton.Group
-  onValueChange={(newValue) => setLocation(newValue)}
-  value={location}
->
-  <RadioButton.Item label="Remote" value="Remote" ... />
-  <RadioButton.Item label="Physical" value="Physical" ... />
-</RadioButton.Group>
+<Select
+  items={[
+    { label: "Remote", value: "Remote" },
+    { label: "Physical", value: "Physical" },
+  ]}
+  onSelect={(selectedItems) => setLocation(selectedItems[0].value)}
+  value={[{ label: location, value: location }]}
+/>

131-131: Address the TODO Comment for Location Name

There's a TODO comment indicating that the location name should be added using a geocoding API:

// TODO: Add location name using geocoding API

Would you like assistance in implementing the geocoding API to retrieve the location name based on the selected coordinates? I can help integrate a geocoding service like Google Maps API or OpenStreetMap.


388-393: Enhance Link Management with Edit and Delete Options

Currently, the added links are displayed as plain text without options to edit or remove them:

links.map((link, index) => (
  <Paragraph key={index}>
    {link.name}: {link.url}
  </Paragraph>
))

Consider enhancing the user experience by displaying the links in a list with options to edit or delete individual links. This will provide users with more control over the links they include.

Example implementation:

links.map((link, index) => (
  <View key={index} style={styles.linkItem}>
    <Paragraph>{link.name}: {link.url}</Paragraph>
    <IconButton
      icon="pencil"
      onPress={() => handleEditLink(index)}
    />
    <IconButton
      icon="delete"
      onPress={() => handleDeleteLink(index)}
    />
  </View>
))

You'll need to implement handleEditLink and handleDeleteLink functions to manage link editing and deletion.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between f92332d and cc9b00c.

⛔ Files ignored due to path filters (7)
  • assets/images/illustration1.png is excluded by !**/*.png
  • assets/images/illustration2.png is excluded by !**/*.png
  • assets/images/illustration3.png is excluded by !**/*.png
  • assets/images/illustration4.png is excluded by !**/*.png
  • assets/images/illustration5.png is excluded by !**/*.png
  • assets/images/illustration6.png is excluded by !**/*.png
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (77)
  • app/(auth)/create-new-account.tsx (1 hunks)
  • app/(auth)/forget-password.tsx (0 hunks)
  • app/(auth)/login.tsx (0 hunks)
  • app/(main)/(drawer)/(tabs)/_layout.tsx (6 hunks)
  • app/(main)/(screens)/CollaborationHistory.tsx (1 hunks)
  • app/(main)/(screens)/_layout.tsx (0 hunks)
  • app/(main)/(screens)/collaboration-details/[pageID].tsx (1 hunks)
  • app/(main)/_layout.tsx (0 hunks)
  • app/(modal)/create-collaboration.tsx (8 hunks)
  • app/(modal)/create-collaboration.web.tsx (0 hunks)
  • app/(onboarding)/onboarding-brand-preference.tsx (1 hunks)
  • app/(onboarding)/onboarding-get-started.tsx (4 hunks)
  • app/(onboarding)/onboarding-your-brand.tsx (5 hunks)
  • app/(public)/pre-signin.tsx (2 hunks)
  • components/BottomSheetActions.tsx (7 hunks)
  • components/FilterModal.tsx (6 hunks)
  • components/InfluencerCard.tsx (5 hunks)
  • components/SearchComponent.tsx (3 hunks)
  • components/channel/channel-list.tsx (1 hunks)
  • components/collaboration/CollaborationCard.tsx (3 hunks)
  • components/collaboration/CollaborationDetails.tsx (0 hunks)
  • components/collaboration/CollaborationHeader.tsx (1 hunks)
  • components/collaboration/collaboration-details/ApplicationsTabContent.tsx (4 hunks)
  • components/collaboration/collaboration-details/InvitationsTabContent.tsx (5 hunks)
  • components/collaboration/collaboration-details/OverviewTabContent.tsx (1 hunks)
  • components/collaboration/collaboration-details/SettingsTabContent.tsx (1 hunks)
  • components/collaboration/collaboration-details/index.tsx (1 hunks)
  • components/collaboration/create-collaboration/CreateCollaborationMap.tsx (1 hunks)
  • components/collaborations/index.tsx (1 hunks)
  • components/contracts/index.tsx (1 hunks)
  • components/drawer-layout/BrandItem.tsx (2 hunks)
  • components/drawer-layout/DrawerMenuContent.tsx (2 hunks)
  • components/drawer-layout/DrawerMenuItem.tsx (2 hunks)
  • components/explore-influencers/index.tsx (3 hunks)
  • components/notifications/index.tsx (2 hunks)
  • components/notifications/notification-icon.tsx (2 hunks)
  • components/proposals/Applications.tsx (3 hunks)
  • components/proposals/Invitations.tsx (2 hunks)
  • components/ui/brand-switcher/index.tsx (2 hunks)
  • components/ui/carousel/carousel.tsx (1 hunks)
  • components/ui/carousel/carousel.web.tsx (1 hunks)
  • components/ui/carousel/render-media-item.tsx (1 hunks)
  • components/ui/empty-state/index.tsx (2 hunks)
  • components/ui/menu-icon/index.tsx (2 hunks)
  • components/ui/modal/DocumentUploadModal.tsx (2 hunks)
  • components/ui/modal/ImageUploadModal.tsx (2 hunks)
  • components/ui/select/index.tsx (1 hunks)
  • components/ui/tag/index.tsx (1 hunks)
  • components/ui/top-tab-navigation/index.tsx (1 hunks)
  • constants/Colors.ts (3 hunks)
  • constants/CreateCollaborationForm.ts (1 hunks)
  • constants/Influencers.ts (2 hunks)
  • constants/Themes/Theme.ts (1 hunks)
  • hooks/request/index.ts (1 hunks)
  • hooks/request/use-influencers.tsx (1 hunks)
  • layouts/app-layout/index.tsx (2 hunks)
  • package.json (2 hunks)
  • styles/CollaborationCard.styles.tsx (3 hunks)
  • styles/FilterModal.styles.tsx (1 hunks)
  • styles/InfluencerCard.styles.tsx (3 hunks)
  • styles/NotificationCard.styles.tsx (1 hunks)
  • styles/Proposal.styles.tsx (2 hunks)
  • styles/brand-item/BrandItem.styles.tsx (1 hunks)
  • styles/collaboration-details/CollaborationDetails.styles.tsx (4 hunks)
  • styles/collaboration-details/CollaborationHeader.styles.tsx (1 hunks)
  • styles/empty-state/EmptyState.styles.tsx (2 hunks)
  • styles/forget-password.styles.tsx (0 hunks)
  • styles/login.styles.tsx (0 hunks)
  • styles/modal/UploadModal.styles.tsx (2 hunks)
  • styles/onboarding/brand.styles.tsx (1 hunks)
  • styles/onboarding/preference.styles.tsx (0 hunks)
  • styles/signup.styles.tsx (0 hunks)
  • styles/tab1.styles.tsx (1 hunks)
  • styles/tag/Tag.styles.tsx (1 hunks)
  • styles/top-tab-navigation/TopTabNavigation.styles.tsx (1 hunks)
  • utils/conversion.ts (1 hunks)
  • utils/url.ts (1 hunks)
💤 Files with no reviewable changes (10)
  • app/(auth)/forget-password.tsx
  • app/(auth)/login.tsx
  • app/(main)/(screens)/_layout.tsx
  • app/(main)/_layout.tsx
  • app/(modal)/create-collaboration.web.tsx
  • components/collaboration/CollaborationDetails.tsx
  • styles/forget-password.styles.tsx
  • styles/login.styles.tsx
  • styles/onboarding/preference.styles.tsx
  • styles/signup.styles.tsx
✅ Files skipped from review due to trivial changes (3)
  • components/collaboration/collaboration-details/SettingsTabContent.tsx
  • constants/CreateCollaborationForm.ts
  • hooks/request/index.ts
🧰 Additional context used
🪛 Biome (1.9.4)
components/collaboration/create-collaboration/CreateCollaborationMap.tsx

[error] 6-6: Do not shadow the global "Map" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

components/drawer-layout/DrawerMenuContent.tsx

[error] 25-26: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)

components/ui/carousel/carousel.tsx

[error] 36-36: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

components/ui/select/index.tsx

[error] 55-57: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

hooks/request/use-influencers.tsx

[error] 103-103: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)

🔇 Additional comments (90)
utils/conversion.ts (1)

1-6: Verify consistent usage across components

Let's ensure the function is implemented consistently across all components that display numerical data.

✅ Verification successful

Function usage is consistent across the codebase

The verification shows that convertToKUnits is only used in InfluencerCard component for formatting followers and reach counts. The search for other number formatting patterns (toFixed with k/K/m/M/b/B units) only found the implementation within the utility function itself, confirming there are no inconsistent number formatting patterns elsewhere in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all usage of convertToKUnits to verify consistent implementation

# Search for direct usage of convertToKUnits
echo "Direct function usage:"
rg -A 2 "convertToKUnits"

# Search for potential places where it could be used (number formatting patterns)
echo "\nPotential places where convertToKUnits could be used:"
rg -A 2 "toFixed\(.*\).*[kKmMbB]"

Length of output: 1260

app/(main)/(screens)/CollaborationHistory.tsx (1)

1-13: Review component placement in the application structure

The AI summary mentions related changes in app/(modal)/create-collaboration.tsx. Given this component's current location in (main)/(screens), please verify:

  1. Should this component be in the modal directory instead?
  2. Are there duplicate implementations across different directories?
  3. What's the intended navigation flow between these components?

Let's analyze the application structure:

✅ Verification successful

Component placement is correct in the current directory structure

Based on the analysis:

  1. The CollaborationHistory component in (main)/(screens) is correctly placed as it's a full screen view, while create-collaboration.tsx in (modal) is a modal component.
  2. These are distinct components with different purposes:
    • create-collaboration.tsx is a modal form for creating new collaborations
    • CollaborationHistory is a main screen for viewing collaboration history
  3. The navigation flow is clear:
    • Modal can be dismissed to return to main screens
    • Main screens are accessed through normal navigation
    • Both serve different user interactions
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for potential duplicate implementations
echo "Checking for collaboration-related files in modal directory..."
fd "collaboration" "app/(modal)"

echo "\nAnalyzing imports of this component..."
rg -l "CollaborationHistory" --type tsx

Length of output: 363


Script:

#!/bin/bash
# Let's try a more comprehensive analysis with ripgrep without file type filter
echo "Analyzing imports and usage of CollaborationHistory..."
rg "CollaborationHistory"

echo "\nChecking the structure and content of both files..."
echo "\nContent of create-collaboration.tsx:"
cat "app/(modal)/create-collaboration.tsx"

echo "\nChecking navigation patterns..."
rg "router.push|href.*collaboration" -A 2

Length of output: 18259

styles/tag/Tag.styles.tsx (1)

7-11: 🛠️ Refactor suggestion

Verify the padding values and consider adding text overflow handling

The zero padding (paddingVertical: 0, paddingHorizontal: 0) seems unusual for a tag component and might affect its appearance and usability. Additionally, consider handling text overflow scenarios.

Consider applying these improvements:

 tag: {
   backgroundColor: Colors(theme).tag,
-  paddingVertical: 0,
-  paddingHorizontal: 0,
+  paddingVertical: 4,
+  paddingHorizontal: 8,
   borderRadius: 10,
+  overflow: 'hidden',
 },
components/ui/tag/index.tsx (2)

1-3: LGTM: Clean imports with clear dependencies

The imports are well-organized and properly scoped. The component relies on standard React Native navigation theming and react-native-paper components.


9-10: Verify theme integration across the application

The component uses the navigation theme, which is good for consistency. However, we should verify that the imported styles properly handle all theme modes (light/dark).

✅ Verification successful

Theme integration is properly implemented

The Tag component correctly handles both light and dark themes:

  • Background colors: #5f6368 (light) / #f1f3f4 (dark)
  • Text colors: #f1f3f4 (light) / #5f6368 (dark)

The colors are appropriately inverted between themes to maintain contrast and readability in both modes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the imported styles handle both theme modes
ast-grep --pattern 'export const stylesFn = ({ colors, dark }) => StyleSheet.create({
  $$$
})'

Length of output: 97


Script:

#!/bin/bash
# Let's first find the stylesFn implementation
rg "stylesFn" -A 10

# Also check for any theme-related styles in the tag component
rg "StyleSheet.create" -A 10 components/ui/tag/

Length of output: 54686


Script:

#!/bin/bash
# Let's check the Tag styles implementation and its theme handling
rg -A 10 "Colors\(theme\)" styles/tag/Tag.styles.tsx

# Also check the Theme type definition to understand available theme properties
rg "type Theme" -A 5

Length of output: 570


Script:

#!/bin/bash
# Let's check the Colors utility to see how theme colors are defined
rg -A 10 "const Colors = \(theme\)" constants/Colors.ts

# Also check if there are any theme-specific color definitions
rg "tag:|tagForeground:" constants/Colors.ts

Length of output: 220

styles/Proposal.styles.tsx (1)

1-1: LGTM!

The Colors import is correctly placed and properly uses the module alias pattern.

styles/brand-item/BrandItem.styles.tsx (1)

14-14: Verify the asymmetric horizontal padding intention

The container has asymmetric horizontal padding (14px left, 8px right). Please confirm if this is intentional, as it might create visual imbalance.

✅ Verification successful

Based on the context gathered, I can now generate the final response:

The asymmetric padding is intentionally designed for the drawer menu layout

The asymmetric padding (14px left, 8px right) is part of a consistent drawer menu design where:

  • BrandItem components are used within DrawerMenuContent as menu items
  • The left padding (14px) aligns with the Searchbar's marginHorizontal
  • The right padding (8px) provides space for the chevron icon in BrandActionItem
  • Both BrandItem and BrandActionItem share the same styles and are used in a consistent layout pattern
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for similar asymmetric padding patterns in other components
# to verify if this is part of a broader design pattern

# Search for padding patterns in style files
rg -A 5 'paddingLeft|paddingRight' --glob '**/*.styles.{ts,tsx}'

Length of output: 980


Script:

#!/bin/bash
# Let's check the BrandItem component usage and its parent components
# to understand the context of this asymmetric padding

# First, find all files that import or reference BrandItem
rg -l "BrandItem" --type ts --type tsx

# Then, let's look for any design tokens or theme constants that might define these padding values
rg "(8|14)" --glob "**/theme/*.{ts,tsx}"

Length of output: 109


Script:

#!/bin/bash
# Let's try a different approach to find BrandItem usage and related components
# Using fd to find files first, then grep through them

# Find TypeScript/React files that mention BrandItem
fd -e ts -e tsx | xargs rg "BrandItem"

# Look for any design system or spacing constants
fd -e ts -e tsx | xargs rg "spacing|padding.*constant|SPACING|PADDING"

Length of output: 688


Script:

#!/bin/bash
# Let's examine the DrawerMenuContent to understand the context where BrandItem is used
cat components/drawer-layout/DrawerMenuContent.tsx

# Also check BrandActionItem since it shares the same styles
cat components/drawer-layout/BrandActionItem.tsx

Length of output: 6591

styles/empty-state/EmptyState.styles.tsx (2)

9-10: LGTM! Container spacing improvements look good.

The added horizontal padding and gap provide better content spacing and consistent layout.


26-26: LGTM! Consistent text alignment.

Centering both title and subtitle provides better visual harmony for empty states.

Also applies to: 30-30

utils/url.ts (2)

13-13: Consider externalizing the placeholder image path.

Hard-coding the placeholder image path creates tight coupling. Consider moving it to a configuration file.

Let's check if there's a central configuration file:


1-15: Verify usage of imageUrl function across the codebase.

Since this is a new function with specific return types, we should verify its integration with components that will consume it.

✅ Verification successful

Function implementation aligns with its usage across the codebase

The imageUrl function is correctly used in multiple components:

  • InfluencerCard.tsx: Used with influencer.profilePic and optional images
  • empty-state/index.tsx: Used with optional image prop
  • CollaborationHeader.tsx: Used with optional collaboration?.logo
  • render-media-item.tsx: Used with URL strings (item.url || item.uri)

All usages align with the function's implementation which handles:

  • URLs (starting with "http" or "ph://")
  • NodeRequire objects
  • Undefined values
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Find all files that might use the imageUrl function
rg -l "imageUrl" --type-add 'react:*.tsx' --type react

# Look for potential image-related components that might need to use this function
ast-grep --pattern 'source={$_}' --type-add 'react:*.tsx' --type react

Length of output: 479


Script:

#!/bin/bash
# Let's examine the usage of imageUrl in the identified files
echo "=== InfluencerCard.tsx ==="
rg "imageUrl" components/InfluencerCard.tsx -B 2 -A 2

echo -e "\n=== empty-state/index.tsx ==="
rg "imageUrl" components/ui/empty-state/index.tsx -B 2 -A 2

echo -e "\n=== CollaborationHeader.tsx ==="
rg "imageUrl" components/collaboration/CollaborationHeader.tsx -B 2 -A 2

echo -e "\n=== render-media-item.tsx ==="
rg "imageUrl" components/ui/carousel/render-media-item.tsx -B 2 -A 2

# Let's also check for Image component usage patterns to understand the expected prop types
echo -e "\n=== Image component usage patterns ==="
ast-grep --pattern 'Image source={$_}'

Length of output: 2330

constants/Themes/Theme.ts (1)

10-17: Verify completeness of Material Design color system tokens

The new color properties follow Material Design naming conventions, which is good. However, let's ensure all essential color tokens are present for a complete theme implementation.

Consider adding these commonly used Material Design color tokens if they're needed in your application:

  • error and onError for error states
  • tertiary and onTertiary for additional accent colors
  • outline for component boundaries
components/collaborations/index.tsx (1)

29-31: Verify TopTabNavigation implementation.

Since TopTabNavigation is a new component, let's verify its implementation to ensure it properly handles tab switching and renders components correctly.

✅ Verification successful

TopTabNavigation implementation is properly integrated

The TopTabNavigation component is well-implemented with:

  • Proper TypeScript interface for props (TopTabNavigationProps)
  • Robust tab switching logic with scroll handling
  • Consistent usage across collaboration components
  • Proper state management for active tabs
  • Responsive layout with support for different sizes ("compact" | "default")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if TopTabNavigation component exists and verify its implementation
echo "Checking TopTabNavigation component implementation..."
ast-grep --pattern 'export $_ function TopTabNavigation' || ast-grep --pattern 'export $_ const TopTabNavigation'

# Check for proper prop types definition
echo "Checking for prop types..."
ast-grep --pattern 'interface $_Props {
  tabs: $_
}'

# Check for proper tab handling logic
echo "Checking tab handling logic..."
rg -A 10 "const.*TopTabNavigation.*=.*{" components/ui/top-tab-navigation/

Length of output: 564


Script:

#!/bin/bash
# Let's try a different approach to locate the TopTabNavigation component
echo "Searching for TopTabNavigation files..."
fd -t f "top-tab-navigation" --exec ls -l

echo "\nSearching for TopTabNavigation usage and implementation..."
rg -l "TopTabNavigation"

echo "\nChecking component content..."
fd -t f "top-tab-navigation" --exec cat {}

Length of output: 540


Script:

#!/bin/bash
# Let's examine the actual implementation of TopTabNavigation
echo "Checking TopTabNavigation implementation:"
cat components/ui/top-tab-navigation/index.tsx

echo "\nChecking usage in collaboration components:"
echo "\n1. In collaborations/index.tsx:"
cat components/collaborations/index.tsx

echo "\n2. In collaboration-details/index.tsx:"
cat components/collaboration/collaboration-details/index.tsx

Length of output: 7602

components/contracts/index.tsx (2)

13-21: Fix typo in empty state message and verify navigation path

  1. There's a typo in the subtitle text: "Opps!" should be "Oops!"
  2. The navigation path "/collaborations" needs verification to ensure it exists
- subtitle="Opps! No Contracts has been created yet. Start applying to collaboration to get contracts."
+ subtitle="Oops! No Contracts have been created yet. Start applying to collaborations to get contracts."

Let's verify the navigation path:

✅ Verification successful

Fix typo in empty state message

The navigation path "/collaborations" exists at app/(main)/(drawer)/(tabs)/collaborations.tsx, confirming it's a valid route. Please fix the typo and grammar in the subtitle text:

- subtitle="Opps! No Contracts has been created yet. Start applying to collaboration to get contracts."
+ subtitle="Oops! No Contracts have been created yet. Start applying to collaborations to get contracts."
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the collaborations route exists
fd -e tsx -e ts -e js "collaborations\.(tsx|ts|js)" app/

Length of output: 104


7-8: 🛠️ Refactor suggestion

Add type annotation and verify data fetching implementation

The contracts array initialization raises two concerns:

  1. Missing type annotation for better type safety
  2. Hardcoded empty array suggests missing data fetching logic

Consider applying these changes:

- const contracts = [];
+ const contracts: Contract[] = []; // Add appropriate interface
+ // TODO: Implement data fetching logic

Let's verify if there's any existing contracts fetching logic in the codebase:

styles/NotificationCard.styles.tsx (4)

8-8: LGTM! Improved spacing consistency

The padding update to 16 aligns better with standard design system spacing units.


26-26: LGTM! Consistent spacing

The marginLeft update maintains spacing consistency with other changes.


Line range hint 1-48: Verify notification handling strategy

Given that Toast components are being removed (as mentioned in the PR summary), please verify:

  • How time-sensitive notifications are now handled
  • Whether this NotificationCard component is intended to replace Toast functionality
  • If any animation or auto-dismiss behavior needs to be added

11-14: Verify layout changes with different content lengths

The new contentContainer style improves spacing consistency. However, since this is a new addition, please verify the layout renders correctly with:

  • Single line content
  • Multi-line content
  • Multiple notification items
✅ Verification successful

Layout changes are appropriately structured for all content variations

The contentContainer styles are correctly implemented and will work well with all content variations because:

  • The gap of 16 provides consistent spacing between multiple notification cards in the ScrollView
  • The paddingBottom of 24 ensures proper bottom spacing when scrolling through notifications
  • The NotificationCard component has a robust structure that handles:
    • Single-line content (title)
    • Multi-line content (description and timestamp)
    • Variable action buttons that appear conditionally
  • The parent Notifications component properly uses these styles in both empty and populated states
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for NotificationCard usage to understand content variations
rg -l "NotificationCard" --type tsx

Length of output: 63


Script:

#!/bin/bash
# Search for NotificationCard usage with ripgrep, trying different file extensions
rg -l "NotificationCard" --type ts --type tsx --type jsx --type js

# Also search for the style file itself to confirm its existence
fd "NotificationCard.styles"

Length of output: 158


Script:

#!/bin/bash
# Search for NotificationCard usage with just file extensions
rg -l "NotificationCard" -g "*.ts" -g "*.tsx" -g "*.jsx" -g "*.js"

# Look at the content of the style file to understand the component structure
cat styles/NotificationCard.styles.tsx

Length of output: 1109


Script:

#!/bin/bash
# Let's look at the component implementation to understand the content structure
cat components/NotificationCard.tsx

# Also check the usage in notifications index
cat components/notifications/index.tsx

Length of output: 5119

app/(main)/(screens)/collaboration-details/[pageID].tsx (2)

1-6: LGTM! Clean and well-organized imports

The imports are properly organized and all imported entities are utilized in the component.


20-24: Verify the hardcoded cardType and snap points implementation

A few considerations about the BottomSheetActions implementation:

  1. The hardcoded cardType="influencerCard" might need to be more flexible
  2. The snap points range might need verification for optimal UX

Let's check how these values are used across the codebase:

✅ Verification successful

The hardcoded cardType is correct and snap points are consistently implemented

The verification reveals that:

  1. The cardType="influencerCard" is intentionally hardcoded as it's part of a well-defined set of card types used across the application (influencerCard, applicationCard, invitationCard, activeCollab, etc.). Each type triggers specific actions in the BottomSheetActions component.
  2. The snap points implementation varies based on the use case:
    • ["20%", "50%"] for influencer cards
    • ["50%", "90%"] for onboarding preferences

This variation is appropriate as different contexts require different sheet heights for optimal UX.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other usages of BottomSheetActions and its props
ast-grep --pattern 'BottomSheetActions $$$cardType="$_"$$$'

# Check for different snap points configurations
ast-grep --pattern 'snapPointsRange={$_}'

Length of output: 105


Script:

#!/bin/bash
# Let's try a different approach to find BottomSheetActions usage
rg -A 3 "<BottomSheetActions"

# Also search for the component definition
ast-grep --pattern 'const BottomSheetActions = $_'

# And check for any type definitions related to cardType
rg "cardType.*=" -A 2

Length of output: 22257

styles/collaboration-details/CollaborationHeader.styles.tsx (3)

1-4: LGTM! Clean and well-organized imports.

The imports are properly structured with external dependencies first, followed by internal modules.


39-43: LGTM! Well-structured tag container styles.

The flex-wrap implementation provides a good responsive layout for tags.


11-24: Verify gap property support in target React Native versions.

The layout structure is well-organized, but the gap property might need a fallback for older React Native versions.

✅ Verification successful

The gap property is safe to use with React Native 0.74.3

The gap property is well-supported in React Native 0.74.3 and is consistently used throughout the codebase in multiple components and styles. The usage pattern shows it's a standard practice in this project, appearing in over 40 style definitions across various components. No fallback is needed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check package.json for React Native version
rg '"react-native":\s*"([^"]+)"' -o | head -n1

Length of output: 86


Script:

#!/bin/bash
# Check if there are any existing fallbacks or alternative spacing approaches in the codebase
rg -B2 -A2 'gap:.*\d+' --type tsx --type ts

Length of output: 73


Script:

#!/bin/bash
# Check for gap usage patterns in style files, correcting the file type
rg -B2 -A2 'gap:' .

Length of output: 14232

components/ui/menu-icon/index.tsx (1)

23-26: Verify icon size consistency

The icon size has been changed from 25 to 24. While this change is minor, let's verify if this new size is consistent with other navigation icons in the app.

styles/FilterModal.styles.tsx (1)

9-10: LGTM! The padding split provides better layout control.

The separation of padding into horizontal and vertical components allows for more precise layout control, following React Native best practices.

styles/CollaborationCard.styles.tsx (3)

8-8: Verify the removal of card elevation

The removal of elevation and setting transparent shadow will make the card appear flat. Please confirm if this aligns with the new design system, as it might impact the visual hierarchy and depth perception of the UI.

Consider maintaining some subtle elevation to help distinguish the card from its background, especially in cases where the card and background colors are similar.

Also applies to: 10-10


25-25: LGTM! Good improvement to layout flexibility

Adding flex: 1 to the collaboration name style is a good practice that ensures proper text truncation and flexible layout behavior.


Line range hint 1-61: Verify cleanup of removed styles

The AI summary mentions that the bookmarkIcon style was removed, but we can't see it in the changes. Let's verify that it's not being used elsewhere in the codebase.

✅ Verification successful

Removed styles are safely deleted

The git diff confirms that bookmarkIcon style was removed along with other styles (chip and divider). After checking the component file, none of these removed styles are being used in the CollaborationCard component, confirming this is a safe cleanup.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining references to bookmarkIcon
rg -i "bookmarkIcon" --type tsx --type ts

Length of output: 69


Script:

#!/bin/bash
# Search for any remaining references to bookmarkIcon using ripgrep without file type filters
rg -i "bookmarkIcon"

# Also search for the component file that might be using these styles
fd -e tsx -e ts "CollaborationCard"

Length of output: 139


Script:

#!/bin/bash
# Let's check the component file to see if it's using any removed styles
cat components/collaboration/CollaborationCard.tsx

# Also get the git history of the styles file to see what was removed
git diff HEAD^ styles/CollaborationCard.styles.tsx

Length of output: 5005

styles/top-tab-navigation/TopTabNavigation.styles.tsx (2)

43-52: LGTM! Well-structured compact styles.

The compact styles follow a good pattern for responsive design, providing a consistent way to render a more condensed version of the tabs.


53-55: LGTM! Appropriate content styling.

The flex: 1 style is appropriate for ensuring the content takes up the available space.

constants/Colors.ts (1)

16-19: Review color contrast ratios for accessibility.

The dark theme colors need review for the following concerns:

  1. primary and onSurface share the same value (#538BA6), which might not follow Material Design principles where surface colors typically contrast with their "on" colors.
  2. The contrast ratio between tag (#5f6368) and tagForeground (#f1f3f4) should be verified for accessibility.
components/notifications/notification-icon.tsx (2)

9-10: LGTM: FontAwesome imports

The new imports for FontAwesome's React Native integration are correctly added.


43-46: LGTM: Icon implementation

The FontAwesomeIcon implementation is correct with proper:

  • Color inheritance from theme
  • Icon specification using faBell
  • Size specification
  • Opacity handling for pressed state
components/ui/empty-state/index.tsx (3)

21-33: LGTM!

Clean props destructuring with sensible defaults and proper hook initialization.


17-17: Consider keeping the title prop required

Making the title optional might lead to empty states without clear messaging for users. Consider keeping it required unless there's a specific use case for empty titles.


34-40: Consider handling navigation edge cases

The fallback to navigation.goBack() might fail if there's no navigation history. Consider adding a safety check or providing a default route.

  const handleAction = () => {
    if (action) {
      action();
    } else {
-     navigation.goBack();
+     if (navigation.canGoBack()) {
+       navigation.goBack();
+     } else {
+       // Navigate to a safe default route
+       navigation.navigate('Home');
+     }
    }
  };
styles/tab1.styles.tsx (1)

16-19: Verify skip button's visibility and accessibility

The skipButtonContainer now only contains positioning properties. Ensure that the skip button remains visible and accessible without the previously removed styling properties (background, padding, border radius).

components/drawer-layout/DrawerMenuItem.tsx (1)

6-7: Verify the impact of IconProp type change across the codebase

The change from string to IconProp for the icon property improves type safety but could be a breaking change.

Let's verify all usages of this component to ensure they've been updated:

Also applies to: 11-11

✅ Verification successful

Let me gather more information to verify the impact of this change.


Let me check how the tabs are defined and passed to DrawerMenuItem through DrawerMenuContent.


Let me try one final search to find any tab or icon definitions in the codebase.


Based on the gathered information, I can now provide the final response:

Type change to IconProp appears to be properly contained

The change from string to IconProp is localized and properly managed:

  • DrawerMenuItem is only imported and used in DrawerMenuContent.tsx
  • The IconProp type is correctly imported and used in the Tab type definition
  • No other components in the codebase are using IconProp, suggesting this is an isolated change
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for DrawerMenuItem usage patterns
rg -l "DrawerMenuItem" | xargs rg -A 5 "icon:\s*['\"]" 

# Search for any Tab type usage
ast-grep --pattern 'type Tab = {
  $$$
}'

Length of output: 401


Script:

#!/bin/bash
# Search for DrawerMenuItem component usage
rg -A 2 "<DrawerMenuItem"

# Search for any icon prop assignments to DrawerMenuItem
rg "icon=" --context 2 "DrawerMenuItem"

# Search for any imports of DrawerMenuItem
rg -A 1 "import.*DrawerMenuItem"

Length of output: 825


Script:

#!/bin/bash
# Search for tabs definition in DrawerMenuContent
rg -A 10 "const.*tabs.*=.*\[" components/drawer-layout/DrawerMenuContent.tsx

# Search for any other files that might define these tabs
rg -g '!DrawerMenuContent.tsx' -A 5 "icon:.*['\"]"

Length of output: 133


Script:

#!/bin/bash
# Search for any array containing icon definitions
rg -A 5 "\[\s*{\s*(icon|href|label):"

# Search for any IconProp type usage
rg "IconProp"

# Search for any FontAwesome icon assignments
rg "icon:\s*[\"\']fa[rls]?-"

Length of output: 469

components/collaboration/CollaborationHeader.tsx (1)

7-7: Verify style definitions and theme typing

Let's ensure the imported styles are properly defined and typed.

✅ Verification successful

Style definitions and theme typing are properly implemented

The verification shows that:

  • The file exists at the correct location: styles/collaboration-details/CollaborationHeader.styles.tsx
  • The style file properly imports and uses the Theme type from @react-navigation/native
  • The stylesFn is correctly exported and typed with the Theme parameter
  • The component correctly imports and uses the theme-aware styles
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if styles file exists and contains proper theme typing
rg -l "stylesFn.*Theme" "styles/collaboration-details/CollaborationHeader.styles.ts"

# Verify theme type usage
ast-grep --pattern 'interface $_ extends Theme {
  $$$
}'

Length of output: 243


Script:

#!/bin/bash
# Let's first check if the file exists in a different location
fd "CollaborationHeader.styles" 

# Search for any stylesFn exports in the codebase
rg "export.*stylesFn"

# Look for Theme imports and interfaces
rg "import.*Theme" -A 2

Length of output: 30380

components/ui/brand-switcher/index.tsx (2)

4-5: LGTM: Clean import restructuring

The switch to FontAwesome icons aligns well with the standardization effort across the application.


40-43: Verify icon standardization across similar components

Let's ensure this icon implementation is consistent with other similar components in the codebase.

✅ Verification successful

Icon implementation is consistent across components

The FontAwesomeIcon usage in brand-switcher follows the same pattern as other components in the codebase:

  • Consistent import from "@fortawesome/react-native-fontawesome"
  • Standard props pattern using color, icon, and size
  • Consistent color handling using Colors(theme).text for UI components
  • Similar icon size values (20-24px range)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other FontAwesomeIcon usage patterns in similar UI components
rg -l "FontAwesomeIcon" --type tsx | while read -r file; do
  echo "=== $file ==="
  rg "FontAwesomeIcon" -A 2 "$file"
done

Length of output: 77


Script:

#!/bin/bash
# Search for FontAwesomeIcon usage patterns in all files
rg -l "FontAwesomeIcon" | while read -r file; do
  echo "=== $file ==="
  rg "FontAwesomeIcon" -A 2 "$file"
done

Length of output: 5175

styles/onboarding/brand.styles.tsx (2)

33-33: Consider accessibility implications

The switch to primary color for the border might affect color contrast ratios. Please verify that the input remains clearly visible against different background colors and meets WCAG accessibility guidelines.

Consider implementing contrast ratio checks in your CI pipeline to automatically verify accessibility compliance. Would you like assistance in setting this up?


33-33: Verify alignment with design system

The change from border color to primary color makes the input more prominent. While this change aligns with the theme update objective, please ensure this styling is consistent with other autocomplete inputs across the application.

✅ Verification successful

Let me generate another verification script to search for similar input containers and their border colors across the codebase.


Let me try one final search with a different approach to find styling patterns.


Based on the comprehensive search results, I can now make a determination about the border color change. Looking at the codebase:

  1. The change from Colors(theme).border to Colors(theme).primary appears to be an intentional styling update for the autocomplete input container.
  2. Other components in the codebase use different border colors based on their specific needs (e.g., Colors(theme).aliceBlue, Colors(theme).text, etc.).
  3. There's no consistent pattern requiring all input containers to use the same border color.
  4. The autocomplete input is a standalone component with its own styling requirements.

Border color change is acceptable

The change from neutral border to primary color for this specific autocomplete input is appropriate as:

  • It's a localized styling change that doesn't affect other components
  • Input containers across the codebase use various border colors based on their individual design needs
  • The primary color will make this input more prominent, which may be desirable for its specific use case
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for other autocomplete input containers to verify styling consistency
# Look for similar style definitions in other files

# Search for autocomplete input container styles
rg -t tsx -t ts "autocompleteInputContainer.*borderColor.*Colors\(theme\)" --glob '!styles/onboarding/brand.styles.tsx'

# Search for similar components using ast-grep
ast-grep --pattern 'StyleSheet.create({
  $$$
  autocompleteInputContainer: {
    $$$
    borderColor: $_,
    $$$
  },
  $$$
})'

Length of output: 5175


Script:

#!/bin/bash
# Search for any input container styles with border colors to compare styling patterns
rg -t ts -t tsx "borderColor.*Colors\(theme\)" -B 2 -A 1

# Search specifically for input-related containers with border colors
ast-grep --pattern '{
  $$$
  input$_: {
    $$$
    borderColor: $_,
    $$$
  }
}'

Length of output: 173


Script:

#!/bin/bash
# Search for all style definitions containing Colors(theme) to understand the color usage pattern
fd -e tsx -e ts -x grep -l "Colors(theme)" {} | xargs cat

# Alternative pattern search for border-related styles
ast-grep --pattern 'StyleSheet.create({
  $$$
  border$_: $_,
  $$$
})'

Length of output: 131206

constants/Influencers.ts (1)

Line range hint 11-12: Add error handling for external image URLs

The profile pictures and media URLs point to external services. Consider:

  1. Adding fallback images
  2. Implementing image loading error handling
  3. Using a CDN or internal asset storage for production

Also applies to: 42-43

✅ Verification successful

Let me check how these URLs are being used in the codebase to understand the implementation better.


External image URLs need proper error handling, but fallback mechanism exists

The codebase already has a fallback mechanism implemented with local placeholder images:

  • Default placeholder: @/assets/images/placeholder-image.jpg
  • Person placeholder: @/assets/images/placeholder-person-image.png
  • Cover placeholder: @/assets/images/cover-placeholder-image.png

However, the external URLs in Influencers.ts should utilize this existing fallback system. Consider:

  • Using the getImageUrl utility from utils/url.ts which already handles fallbacks
  • Moving the external images to a CDN in production for better reliability
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for other instances of hardcoded external URLs in the codebase
rg -g '*.{ts,tsx,js,jsx}' 'https://img.freepik.com|https://picsum.photos'

Length of output: 935


Script:

#!/bin/bash
# Check for image handling components and utilities
rg -g '*.{ts,tsx,js,jsx}' -B 2 -A 2 'onError|fallback|placeholder|loading.*image'

# Check Image component usage
ast-grep --pattern 'Image source={$_}'

Length of output: 6454

styles/InfluencerCard.styles.tsx (2)

14-16: LGTM! Good use of gap for spacing

The header styling changes improve the layout consistency by using the gap property for spacing elements.


74-80: LGTM! Good layout structure

The new layout structure with separate stats and statsContainer provides better organization and spacing control.

styles/collaboration-details/CollaborationDetails.styles.tsx (3)

85-85: LGTM! Good use of theme-based colors.

The change to use theme-based border color improves consistency with the app's theming system.


50-53: Verify the shadow removal intention and clean up unused properties.

The shadow color is set to transparent, but according to the AI summary, other shadow-related properties were removed. This might indicate a move towards a flatter UI design.

If the intention is to remove shadows completely, consider removing all shadow-related properties for cleaner code. Run this script to verify shadow-related properties across style files:

✅ Verification successful

Let me gather more context about the specific file to understand if there are any remaining shadow properties.


Shadow properties are properly cleaned up in this component

The verification shows that in CollaborationDetails.styles.tsx, shadowColor is the only shadow-related property present, and it's set to transparent. There are no lingering shadow properties like shadowOffset, shadowOpacity, shadowRadius, or elevation that would need cleanup.

Looking at the broader codebase context:

  • Some components like modals and Tab1 maintain full shadow implementations
  • Other cards (CollaborationCard, NotificationCard) also use transparent shadows
  • This suggests an intentional design pattern where certain components are flat while others maintain elevation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for shadow-related properties in style files
rg -i 'shadow(Color|Offset|Opacity|Radius)|elevation' 'styles/'

Length of output: 1126


Script:

#!/bin/bash
# Check the full style object in CollaborationDetails.styles.tsx
rg -A 10 -B 10 'shadowColor: Colors\(theme\)\.transparent' styles/collaboration-details/CollaborationDetails.styles.tsx

Length of output: 555


Line range hint 1-97: Verify the impact of removed styles.

The AI summary indicates that several styles (profileCard, profileContent, name, statChip) were removed. Let's verify these aren't used anymore.

✅ Verification successful

The removed styles are not used in the codebase

The search results show that while there are many occurrences of "name", "profileCard", "profileContent", and "statChip" in the codebase, none of them refer to the removed style properties from CollaborationDetails.styles.tsx. The occurrences are either:

  • Component props and data properties
  • Different style objects in other components
  • Route/screen names
  • File paths
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for usage of removed styles
rg -l 'styles\.(profileCard|profileContent|name|statChip)' --type tsx

Length of output: 99


Script:

#!/bin/bash
# Check for usage of removed styles with proper file extension
rg -l 'styles\.(profileCard|profileContent|name|statChip)' --type ts --type tsx --type jsx --type js

# Also search for any direct references to these style names
rg -l '(profileCard|profileContent|name|statChip):\s*{' --type ts --type tsx --type jsx --type js

Length of output: 388


Script:

#!/bin/bash
# Search for any usage of the removed style names in all files
rg "profileCard|profileContent|name|statChip" -g "*.ts" -g "*.tsx" -g "*.js" -g "*.jsx" -C 2

Length of output: 26897

components/SearchComponent.tsx (1)

2-7: LGTM! Good improvements to the imports

The switch to Pressable and standardization of icons with FontAwesome are good improvements. The Theme type import properly supports the new theme-aware styling.

components/notifications/index.tsx (2)

39-62: LGTM! Well-structured notification list implementation

The ScrollView implementation with NotificationCard mapping is clean and efficient:

  • Proper style management with contentContainerStyle
  • Correct data passing to NotificationCard components
  • Appropriate callback handling

40-41: Verify style definitions exist

The component references styles.container and styles.contentContainer. Let's ensure these styles are properly defined in the stylesFn.

✅ Verification successful

Style definitions are properly implemented

The container and contentContainer styles are correctly defined in styles/NotificationCard.styles.tsx and properly imported and used in the component. The styles are created using StyleSheet.create with appropriate properties:

  • container has flex, padding, and background color
  • contentContainer has gap and bottom padding
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for container and contentContainer style definitions
rg -A 5 "stylesFn.*=.*{" "@/styles/NotificationCard.styles"

Length of output: 151


Script:

#!/bin/bash
# First, let's find the styles file in the repository
fd "NotificationCard.styles" 

# Then search for style definitions in the components directory
rg -A 5 "styles\s*=\s*{|StyleSheet.create\s*\(" "components/notifications/"

Length of output: 273


Script:

#!/bin/bash
# Let's check the content of the styles file
cat styles/NotificationCard.styles.tsx

# Also check the component file for inline styles
cat components/notifications/index.tsx

Length of output: 3102

components/drawer-layout/BrandItem.tsx (1)

6-8: LGTM! Clean import structure

The transition to FontAwesome icons while maintaining necessary react-native-paper components shows a thoughtful migration approach.

components/channel/channel-list.tsx (1)

54-55: LGTM! Standardized padding values.

The change to use consistent padding values (16) aligns with common design system practices. However, please verify that reducing the top padding from 20 to 16 doesn't negatively impact the visual spacing with elements above this view.

✅ Verification successful

Padding standardization aligns with codebase patterns

The change to use padding: 16 and paddingTop: 16 in channel-list.tsx is consistent with the codebase's patterns. The search results show that:

  • 16px padding is commonly used (NotificationCard, CollaborationCard, UploadModal, etc.)
  • Top padding values vary between 8px and 16px for similar list/content components
  • The previous value of 20px is typically used for more prominent containers like modals and full-screen views
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for other components using similar padding patterns
# to ensure consistency across the codebase

# Search for padding declarations in TSX/JSX files
rg -t tsx -t jsx 'padding(?:Top)?: \d+' --no-filename | sort | uniq -c | sort -nr

Length of output: 111


Script:

#!/bin/bash
# Search for padding patterns in all files, not relying on file extensions
rg 'padding(?:Top)?: \d+' --type-add 'frontend:*.{tsx,jsx,ts,js}' -t frontend

Length of output: 2629

components/ui/carousel/render-media-item.tsx (1)

1-14: LGTM! Imports are well-organized and necessary.

The imports are properly structured, separating external dependencies from internal utilities.

components/ui/carousel/carousel.tsx (1)

21-23: LGTM! Well-structured state management

The state variables are well-defined with clear purposes and proper typing.

styles/modal/UploadModal.styles.tsx (1)

79-82: LGTM! Good improvements to layout flexibility

The changes from fixed widths to flex layout and from space-between to gap spacing improve the component's maintainability and flexibility.

components/collaboration/collaboration-details/OverviewTabContent.tsx (1)

16-21: LGTM!

Component declaration and theme setup are properly implemented.

package.json (1)

71-71: Verify compatibility with Font Awesome integration

Changing react-native-svg from fixed version "15.2.0" to "^15.2.0" could introduce breaking changes through minor updates. Please verify compatibility with the Font Awesome integration.

✅ Verification successful

Using react-native-svg ^15.2.0 is safe with Font Awesome integration

The codebase uses @fortawesome/react-native-fontawesome v0.3.2, which requires react-native-svg >= 11.x. Since v15.2.0 satisfies this requirement and no breaking changes were found in the react-native-svg repository that would affect Font Awesome integration, the version change is safe. The extensive usage of FontAwesomeIcon across multiple components is working with the current setup and will continue to work with minor updates to v15.x.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check compatibility between react-native-svg and @fortawesome/react-native-fontawesome

# Get the latest compatible version of react-native-svg from Font Awesome's package.json
curl -s https://registry.npmjs.org/@fortawesome/react-native-fontawesome/latest | jq -r '.peerDependencies["react-native-svg"]'

# Check for any reported issues or breaking changes
gh api graphql -f query='
{
  search(query: "repo:react-native-svg/react-native-svg is:issue label:breaking-change", type: ISSUE, first: 5) {
    nodes {
      ... on Issue {
        title
        url
        labels(first: 5) {
          nodes {
            name
          }
        }
      }
    }
  }
}'

Length of output: 478


Script:

#!/bin/bash
# Let's verify if Font Awesome is actually used in the codebase and check its version
rg -l "@fortawesome/react-native-fontawesome"

# Check the actual version of Font Awesome being used
cat package.json | jq '.dependencies["@fortawesome/react-native-fontawesome"], .devDependencies["@fortawesome/react-native-fontawesome"]'

# Look for any Font Awesome icon usage in the code
rg "FontAwesomeIcon|createIconSet" -A 2

Length of output: 7227

app/(public)/pre-signin.tsx (2)

1-4: LGTM! Import cleanup and Button component addition

The import changes align with the theme update objectives, removing unused imports and adding the Button component from react-native-paper.


62-63: Verify the skipButtonContainer styles

Please ensure that the skipButtonContainer style is properly defined in the styles object.

✅ Verification successful

Let me verify if this style is properly imported in the pre-signin.tsx file.


The skipButtonContainer style is properly defined and imported

The style is correctly defined in styles/tab1.styles.tsx and properly imported in pre-signin.tsx as stylesFn. The style definition includes the necessary positioning properties.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for skipButtonContainer style definition
rg -A 5 "skipButtonContainer.*[:=]" 

Length of output: 291


Script:

#!/bin/bash
# Check imports and style usage in pre-signin.tsx
rg -A 5 "import.*styles.*tab1\.styles" app/\(public\)/pre-signin.tsx

Length of output: 341

components/collaboration/CollaborationCard.tsx (2)

1-12: LGTM! Import changes align with component refactoring

The changes streamline the imports by removing unused hooks and replacing icon libraries, which aligns well with the refactoring objectives.


49-63: Verify the ellipsis button alignment

The justifyContent and alignItems changes to "flex-start" might affect the ellipsis button's positioning. Please ensure this doesn't create unintended layout shifts.

Consider using predefined style constants for consistent spacing:

-              justifyContent: "flex-start",
-              alignItems: "flex-start",
+              justifyContent: "center",
+              alignItems: "center",
app/(main)/(drawer)/(tabs)/_layout.tsx (4)

13-23: LGTM! Clean organization of FontAwesome imports.

The separation between regular and solid icons is well-structured, making it clear which icon variants are being used throughout the component.


38-38: LGTM! Improved tab bar spacing.

The added horizontal padding enhances the visual spacing between tab items.


129-133: LGTM! Consistent icon implementation.

The Messages and Contracts tabs maintain consistent icon sizing and styling patterns.

Also applies to: 145-149


Line range hint 107-123: Verify deep linking support for the create collaboration modal.

The current implementation prevents default tab navigation and pushes to a modal route. Ensure this pattern supports deep linking scenarios.

✅ Verification successful

Let me gather more information about the navigation setup and deep linking configuration.


Let me check one more thing about the navigation setup, particularly focusing on the modal routes and their configuration.


Deep linking support appears to be properly configured

The app has a URL scheme ("myapp") defined in app.json, which is a prerequisite for deep linking. The modal navigation pattern using router.push to "/(modal)/create-collaboration" is a standard approach in Expo Router, which inherently supports deep linking through its file-system based routing. The implementation follows the recommended patterns for modal presentation in Expo Router.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for deep linking configuration and modal route definition
rg -A 5 "create-collaboration" app/\(modal\)

Length of output: 639


Script:

#!/bin/bash
# Check for deep linking configuration in app config and navigation setup
rg -A 5 "linking|Linking" app.json app/\(_layout|expo-router\)
rg -A 5 "scheme" app.json

Length of output: 440


Script:

#!/bin/bash
# Check for modal route configuration and navigation setup
rg -A 10 "Stack.Screen.*create-collaboration" app/
rg -A 10 "Tabs.Screen.*create-collaboration" app/

Length of output: 104

components/explore-influencers/index.tsx (2)

10-11: LGTM: Theme integration follows best practices

The addition of theme support using React Navigation's useTheme hook and centralized color management is well-implemented.

Also applies to: 28-28


73-74: Verify the impact of reduced bottom padding

The bottom padding has been reduced from 100 to 16. Please verify that this doesn't affect the visibility of list items when used with bottom navigation or floating action buttons.

✅ Verification successful

Reduced bottom padding is safe to use

The reduced bottom padding from 100 to 16 is appropriate because:

  • The FlatList is wrapped in AppLayout which likely handles the main layout spacing
  • The BottomSheetActions component is rendered conditionally and uses absolute positioning with its own bottom spacing
  • The FlatList has proper item separation with 16px height between items
  • No fixed bottom navigation or floating buttons are present in the component that would require extra padding
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for bottom navigation or floating elements that might be affected
rg -t tsx -t jsx "position: *['\"]absolute['\"].*bottom:|bottom: *[0-9]" ./components/

Length of output: 120


Script:

#!/bin/bash
# Search for bottom navigation or floating elements with different pattern
rg "position.*absolute.*bottom|bottom:.*\d+" ./components/

# Also check for any FlatList components that might have similar padding patterns
rg "FlatList.*padding" ./components/

Length of output: 210


Script:

#!/bin/bash
# Let's check the context of the FlatList in the file under review
cat ./components/explore-influencers/index.tsx

# Also check if there are any bottom sheets or navigation components that might overlap
rg -A 5 "BottomSheetActions|BottomNavigation|TabBar" ./components/

Length of output: 11634

app/(onboarding)/onboarding-brand-preference.tsx (1)

93-98: Verify the skip flow implementation

Let's verify if skipping preferences is properly handled throughout the onboarding flow.

✅ Verification successful

Let me gather more information about the skip functionality and preferences handling.


Let me check one more aspect to understand the flow between screens and preference handling.


Based on the gathered information, I can now provide a final response about the skip flow implementation.

Skip functionality is properly implemented but needs documentation

The skip flow is correctly implemented with:

  • handleSignUp() function that calls firebaseSignIn with the current user's ID
  • Navigation flow from brand preferences to main app (/(main)/explore-influencers)
  • Proper state management through useAuthContext

However, for better maintainability:

  • Consider adding comments explaining the skip behavior's impact on user preferences
  • Document that skipped preferences can be updated later in app/(main)/(screens)/(menu)/preferences.tsx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other onboarding screens to understand the flow
rg -t tsx -l "AppLayout.*onboarding" app/

# Check if other screens handle skipped preferences
rg -A 5 "preferences" app/

Length of output: 1098


Script:

#!/bin/bash
# Check for skip-related functionality in onboarding
rg -A 5 "handleSignUp|onSkip" app/

# Look for preferences component implementation
ast-grep --pattern 'export default function Preferences() {
  $$$
}'

# Check for any preference state management
rg -A 5 "preferences.*State|usePreferences" app/

Length of output: 2770


Script:

#!/bin/bash
# Check for navigation and routing related to onboarding
rg -A 5 "router.push|router.replace|navigation" app/\(onboarding\)/

# Look for firebase-related preference handling
rg -A 5 "firebaseSignIn" app/

Length of output: 4487

app/(onboarding)/onboarding-get-started.tsx (2)

7-8: LGTM! Import organization follows good practices.

The reorganization places core React Native imports before third-party ones, which is a common convention.


86-92: Verify skip functionality impact on user onboarding

The skip button bypasses the survey data collection. Consider:

  1. Whether this affects any downstream features that might depend on this data
  2. If we should persist a "skipped" state to differentiate these users
✅ Verification successful

Skip functionality is safe to use

The skip button's implementation is appropriate as:

  • Survey data is only used for brand profiling and stored in the "brands" collection
  • No critical downstream features depend on this data
  • The handleSignUp() function still ensures proper user authentication
  • Users are correctly redirected regardless of survey completion

The survey appears to be optional analytics data rather than critical user information, making the skip functionality a valid user flow.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of survey data in the codebase
rg -l "survey\." --type ts --type tsx | xargs rg "survey\."

Length of output: 89


Script:

#!/bin/bash
# Search for survey-related patterns in TypeScript files
rg -t ts "survey" -i

# Search for any data persistence or state management related to onboarding
rg -t ts "onboarding.*state|onboarding.*data" -i

# Look for skip-related functionality in onboarding
rg -t ts "skip.*onboarding|onboarding.*skip" -i

Length of output: 545


Script:

#!/bin/bash
# Check the onboarding file content for survey data structure and usage
cat "app/(onboarding)/onboarding-get-started.tsx"

# Look for any state management or context files
fd -e ts -e tsx "(state|context|store)" --type f

# Search for any API or data persistence related to onboarding
rg -t ts "onboarding.*api|onboarding.*service|onboarding.*storage" -i

Length of output: 7164

components/proposals/Invitations.tsx (2)

1-20: LGTM! Clean and well-organized imports

The imports are properly structured and all are being utilized in the component.


142-189: LGTM! Well-structured FlatList implementation

The FlatList implementation is clean with proper refresh control and well-organized styling properties.

app/(onboarding)/onboarding-your-brand.tsx (3)

6-6: LGTM! Good choice using Pressable.

The switch to Pressable from TouchableOpacity is a good modernization. Pressable provides more flexibility and better control over touch interactions.


203-203: Same styling improvement applies here.

The same inline styles improvement suggested for the role selection applies to this industry selection implementation.

Also applies to: 208-219


Line range hint 1-250: Verify complete removal of Toast component.

The AI summary mentions the removal of the Toast component, but let's verify there are no remaining Toast-related imports or remnants in the codebase.

✅ Verification successful

Toast component has been properly migrated to Toaster

The codebase shows a consistent pattern where the old Toast component is only used as a wrapper in the app layout (layouts/app-layout/index.tsx), while all actual toast notifications are handled through the new Toaster utility (@/shared-uis/components/toaster/Toaster). This is the correct implementation as per the changes.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for any remaining Toast-related code
rg -i "toast" --type tsx --type ts

Length of output: 62


Script:

#!/bin/bash
# Search for any Toast or Toaster related code in all files
rg -i "toast"

Length of output: 3922

components/FilterModal.tsx (4)

10-12: LGTM: Icon library migration and prop updates

Clean migration from Ionicons to FontAwesome icons with proper typing.


113-117: LGTM: Clean icon implementation

Proper implementation of FontAwesome icon with theme-based colors.


121-123: Verify nested scrolling behavior

Using flex: 1 within a BottomSheet's ScrollView might cause nested scrolling issues. Consider testing the following scenarios:

  1. Content overflow behavior
  2. Interaction between BottomSheet drag and scroll
  3. Scroll gesture conflicts

101-106: Verify color contrast for accessibility

The handle indicator's visibility might be affected by the theme colors. Ensure sufficient contrast ratio between background and indicator colors for accessibility.

✅ Verification successful

Color contrast is sufficient for accessibility

Based on the Colors definition, the contrast is adequate:

  • Light theme: black text (#000) on white background (#fff)
  • Dark theme: white text (#fff) on black background (#000)

These combinations provide maximum contrast ratios (21:1), well above the WCAG AAA requirement of 7:1 for normal text.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other theme color usage patterns to compare
rg -g '*.{ts,tsx}' "Colors\(theme\)\.background.*Colors\(theme\)\.text" .

Length of output: 75


Script:

#!/bin/bash
# Let's search for the Colors utility function and theme color definitions
rg -g '*.{ts,tsx}' "export.*Colors.*theme" -A 10

Length of output: 50


Script:

#!/bin/bash
# Search for any color contrast or accessibility related tests
rg -g '*.{test,spec}.{ts,tsx}' -i "contrast|a11y|accessibility"

Length of output: 214


Script:

#!/bin/bash
# Look for the theme type definitions
fd -e ts -e tsx "theme|colors" --type f --exec rg -l "interface.*Theme|type.*Theme|export.*Colors"

Length of output: 130


Script:

#!/bin/bash
# Let's examine the theme definitions file we found
cat ./components/theme/Themed.tsx

Length of output: 1346


Script:

#!/bin/bash
# Search for any other usage of Colors in FilterModal
rg -g "FilterModal.tsx" "Colors\(theme\)" -B 2 -A 2

Length of output: 1663


Script:

#!/bin/bash
# Let's check the Colors constant definition
cat @/constants/Colors.ts || cat constants/Colors.ts

Length of output: 1600


Script:

#!/bin/bash
# Search for any theme-related configuration or setup
fd -e ts -e tsx -e js -e json "theme|colors" --type f --exec rg -l "defaultTheme|ThemeProvider|createTheme"

Length of output: 178

components/collaboration/collaboration-details/InvitationsTabContent.tsx (2)

214-214: Verify the cardId prop passed to BottomSheetActions

Passing the entire selectedInfluencer object as cardId may not be appropriate if BottomSheetActions expects an identifier. Ensure that the component expects an object; otherwise, pass the correct identifier.


99-99: ⚠️ Potential issue

Remove unnecessary semicolon after the if block

The semicolon after the closing brace of the if statement is unnecessary and could lead to syntax errors. It should be removed.

Apply this diff to fix the issue:

-};
+}

Likely invalid or redundant comment.

components/InfluencerCard.tsx (2)

125-128: ⚠️ Potential issue

Confirm the imageUrl utility function compatibility with Avatar.Image

The Avatar.Image component receives source as imageUrl(influencer.profilePic). Ensure that imageUrl returns an object compatible with the source prop expected by Avatar.Image, which typically requires an object like { uri: string }.

If imageUrl does not return the correct format, consider updating it or adjusting the usage.

Apply this diff if necessary:

<Avatar.Image
    size={50}
-   source={imageUrl(influencer.profilePic)}
+   source={{ uri: imageUrl(influencer.profilePic) }}
/>

26-31: Verify the imported module paths and component existence

Ensure that the imported modules such as CarouselNative, convertToKUnits, FontAwesomeIcon, and Tag are correctly installed and the paths are accurate. This prevents runtime errors due to missing modules or incorrect import paths.

Run the following script to verify the existence of the imported modules:

✅ Verification successful

All imported modules are correctly configured and available

  • CarouselNative exists at ./components/ui/carousel/carousel.tsx
  • convertToKUnits utility exists at ./utils/conversion.ts
  • Tag component exists at ./components/ui/tag/index.tsx
  • FontAwesomeIcon and its icons are properly installed (all required @FortAwesome packages are in package.json)
  • imageUrl utility exists at ./utils/url.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if the imported modules exist at the specified paths.

# Verify CarouselNative import
fd 'carousel.tsx' ./components

# Verify convertToKUnits import
fd 'conversion.ts' ./utils

# Verify Tag component import
fd 'tag.tsx' ./components/ui

# Verify FontAwesomeIcon module
npm ls @fortawesome/react-native-fontawesome

Length of output: 246


Script:

#!/bin/bash
# Let's verify the tag component and check its content
rg -g '*.tsx' -g '*.ts' 'export.*Tag' -A 2

# Check if FontAwesome icons are used elsewhere in the codebase
rg -g '*.tsx' -g '*.ts' '@fortawesome/.*-fontawesome'

# Check the actual content of the carousel component
cat "./components/ui/carousel/carousel.tsx"

# Check the content of conversion utility
cat "./utils/conversion.ts"

Length of output: 3659


Script:

#!/bin/bash
# Let's verify the Tag component's existence and implementation
cat "./components/ui/tag/index.tsx"

# Check if the imageUrl utility exists and its implementation
cat "./utils/url.ts"

# Verify FontAwesome icon package in package.json
cat package.json | grep -A 5 -B 5 "@fortawesome"

Length of output: 1829

app/(modal)/create-collaboration.tsx (4)

81-84: Good Practice: Added Input Validation for Adding Links

Adding validation to check that both newLinkName and newLinkUrl are filled before adding a link improves the robustness of the addLink function.


158-159: Verify Compatibility of the 'gap' Style Property

The gap property used in the contentContainerStyle of ScrollView might not be supported on all platforms or older versions of React Native. This could lead to layout issues on unsupported devices.

Please confirm that the gap property is compatible with all target platforms or consider using alternative styling methods, such as margin or padding, to ensure consistent spacing.


168-176: Ensure Back Button Visibility on All Platforms

The back navigation button is conditionally rendered only on web platforms:

Platform.OS === "web" && (
  <IconButton ... />
)

Verify that users on mobile platforms (iOS and Android) have an intuitive way to navigate back. If not, consider rendering the back button on all platforms or implementing platform-specific navigation solutions.


261-285: Ensure 'Select' Components Match Expected Selection Behavior

You've replaced RadioButton groups with Select components for Promotion Type, Collaboration Type, and Platform. If these fields are intended for single selection, ensure that the Select component is configured to allow only single selection to prevent user confusion.

Check if the Select component has a prop to enforce single selection or adjust the component to handle multiple selections appropriately.

Comment thread utils/conversion.ts
Comment on lines +1 to +6
export const convertToKUnits = (num: number) => {
if (num >= 1000) {
return `${(num / 1000).toFixed(1)}k`;
}
return num;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Handle edge cases for robust number formatting

While the basic implementation works, consider handling these edge cases:

  • Negative numbers
  • NaN/Infinity values
  • Decimal number inputs
 export const convertToKUnits = (num: number) => {
+  if (!Number.isFinite(num)) return 'N/A';
+  const absNum = Math.abs(num);
-  if (num >= 1000) {
-    return `${(num / 1000).toFixed(1)}k`;
+  if (absNum >= 1000) {
+    const sign = num < 0 ? '-' : '';
+    return `${sign}${(absNum / 1000).toFixed(1)}k`;
   }
-  return num;
+  return num.toString();
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const convertToKUnits = (num: number) => {
if (num >= 1000) {
return `${(num / 1000).toFixed(1)}k`;
}
return num;
};
export const convertToKUnits = (num: number) => {
if (!Number.isFinite(num)) return 'N/A';
const absNum = Math.abs(num);
if (absNum >= 1000) {
const sign = num < 0 ? '-' : '';
return `${sign}${(absNum / 1000).toFixed(1)}k`;
}
return num.toString();
};

Comment on lines +1 to 4
import React from "react";
import AppLayout from "@/layouts/app-layout";
import { stylesFn } from "@/styles/CollaborationHistory.styles";
import { useTheme } from "@react-navigation/native";
import React, { useState } from "react";
import { View, ScrollView, StyleSheet } from "react-native";
import {
TextInput,
Button,
Title,
Paragraph,
IconButton,
RadioButton,
} from "react-native-paper";
import ScreenHeader from "@/components/ui/screen-header";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Component name doesn't match the file name

The file is named CollaborationHistory.tsx but exports a component named CreateCollaborationScreen. This naming inconsistency could lead to confusion. Consider renaming either:

  • The component to CollaborationHistory to match the file name, or
  • The file to CreateCollaborationScreen.tsx to match the component name

Comment on lines 6 to 13
return (
<AppLayout>
<ScrollView style={styles.container}>
<View
style={{
flexDirection: "row",
alignItems: "center",
marginBottom: 16,
gap: 16,
}}
>
<BackButton />
<Title style={styles.title}>Collaboration History</Title>
</View>
</ScrollView>
<ScreenHeader
title="Collaboration History"
/>
</AppLayout>
);
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Component name inconsistent with its purpose

The component is named CreateCollaborationScreen but it's clearly a history view component based on:

  1. The rendered title "Collaboration History"
  2. The file name CollaborationHistory.tsx
  3. The existence of separate creation-related files (CreateCollaborationMap.tsx and CreateCollaborationForm.ts)

The component should be renamed to match its purpose:

  • Change the component name from CreateCollaborationScreen to CollaborationHistoryScreen
  • Update any imports/references accordingly
🔗 Analysis chain

Verify component purpose and functionality

The component name CreateCollaborationScreen suggests creation functionality, but it appears to be a history view based on the title "Collaboration History". This seems contradictory. Please verify:

  1. Is this meant to be a creation screen or a history view?
  2. If it's a creation screen, where is the creation functionality?
  3. If it's a history view, shouldn't the component be renamed?

Let's check for related components and usage:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for related collaboration components and their usage
echo "Searching for collaboration-related components..."
rg -l "Collaboration" --type tsx

echo "\nChecking for references to this component..."
rg "CreateCollaborationScreen" --type tsx

Length of output: 342


Script:

#!/bin/bash
# Search for related collaboration components and their usage with correct file extensions
echo "Searching for collaboration-related files..."
fd -e tsx -e ts "Collaboration"

echo "\nSearching for collaboration-related content..."
rg "Collaboration" -t ts -t tsx

echo "\nChecking component references..."
rg "CreateCollaborationScreen" -t ts -t tsx

Length of output: 919


Script:

#!/bin/bash
# Let's check the content of the file to understand its actual purpose
echo "Checking the full content of CollaborationHistory.tsx..."
cat "app/(main)/(screens)/CollaborationHistory.tsx"

echo "\nChecking create collaboration related files..."
cat "components/collaboration/create-collaboration/CreateCollaborationMap.tsx"
cat "constants/CreateCollaborationForm.ts"

Length of output: 3392

Comment on lines +1 to +23
import { stylesFn } from "@/styles/tag/Tag.styles";
import { useTheme } from "@react-navigation/native";
import { Chip, ChipProps } from "react-native-paper";

const Tag: React.FC<ChipProps> = ({
children,
...props
}) => {
const theme = useTheme();
const styles = stylesFn(theme);

return (
<Chip
style={styles.tag}
textStyle={styles.tagText}
{...props}
>
{children}
</Chip>
);
};

export default Tag;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Migration from Chip to Tag component is incomplete

The FilterModal.tsx still uses Chip directly from react-native-paper instead of the new Tag component. Found two instances:

  • Categories section using <Chip> for category selection
  • Job Types section using <Chip> for job type selection

Both instances should be migrated to use the new Tag component for consistency.

🔗 Analysis chain

Verify complete migration from Chip to Tag

The AI summary mentions this component replacing Chip in CollaborationCard. Let's verify the migration is complete.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any remaining direct Chip usage that should use Tag instead
rg -l "import.*Chip.*react-native-paper" | \
  xargs rg "<Chip" -l | \
  grep -v "components/ui/tag/index.tsx"

Length of output: 129


Script:

#!/bin/bash
# Check the usage of Chip in FilterModal.tsx to understand the context
rg -A 5 -B 5 "<Chip" components/FilterModal.tsx

Length of output: 941

Comment thread utils/url.ts
Comment on lines +1 to +15
export const imageUrl = (image: string | NodeRequire | undefined) => {
if (
image &&
typeof image === "string" &&
(image.startsWith("http") || image.startsWith("ph://"))
) {
return {
uri: image,
};
} else if (image) {
return image;
} else {
return require("@/assets/images/placeholder-image.jpg");
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider improving type safety and return type consistency.

The function has inconsistent return types which could lead to type-related issues downstream. Consider using a discriminated union type for the return value.

+type ImageSource = 
+  | { type: 'uri'; uri: string }
+  | { type: 'require'; source: NodeRequire };
+
-export const imageUrl = (image: string | NodeRequire | undefined) => {
+export const imageUrl = (image: string | NodeRequire | undefined): ImageSource => {
   if (
     image &&
     typeof image === "string" &&
     (image.startsWith("http") || image.startsWith("ph://"))
   ) {
-    return {
-      uri: image,
-    };
+    return { type: 'uri', uri: image };
   } else if (image) {
-    return image;
+    return { type: 'require', source: image as NodeRequire };
   } else {
-    return require("@/assets/images/placeholder-image.jpg");
+    return { type: 'require', source: require("@/assets/images/placeholder-image.jpg") };
   }
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const imageUrl = (image: string | NodeRequire | undefined) => {
if (
image &&
typeof image === "string" &&
(image.startsWith("http") || image.startsWith("ph://"))
) {
return {
uri: image,
};
} else if (image) {
return image;
} else {
return require("@/assets/images/placeholder-image.jpg");
}
};
type ImageSource =
| { type: 'uri'; uri: string }
| { type: 'require'; source: NodeRequire };
export const imageUrl = (image: string | NodeRequire | undefined): ImageSource => {
if (
image &&
typeof image === "string" &&
(image.startsWith("http") || image.startsWith("ph://"))
) {
return { type: 'uri', uri: image };
} else if (image) {
return { type: 'require', source: image as NodeRequire };
} else {
return { type: 'require', source: require("@/assets/images/placeholder-image.jpg") };
}
};

Comment on lines +101 to +104
const onImagePress = (data: any) => {
setSelectedImage(data); // TODO: data -> uri
setIsZoomed(true);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Resolve the TODO in onImagePress function

The onImagePress function contains a TODO comment indicating that data should be converted to uri. This suggests that data may not be in the correct format, which could lead to issues when displaying the zoomed image. Please ensure that data contains the correct image URI or extract the uri property before setting selectedImage.

Apply this diff to address the issue:

const onImagePress = (data: any) => {
-   setSelectedImage(data); // TODO: data -> uri
+   setSelectedImage(data.uri);
    setIsZoomed(true);
}

Comment on lines +106 to +112
useEffect(() => {
if (props?.alreadyInvited) {
props.alreadyInvited(props.influencer.id).then((invited) => {
setIsInvited(invited);
});
}
};

const renderMediaItem = ({ item, index }: any) => {
if (item.type === "image") {
return (
<TapGestureHandler
onHandlerStateChange={({ nativeEvent }) => {
if (nativeEvent.state === State.ACTIVE) {
handleImagePress(item.uri);
}
}}
>
<Animated.View>
<Image
source={{ uri: item.url || item.uri }}
style={styles.media}
/>
</Animated.View>
</TapGestureHandler>
);
} else {
return (
<Video
ref={(ref) => {
if (ref) {
videoRefs.current[index] = ref;
}
}}
source={
item.appleUrl
? {
uri: Platform.OS === "ios" ? item.appleUrl : item.playUrl,
}
: require("../assets/videos/ForBiggerJoyrides.mp4")
}
style={styles.media}
resizeMode={ResizeMode.COVER}
isLooping={false}
shouldPlay={false}
useNativeControls
onError={(error) => console.log("Video Error:", error)}
/>
);
}
};
}, []);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Include dependencies in the useEffect hook

The useEffect hook has an empty dependency array [], but it relies on props.alreadyInvited and props.influencer.id. If these props change, the effect won't re-run, and isInvited may not update accordingly. To ensure the invitation status reflects the current props, include them in the dependency array.

Apply this diff:

useEffect(() => {
    if (props?.alreadyInvited) {
        props.alreadyInvited(props.influencer.id).then((invited) => {
            setIsInvited(invited);
        });
    }
- }, []);
+ }, [props.alreadyInvited, props.influencer.id]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (props?.alreadyInvited) {
props.alreadyInvited(props.influencer.id).then((invited) => {
setIsInvited(invited);
});
}
};
const renderMediaItem = ({ item, index }: any) => {
if (item.type === "image") {
return (
<TapGestureHandler
onHandlerStateChange={({ nativeEvent }) => {
if (nativeEvent.state === State.ACTIVE) {
handleImagePress(item.uri);
}
}}
>
<Animated.View>
<Image
source={{ uri: item.url || item.uri }}
style={styles.media}
/>
</Animated.View>
</TapGestureHandler>
);
} else {
return (
<Video
ref={(ref) => {
if (ref) {
videoRefs.current[index] = ref;
}
}}
source={
item.appleUrl
? {
uri: Platform.OS === "ios" ? item.appleUrl : item.playUrl,
}
: require("../assets/videos/ForBiggerJoyrides.mp4")
}
style={styles.media}
resizeMode={ResizeMode.COVER}
isLooping={false}
shouldPlay={false}
useNativeControls
onError={(error) => console.log("Video Error:", error)}
/>
);
}
};
}, []);
useEffect(() => {
if (props?.alreadyInvited) {
props.alreadyInvited(props.influencer.id).then((invited) => {
setIsInvited(invited);
});
}
}, [props.alreadyInvited, props.influencer.id]);

Comment on lines +221 to +230
<TouchableOpacity
onPress={() => {
return router.push("/(main)/CollaborationHistory");
}}
>
<Text style={styles.jobHistory}>
{influencer.jobsCompleted} Jobs completed ({influencer.successRate}{" "}
success rate)
</Text>
</TouchableOpacity>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Pass influencer ID when navigating to collaboration history

When navigating to the CollaborationHistory screen, the influencer's ID should be included to display the correct data. Modify the route to pass the influencer's ID dynamically.

Apply this diff:

<TouchableOpacity
    onPress={() => {
-       return router.push("/(main)/CollaborationHistory");
+       return router.push(`/collaboration-history/${influencer.id}`);
    }}
>
    <Text style={styles.jobHistory}>
        {influencer.jobsCompleted} Jobs completed ({influencer.successRate}{" "}
        success rate)
    </Text>
</TouchableOpacity>

Ensure that the route /collaboration-history/[id] exists and is configured to handle the influencer ID.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +124 to +127
promotionType: promotionType[0].value,
collaborationType: collabType[0].value,
numberOfInfluencersNeeded: numInfluencers,
platform,
platform: platform[0].value,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential Runtime Error When Accessing Array Elements Without Checks

In the submitCollaboration function, you access promotionType[0].value, collabType[0].value, and platform[0].value without verifying that these arrays have at least one element. If any of these arrays are empty, this will cause a runtime error.

Ensure that these arrays are not empty before accessing their elements. Consider adding checks:

if (
  !collaborationName ||
  !aboutCollab ||
  !budgetMin ||
  !budgetMax ||
  !promotionType ||
  !collabType ||
  !numInfluencers ||
  !platform ||
  !location
) {
  Toaster.error("Please fill all fields");
  return;
}

+if (
+  promotionType.length === 0 ||
+  collabType.length === 0 ||
+  platform.length === 0
+) {
+  Toaster.error("Please select at least one option for Promotion Type, Collaboration Type, and Platform");
+  return;
+}

Also, before accessing the first element, you can add:

const promotionTypeValue = promotionType.length > 0 ? promotionType[0].value : null;

Repeat similar checks for collabType and platform.

Comment on lines +37 to +44
const [promotionType, setPromotionType] = useState<SelectItem[]>([]);
const [collabType, setCollabType] = useState<SelectItem[]>([]);
const [platform, setPlatform] = useState([
{
label: "Instagram",
value: "Instagram",
},
]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential Runtime Error When Accessing Elements in Empty Arrays

The state variables promotionType, collabType, and platform are initialized as arrays. Later in your code, you access their first elements without checking if they contain any items. If these arrays are empty, accessing promotionType[0].value will result in a runtime error.

To prevent this, ensure that these arrays are not empty before accessing their elements. You can initialize them with default values or add checks before accessing:

-const [promotionType, setPromotionType] = useState<SelectItem[]>([]);
+const [promotionType, setPromotionType] = useState<SelectItem[]>([PROMOTION_TYPES[0]]);

-const [collabType, setCollabType] = useState<SelectItem[]>([]);
+const [collabType, setCollabType] = useState<SelectItem[]>([COLLAB_TYPES[0]]);

-const [platform, setPlatform] = useState([
-  {
-    label: "Instagram",
-    value: "Instagram",
-  },
-]);
+const [platform, setPlatform] = useState([PLATFORM_TYPES[0]]);

Alternatively, modify your validation to ensure these arrays have at least one item before accessing them.

Committable suggestion skipped: line range outside the PR's diff.

@dev-rathore
dev-rathore merged commit 6c56a73 into master Nov 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants