Skip to content

New profile UI changes - #44

Merged
dev-rathore merged 22 commits into
masterfrom
dev
Dec 9, 2024
Merged

dev-rathore merged 22 commits into
masterfrom
dev

Conversation

@dev-rathore

@dev-rathore dev-rathore commented Dec 9, 2024 •

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced CreateCollaboration, EditCollaborationScreen, and ScreenOne, ScreenTwo, ScreenThree components for collaboration management.
    • Added a loading indicator in the RenderMediaItem component.
    • New BottomSheetContainer component for modal bottom sheets.
  • Improvements

    • Enhanced InfluencerCard and CollaborationFilter components for better interactivity and visibility management.
    • Streamlined data handling in ApplicationsTabContent and InvitationsTabContent components.
  • Bug Fixes

    • Improved error handling in various components for better user experience.
  • Chores

    • Updated dependencies, including the addition of react-native-render-html.

@coderabbitai

coderabbitai Bot commented Dec 9, 2024 •

Copy link
Copy Markdown

Walkthrough

The pull request includes significant changes across multiple components related to collaboration management and influencer interactions. Key updates involve the TabLayout component's navigation logic, the introduction of new screens for creating and editing collaborations, and enhancements to the BottomSheetActions component for improved user interactions. Additionally, modifications to the InfluencerCard and various context providers streamline data handling and improve responsiveness. The overall structure and functionality of the application are preserved while introducing new features and refining existing ones.

Changes

File Path Change Summary
app/(main)/(drawer)/(tabs)/_layout.tsx Updated listeners prop for create-collaboration tab from router.push("/(modal)/create-collaboration") to router.push({ pathname: "/(modal)/create-collaboration" }).
app/(modal)/create-collaboration.tsx Refactored CreateCollaborationScreen to a single return statement rendering CreateCollaboration, removing all previous state management and UI elements related to collaboration creation.
app/(modal)/edit-collaboration.tsx Introduced new EditCollaborationScreen component that renders CreateCollaboration within AppLayout.
app/_layout.tsx Added BottomSheetModalProvider around existing context providers; updated presentation property for (modal)/create-collaboration from "modal" to "formSheet"; added new Stack.Screen for (modal)/edit-collaboration.
components/BottomSheetActions.tsx Added import for useRouter; initialized router with useRouter(). Added new List.Item for "Edit Collaboration" with navigation functionality.
components/FilterModal.tsx Updated CollaborationFilterProps to include isVisible; modified rendering logic to conditionally display a new icon for selected influencer types.
components/InfluencerCard.tsx Updated influencer prop type to User, added optional props openProfile and setSelectedInfluencer, and modified media data handling for CarouselNative.
components/collaboration/collaboration-details/ApplicationsTabContent.tsx Consolidated imports; added useBreakpoints for responsive design; simplified influencer data structure passed to InfluencerCard.
components/collaboration/collaboration-details/InvitationsTabContent.tsx Added useBreakpoints for responsive design; altered influencer data structure passed to InfluencerCard.
components/collaboration/collaboration-details/OverviewTabContent.tsx Added useBreakpoints for responsive design.
components/create-collaboration/index.tsx Introduced CreateCollaboration component for creating and editing collaborations, managing various state variables and user inputs.
components/create-collaboration/screen-one.tsx Added ScreenOne component for collaboration creation/editing UI with input fields and error handling.
components/create-collaboration/screen-two.tsx Added ScreenTwo component for collaboration location selection and link management.
components/create-collaboration/screen-three.tsx Added ScreenThree component to confirm collaboration posting/updating.
components/explore-influencers/index.tsx Enhanced ExploreInfluencers with new state management, data fetching from Firestore, and improved layout for responsiveness.
components/ui/bottom-sheet/BottomSheet.tsx Introduced BottomSheetContainer component for modal bottom sheet functionality.
components/ui/carousel/render-media-item.tsx Added loading indicator for images in RenderMediaItem component.
components/ui/screen-header/index.tsx Added optional hideAction property to ScreenHeaderProps interface to control action button visibility.
constants/Influencer.ts Introduced DUMMY_INFLUENCER constant for mock influencer profile data.
contexts/collaboration-context.provider.tsx Added createCollaboration and updateCollaboration methods to CollaborationContext for Firestore integration.
package.json Added new dependency: "react-native-render-html": "^6.3.4".
styles/InfluencerCard.styles.tsx Added new style for loading indicator and removed bio style.
utils/conversion.ts Modified convertToKUnits function to handle NaN input gracefully.
utils/text.ts Introduced truncateText function for string truncation with ellipsis.

Possibly related PRs

  • Firebase setup #2: Modifies the TabLayout component's navigation logic, related to changes in the BottomSheetActions component.
  • added firebase auth #7: Changes to the CreateCollaborationScreen are relevant to the added firebase auth PR, which introduces authentication logic affecting collaboration creation.
  • added integration #11: Updates to the CreateCollaborationScreen align with the added integration PR, involving modifications to the collaboration creation process.
  • Implementation for group creation after application is accepted #12: Focus on collaboration details relates to the Implementation for group creation after application is accepted PR, dealing with collaboration management.
  • Bug fix/UI feedback color changes #20: Restructuring of the RootLayout connects with the Feedbacks Resolved PR, involving layout and context provider adjustments.
  • Carousel for web #30: Updates to the InfluencerCard component are relevant to the Carousel for web PR, modifying media rendering within influencer cards.
  • Feedbacks Resolved #36: Enhancements to the CreateCollaborationScreen are related to the Feedbacks Resolved PR, addressing improvements in collaboration creation.
  • added constant and bottomsheetmodal #42: Addition of BottomSheetModalProvider is relevant to the added constant and bottomsheetmodal PR, introducing a bottom sheet modal context.
  • New profile changes #43: Changes regarding the InfluencerCard component connect to the New profile changes PR, updating influencer-related data handling.

Suggested reviewers

  • Manan-Sharma-5

Poem

🐇 In the meadow where ideas bloom,
Changes sprout, dispelling gloom.
Tabs now dance with a new route,
Collaborations flourish, there's no doubt!
With every click, a story grows,
In this vibrant world, creativity flows! 🌼


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between b18b395 and 2dfc60a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (24)
  • app/(main)/(drawer)/(tabs)/_layout.tsx (1 hunks)
  • app/(modal)/create-collaboration.tsx (1 hunks)
  • app/(modal)/edit-collaboration.tsx (1 hunks)
  • app/_layout.tsx (5 hunks)
  • components/BottomSheetActions.tsx (3 hunks)
  • components/FilterModal.tsx (2 hunks)
  • components/InfluencerCard.tsx (9 hunks)
  • components/collaboration/collaboration-details/ApplicationsTabContent.tsx (6 hunks)
  • components/collaboration/collaboration-details/InvitationsTabContent.tsx (4 hunks)
  • components/collaboration/collaboration-details/OverviewTabContent.tsx (2 hunks)
  • components/create-collaboration/index.tsx (1 hunks)
  • components/create-collaboration/screen-one.tsx (1 hunks)
  • components/create-collaboration/screen-three.tsx (1 hunks)
  • components/create-collaboration/screen-two.tsx (1 hunks)
  • components/explore-influencers/index.tsx (5 hunks)
  • components/ui/bottom-sheet/BottomSheet.tsx (1 hunks)
  • components/ui/carousel/render-media-item.tsx (6 hunks)
  • components/ui/screen-header/index.tsx (2 hunks)
  • constants/Influencer.ts (1 hunks)
  • contexts/collaboration-context.provider.tsx (2 hunks)
  • package.json (1 hunks)
  • styles/InfluencerCard.styles.tsx (1 hunks)
  • utils/conversion.ts (1 hunks)
  • utils/text.ts (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • app/(modal)/edit-collaboration.tsx
  • app/(modal)/create-collaboration.tsx
🔇 Additional comments (20)
components/ui/carousel/render-media-item.tsx (1)

2-2: LGTM! Loading state management is properly implemented.

The addition of ActivityIndicator and useState hook with proper state initialization follows React Native best practices.

Also applies to: 15-16, 42-42

components/ui/screen-header/index.tsx (3)

11-11: LGTM! Clean interface extension.

The new optional hideAction prop is well-typed and maintains backward compatibility.


19-19: LGTM! Sensible default value.

Setting hideAction = false as default maintains backward compatibility and existing behavior.


Line range hint 1-83: Verify the usage of hideAction in profile screens.

Since this PR involves profile UI changes, please ensure that the hideAction prop is used consistently across profile-related screens where the back/action button needs to be hidden.

✅ Verification successful

These scripts will help us understand:

  1. Where ScreenHeader is defined/imported
  2. Where ScreenHeader is actually used
  3. The context and props being passed to ScreenHeader instances

The hideAction prop is not being used in profile-related screens

Based on the search results, none of the profile-related screens (profile.tsx, brand-profile.tsx) are using the hideAction prop in their ScreenHeader components. The only usage of hideAction is in screen-one.tsx for the collaboration creation flow. This indicates that the back/action button is consistently shown in all profile screens, which is the expected navigation behavior.

  • app/(main)/(screens)/(menu)/profile.tsx: Uses default hideAction (false)
  • app/(main)/(screens)/(menu)/brand-profile.tsx: Uses default hideAction (false)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for ScreenHeader usage in profile-related files
rg -l "ScreenHeader" | rg -i "profile" | xargs rg "hideAction"

Length of output: 58


Script:

#!/bin/bash
# First, let's find all files that contain ScreenHeader
rg -l "ScreenHeader"

Length of output: 564


Script:

#!/bin/bash
# Let's also search for profile-related screens that might use ScreenHeader
rg -l "<ScreenHeader"

Length of output: 567


Script:

#!/bin/bash
# Search for actual usage of ScreenHeader component with its props
rg -A 3 "<ScreenHeader"

Length of output: 3511

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

24-24: LGTM: Responsive design enhancement

The addition of the useBreakpoints hook and extraction of the xl breakpoint value improves the component's responsive behavior.

Also applies to: 46-49


120-128: ⚠️ Potential issue

Add null checks and consider simplifying the data structure

The current transformation of the influencer data adds unnecessary nesting and could be prone to errors if item.profileImage is undefined.

Consider adding null checks and simplifying:

 influencer={{
   ...item,
   profile: {
     attachments: [
       {
         type: "image",
-        imageUrl: item.profileImage,
+        imageUrl: item.profileImage ?? null,
       },
     ]
   }
 }}

Also, verify if this nested structure is really necessary. If InfluencerCard can be modified to accept a simpler structure, that would be preferable.

✅ Verification successful

Based on the shell script results, I can now provide a final response:

The nested profile structure is required and matches the component's expectations

The InfluencerCard component explicitly uses this data structure in its carousel implementation:

data={influencer.profile?.attachments?.map((attachment) => processRawAttachment(attachment)) || []}

The transformation is necessary because:

  1. The component expects attachments in the profile structure
  2. The processRawAttachment utility is used to transform the attachments for display
  3. Proper null checks are already in place with optional chaining (?.)

However, you're right about adding a null check for profileImage. The current implementation in InvitationsTabContent.tsx should be kept but with a null check:

profile: {
  attachments: [
    {
      type: "image",
      imageUrl: item.profileImage || null,
    },
  ]
}
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check how InfluencerCard uses the profile.attachments structure
ast-grep --pattern 'profile?.attachments' 

Length of output: 43


Script:

#!/bin/bash
# Let's try to find the InfluencerCard component and see how it handles profile data
fd InfluencerCard --type f --exec cat {}

Length of output: 11665


Script:

#!/bin/bash
# Search for any usage of profile attachments with ripgrep for broader context
rg -A 5 "profile.*attachments" 

Length of output: 419


Script:

#!/bin/bash
# Look for profile image usage patterns in the codebase
rg -A 3 "profileImage|imageUrl" 

Length of output: 8603

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

11-11: LGTM! Import follows project conventions.


34-35: 🛠️ Refactor suggestion

Extract magic number to constants and consider additional breakpoints.

The fixed width of 768px should be defined in a constants file for better maintainability. Also, consider adding intermediate breakpoints for more granular control over the layout.

+ // In constants/layout.ts
+ export const CONTENT_WIDTH = {
+   tablet: 768,
+   desktop: 1024,
+ } as const;

// In component
- width: xl ? 768 : '100%',
+ width: xl ? CONTENT_WIDTH.tablet : '100%',

Let's check if similar magic numbers are used elsewhere:

components/InfluencerCard.tsx (6)

33-36: LGTM!

The new imports are necessary for the added functionalities and are correctly implemented.


41-41: LGTM!

Updating the influencer prop type to User enhances type safety and simplifies the prop definition.


46-47: LGTM!

The addition of optional props openProfile and setSelectedInfluencer improves the component's interactivity and state management.


65-65: LGTM!

Fetching the screenWidth using Dimensions.get("window").width ensures responsive design across different devices.


177-179: LGTM!

Properly setting the selected influencer when triggering the modal enhances user experience.


191-191: LGTM!

Processing the media attachments correctly prepares the data for the CarouselNative component.

styles/InfluencerCard.styles.tsx (1)

59-67: LGTM!

The new loadingIndicatorContainer style is correctly defined and will help with centering the loading indicator over the entire card.

contexts/collaboration-context.provider.tsx (1)

58-66: Verify the impact of context changes across the application.

The context API changes might affect other components using these methods.

Let's verify the usage:

✅ Verification successful

Context changes have been properly implemented across components

The verification shows that all components are correctly using the Collaboration Context:

  • create-collaboration/index.tsx uses all three methods (getCollaborationById, createCollaboration, updateCollaboration) through the context hook
  • notifications.tsx uses getCollaborationById through the context hook
  • No direct Firebase operations were found in the codebase
  • All components properly import and use the useCollaborationContext hook
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for components using collaboration context methods
echo "Searching for components using collaboration context..."
rg -l "useCollaborationContext|CollaborationContext.Provider" --type tsx

# Search for direct Firebase operations that should use context
echo "Checking for direct Firebase operations..."
rg -l "collection\(.*collaborations\)|doc\(.*collaborations\)" --type tsx

Length of output: 422


Script:

#!/bin/bash
# Search for components using collaboration context methods without file type restriction
echo "Searching for components using collaboration context..."
rg -l "useCollaborationContext|CollaborationContext.Provider"

# Search for direct Firebase operations that should use context
echo "Checking for direct Firebase operations..."
rg -l "collection\(.*collaborations\)|doc\(.*collaborations\)"

# Search for any imports or usage of collaboration-related functions
echo "Checking for collaboration-related imports and usage..."
rg -l "getCollaborationById|createCollaboration|updateCollaboration"

Length of output: 804


Script:

#!/bin/bash
# Let's check the actual usage of these methods in the components
echo "Checking usage in create-collaboration component..."
rg "getCollaborationById|createCollaboration|updateCollaboration" -C 3 "components/create-collaboration/index.tsx"

echo "\nChecking usage in notifications screen..."
rg "getCollaborationById|createCollaboration|updateCollaboration" -C 3 "app/(main)/(screens)/notifications.tsx"

echo "\nChecking context imports..."
rg "useCollaborationContext" -C 2 "components/create-collaboration/index.tsx" "app/(main)/(screens)/notifications.tsx"

Length of output: 3226

app/(main)/(drawer)/(tabs)/_layout.tsx (1)

107-109: Verify navigation state preservation

The change from direct string path to pathname object might affect the navigation state preservation. Ensure that:

  1. Back navigation works as expected
  2. Deep linking still functions correctly
  3. Navigation state is preserved across app reloads
✅ Verification successful

The previous script failed because the typescript file type wasn't recognized. Let's try searching across all files and also look for Link component usage to understand the navigation patterns better.


Navigation pattern is consistent with codebase usage

The codebase shows consistent usage of router.push with both string paths and pathname objects. The change to use pathname object for modal navigation is aligned with existing patterns, particularly for modal and onboarding routes (e.g., in onboarding-brand-preference.tsx). The navigation state preservation concerns are mitigated by Next.js's built-in handling of these navigation patterns.

  • Modal route pattern /(modal)/... is used consistently
  • Both string paths and pathname objects are used appropriately based on the navigation context
  • Back navigation and deep linking are handled by Next.js router's default behavior for both patterns
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other router.push usage patterns to ensure consistency
rg "router\.push\(" --type typescript

Length of output: 74


Script:

#!/bin/bash
# Search for router.push patterns across all files
rg "router\.push\("

# Also search for Link component usage as it's commonly used for navigation in Next.js
rg "import.*Link.*from.*next/link"

Length of output: 1764

app/_layout.tsx (1)

74-90: Verify provider order dependencies

The addition of BottomSheetModalProvider as the outermost provider needs verification:

  1. Check if it depends on any context from inner providers
  2. Verify if any inner providers require gesture handler context
✅ Verification successful

Provider order is correctly implemented

The BottomSheetModalProvider's placement is appropriate because:

  • GestureHandlerRootView is already present as the outermost wrapper in _layout.tsx
  • No context dependencies were found between BottomSheetModal and other providers
  • The only usage of BottomSheetModal is in explore-influencers component which doesn't depend on other contexts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for bottom sheet modal usage across the codebase
rg "useBottomSheetModal|BottomSheetModal" --type typescript

# Search for potential context dependencies
rg "useContext.*Bottom" --type typescript

Length of output: 175


Script:

#!/bin/bash
# Search for bottom sheet modal usage and context dependencies with proper file extensions
rg "useBottomSheetModal|BottomSheetModal" -g "*.{ts,tsx,js,jsx}"

# Search for potential context dependencies
rg "useContext.*Bottom" -g "*.{ts,tsx,js,jsx}"

# Look for imports to understand dependencies
rg "import.*BottomSheetModal" -g "*.{ts,tsx,js,jsx}"

# Search for gesture handler dependencies
rg "GestureHandlerRootView|gestureHandlerRootHOC" -g "*.{ts,tsx,js,jsx}"

Length of output: 1203

components/BottomSheetActions.tsx (1)

258-263: Verify collaboration ID type.

The navigation assumes cardId is a string, but the type allows it to be an object. Add type checking before navigation.

components/FilterModal.tsx (1)

10-10: LGTM: Clean import and prop additions

The new icon import and isVisible prop are well-structured and properly documented.

Also applies to: 27-27


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.

@dev-rathore
dev-rathore merged commit dcb68f0 into master Dec 9, 2024

@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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

Actionable comments posted: 25

🧹 Outside diff range and nitpick comments (24)
components/ui/carousel/render-media-item.tsx (2)

53-67: Consider adding accessibility attributes to the loading state.

While the loading indicator implementation is good, consider enhancing accessibility for screen readers.

 <View
   style={[
     styles.loadingIndicatorContainer,
     {
       display: isLoading ? "flex" : "none",
     }
   ]}
+  accessibilityRole="progressbar"
+  accessibilityLabel="Loading image"
+  accessibilityLiveRegion="polite"
 >
   {isLoading && <ActivityIndicator />}
 </View>

Also applies to: 78-79


112-113: Enhance video error handling and loading state feedback.

Consider providing more detailed error handling and user feedback for video loading failures.

 <Video
   // ... existing props
   onError={(error) => {
-    console.error("Video Error:", error)
+    console.error("Video Error:", error);
+    setIsLoading(false);
+    // Consider showing an error state UI
   }}
   onLoadStart={() => setIsLoading(true)}
   onLoad={() => setIsLoading(false)}
 />
components/collaboration/collaboration-details/ApplicationsTabContent.tsx (3)

20-22: Add proper TypeScript types for props and breakpoints.

Consider adding proper TypeScript interfaces for component props and breakpoint values.

+interface ApplicationsTabContentProps {
+  pageID: string;
+  collaboration: any; // Define proper type
+}

-const ApplicationsTabContent = (props: any) => {
+const ApplicationsTabContent: React.FC<ApplicationsTabContentProps> = (props) => {

74-74: Consider using theme.colors for consistency.

For better maintainability and consistency, consider using theme colors directly instead of the Colors utility.

-<ActivityIndicator size="large" color={Colors(theme).primary} />
+<ActivityIndicator size="large" color={theme.colors.primary} />

110-111: Consider using more flexible responsive design patterns.

The current implementation uses a fixed width for xl breakpoint. Consider using relative units or a more flexible approach.

-width: xl ? 768 : '100%',
+width: xl ? '80%' : '100%',
+maxWidth: 768,
components/ui/screen-header/index.tsx (1)

43-65: Simplify the action button implementation.

The current implementation has some redundant styling and could be more efficient.

Consider these improvements:

-      {
-        !hideAction && (
-          <Appbar.Action
-            icon={() => (
-              <View
-                style={{
-                  marginTop: 2,
-                }}
-                lightColor={Colors(theme).transparent}
-                darkColor={Colors(theme).transparent}
-              >
-                <FontAwesomeIcon
-                  icon={faArrowLeft}
-                  size={20}
-                  color={Colors(theme).text}
-                />
-              </View>
-            )}
-            color={Colors(theme).text}
-            onPress={handleAction}
-          />
-        )
-      }
+      {!hideAction && (
+        <Appbar.Action
+          style={{ marginTop: 2 }}
+          icon={({ size, color }) => (
+            <FontAwesomeIcon
+              icon={faArrowLeft}
+              size={20}
+              color={Colors(theme).text}
+            />
+          )}
+          onPress={handleAction}
+        />
+      )}

Changes:

  1. Removed redundant View wrapper
  2. Removed unnecessary transparent color settings
  3. Moved marginTop to Appbar.Action's style prop
  4. Simplified the conditional rendering structure
components/collaboration/collaboration-details/InvitationsTabContent.tsx (2)

158-159: LGTM: Good responsive design practice

The conditional width constraint and auto margins provide a better reading experience on larger screens. Consider extracting the magic number 768 to a constant for better maintainability.

+const MAX_CONTENT_WIDTH = 768;
+
 <FlatList
   style={{
-    width: xl ? 768 : '100%',
+    width: xl ? MAX_CONTENT_WIDTH : '100%',
     marginHorizontal: "auto",
   }}
 />

Line range hint 51-71: Improve error handling in handleCollaborationInvite

The current error handling only logs to console and shows a generic message. Consider:

  1. Adding specific error types and messages
  2. Cleaning up state in a consistent order
 try {
   setIsInviting(true);
   const invitationRef = collection(
     FirestoreDB,
     "collaborations",
     props.pageID,
     "invitations"
   );

   const invitationPayload = {
     userId: selectedInfluencer.influencerID,
     managerId: AuthApp.currentUser?.uid,
     collaborationId: selectedInfluencer.collaborationID,
     status: "pending",
     message: message,
   };

   await addDoc(invitationRef, invitationPayload);
   setIsMessageModalVisible(false);
   Toaster.success("Invitation sent successfully");
 } catch (error) {
-  console.error(error);
-  Toaster.error("Failed to send invitation");
+  console.error('Failed to send invitation:', error);
+  Toaster.error(error instanceof Error 
+    ? `Failed to send invitation: ${error.message}`
+    : "Failed to send invitation");
 } finally {
   setMessage("");
   setIsInviting(false);
+  setSelectedInfluencer(null);
 }
components/collaboration/collaboration-details/OverviewTabContent.tsx (2)

23-25: Consider adding type information for the breakpoint value.

While the code works correctly, adding type information would improve maintainability and provide better IDE support.

- const {
-   xl,
- } = useBreakpoints();
+ const {
+   xl
+ }: { xl: boolean } = useBreakpoints();

Line range hint 42-93: Review and update hardcoded values and duplicate content.

Several improvements needed in the content sections:

  1. The same description is used in both "Ad Description" and "About Brand" sections
  2. Platform is hardcoded to "Instagram"
  3. Payment verification shows a hardcoded "True"

Consider:

  • Using distinct content for each section
  • Making platform dynamic based on collaboration data
  • Using proper boolean rendering for payment verification
- <Paragraph style={styles.paragraph}>Instagram</Paragraph>
+ <Paragraph style={styles.paragraph}>{collaboration.platform}</Paragraph>

- <Paragraph style={styles.brandName}>True</Paragraph>
+ <Paragraph style={styles.brandName}>
+   {collaboration.paymentVerified ? "Yes" : "No"}
+ </Paragraph>
components/create-collaboration/index.tsx (1)

205-206: Provide user feedback on submission errors

In the catch block, errors are logged to the console, but the user is not informed about the error. Consider displaying an error message to the user to inform them that the submission failed.

Apply this diff to inform the user:

} catch (error) {
  console.error(error);
+ Toaster.error("Failed to submit collaboration. Please try again.");
}
components/explore-influencers/index.tsx (2)

97-106: Remove commented-out code or implement the filters

The filterInfluencers function contains several lines of commented-out code related to filters for followers, reach, and engagement ranges. Removing unused code can improve readability and maintainability. If these filters are planned for future implementation, consider adding a TODO comment.


273-273: Handle potential null for selectedInfluencer

The ProfileBottomSheet component receives selectedInfluencer without checking if it's null. While selectedInfluencer is set before opening the modal, adding a null check can prevent potential runtime errors.

Apply this diff to add a null check:

<ProfileBottomSheet
-  influencer={selectedInfluencer as User}
+  influencer={selectedInfluencer as User | undefined}
  theme={theme}
  isBrandsApp={true}
/>

And update the ProfileBottomSheet component to handle an undefined influencer.

utils/text.ts (1)

1-5: Consider handling cases where length is zero or negative

If length is zero or negative, the function will return the full text. Consider adding validation for length to ensure it is a positive integer, or handle these cases appropriately.

Apply this diff to validate length:

export const truncateText = (text: string, length: number) => {
  if (!text) return "";
+ if (length <= 0) return "";
  return text.length > length ? text.slice(0, length) + "..." : text;
};
components/create-collaboration/screen-three.tsx (2)

22-35: Add accessibility attributes to improve user experience.

The success screen should be more accessible to screen readers.

Apply these changes:

 <View style={styles.container3}>
   <FontAwesomeIcon
     icon={faCheckCircle}
     size={100}
     color={Colors(theme).primary}
     style={styles.checkIcon}
+    accessibilityRole="image"
+    accessibilityLabel="Success check mark"
   />
-  <Title style={styles.title}>
+  <Title style={styles.title} accessibilityRole="header">
     Collaboration {type === "Add" ? "Posted" : "Updated"}
   </Title>
-  <Text style={styles.description}>
+  <Text style={styles.description} accessibilityRole="text">
     Your collaboration has been successfully {type === "Add" ? "posted" : "updated"}.
   </Text>
 </View>

14-38: Consider making this a reusable success screen component.

This success screen pattern could be useful in other parts of the application.

Consider generalizing it into a reusable component:

interface SuccessScreenProps {
  title: string;
  description: string;
  iconSize?: number;
  onDismiss?: () => void;
}

const SuccessScreen: React.FC<SuccessScreenProps> = ({
  title,
  description,
  iconSize = 100,
  onDismiss,
}) => {
  // ... implementation
}
components/ui/bottom-sheet/BottomSheet.tsx (1)

33-38: Consider adding error handling for sheet ref

The handleClose function assumes the ref will always be valid. Consider adding error handling for cases where the ref might be null.

  const handleClose = () => {
+   try {
      if (sheetRef.current) {
        sheetRef.current.close();
      }
      onClose();
+   } catch (error) {
+     console.error('Failed to close bottom sheet:', error);
+     onClose(); // Ensure we still call onClose even if sheet closing fails
+   }
  };
app/_layout.tsx (1)

149-152: Document formSheet presentation mode impact

The change from 'modal' to 'formSheet' presentation mode will affect the user experience. Please:

  1. Document the reasoning behind this change
  2. Update relevant UI/UX documentation
  3. Consider adding a comment explaining the choice of 'formSheet'
components/create-collaboration/screen-two.tsx (1)

125-128: Add validation for link display.

The link rendering logic doesn't handle empty or malformed links, which could lead to rendering issues.

-            <Paragraph key={index + link.url}>
-              {link.name}: {link.url}
-            </Paragraph>
+            <Paragraph key={index + link.url}>
+              {link.name ? `${link.name}: ` : ''}{link.url || 'Invalid URL'}
+            </Paragraph>
components/create-collaboration/screen-one.tsx (1)

84-84: Uncomment multiline prop for better description input.

The commented multiline prop would improve the user experience for entering longer collaboration descriptions.

-          // multiline
+          multiline
+          numberOfLines={4}
components/BottomSheetActions.tsx (2)

Line range hint 19-24: Replace any types with proper interfaces.

The component uses any type for data and cardId props, which could lead to type-safety issues.

-  data?: any; // TODO: Update with the correct type
-  cardId?: any;
+  data?: {
+    collaboration?: {
+      id: string;
+      name: string;
+    };
+  };
+  cardId?: string | {
+    collaborationID: string;
+    applicationID: string;
+    influencerID: string;
+  };

254-265: Add loading state for navigation.

The edit collaboration navigation should show a loading state while the navigation is in progress.

+  const [isNavigating, setIsNavigating] = React.useState(false);
+
   // ... in the List.Item
              title="Edit Collaboration"
+             disabled={isNavigating}
              onPress={() => {
+               setIsNavigating(true);
                handleClose();
                router.push({
                  pathname: "/edit-collaboration",
                  params: {
                    id: cardId,
                  },
-               });
+               }).finally(() => setIsNavigating(false));
              }}
components/FilterModal.tsx (2)

Line range hint 92-92: Consider extracting the BottomSheet indices into constants

The -1 and 1 values used for the BottomSheet index could be extracted into named constants for better maintainability.

+ const BOTTOM_SHEET_STATES = {
+   HIDDEN: -1,
+   VISIBLE: 1,
+ } as const;

  <BottomSheet
    ref={sheetRef}
-   index={isVisible ? 1 : -1}
+   index={isVisible ? BOTTOM_SHEET_STATES.VISIBLE : BOTTOM_SHEET_STATES.HIDDEN}

Line range hint 177-178: Fix incorrect state usage in Reach range display

The Reach range display is incorrectly using localFollowersRange instead of localReachRange for min/max values.

  <Text style={styles.salaryLabel}>
-   Min Reach: {localFollowersRange[0].toLocaleString() || "0"}
+   Min Reach: {localReachRange[0].toLocaleString() || "0"}
  </Text>
🛑 Comments failed to post (25)
package.json (1)

68-68: 💡 Codebase verification

HTML content is not properly sanitized, potential security risk

The implementation in InfluencerCard.tsx directly renders HTML content from user profiles without any sanitization. The truncateText utility only handles string length and doesn't sanitize HTML content. This poses a potential XSS risk.

  • components/InfluencerCard.tsx: The RenderHTML component renders raw HTML from influencer?.profile?.content?.about without sanitization
  • No HTML sanitization utilities found in the codebase

Consider:

  • Using the tagsStyles and ignoredTags props in RenderHTML to restrict allowed HTML elements
  • Implementing HTML sanitization before rendering content
  • Using a sanitization library like DOMPurify or setting up proper content validation on the backend
🔗 Analysis chain

LGTM! But verify HTML content sanitization.

The addition of react-native-render-html is appropriate for rendering HTML content in the bio display. However, ensure proper content sanitization is implemented to prevent XSS attacks.

Let's verify the implementation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check how react-native-render-html is being used in InfluencerCard.tsx
# Specifically looking for sanitization options or dangerous props

# Search for RenderHTML usage
ast-grep --pattern 'RenderHTML {
  $$$
}'

# Search for any sanitization or security-related props
rg -A 5 'contentWidth|baseStyle|ignoredDomTags|ignoredStyles|enableExperimentalBRCollapsing' 

Length of output: 570


Script:

#!/bin/bash
# Let's examine the full implementation of InfluencerCard.tsx to understand the context
# and any potential sanitization measures

# Get the full content of InfluencerCard.tsx
cat components/InfluencerCard.tsx

# Also check for any custom sanitization utilities
rg -l "sanitize|xss|clean.*html|purify"

Length of output: 9638


Script:

#!/bin/bash
# Let's check the truncateText utility and any HTML processing
cat utils/text.ts

# Also check if there's any HTML sanitization in the project's utilities
fd -e ts -e js -x cat {} \; -p "utils/"

Length of output: 4910

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

27-27: 🛠️ Refactor suggestion

Define proper TypeScript interface for component props

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

interface InvitationsTabContentProps {
  pageID: string;
  // add other required props
}

const InvitationsTabContent = (props: InvitationsTabContentProps) => {
components/InfluencerCard.tsx (4)

119-131: 🛠️ Refactor suggestion

Refactor to reduce code duplication in onPress handlers

The onPress handlers in both Pressable components are identical. Consider extracting the logic into a separate function to avoid code duplication and improve maintainability.

Apply this refactor:

+const handleOpenProfile = () => {
+  if (props.openProfile) {
+    props.openProfile(influencer);
+  }
+};

<Pressable
  onPress={handleOpenProfile}
>
  <Avatar.Image
    size={50}
    source={imageUrl(influencer.profileImage)}
  />
</Pressable>

<Pressable
  style={styles.nameContainer}
  onPress={handleOpenProfile}
>
  <Text style={styles.name}>{influencer.name}</Text>
  <Text style={styles.handle}>{influencer.socials?.[0] || 'influencer-handle'}</Text>
</Pressable>

Also applies to: 132-142


207-207: ⚠️ Potential issue

Handle potential NaN values when converting backend data

If influencer.backend?.followers, reach, or rating are undefined, calling Number(undefined) will result in NaN, which may cause unexpected behavior in convertToKUnits. Consider providing default values to ensure reliable display.

Apply this fix:

-{convertToKUnits(Number(influencer.backend?.followers))}
+{convertToKUnits(Number(influencer.backend?.followers ?? 0))}

-{convertToKUnits(Number(influencer.backend?.reach))}
+{convertToKUnits(Number(influencer.backend?.reach ?? 0))}

-{influencer.backend?.rating}
+{influencer.backend?.rating ?? 'N/A'}

Also applies to: 217-217, 227-227


248-264: ⚠️ Potential issue

Ensure safe handling of about content when rendering HTML

If influencer?.profile?.content?.about is undefined, passing it to truncateText may result in an error. Provide a default empty string to prevent potential issues.

Apply this fix:

      html:
-        truncateText(influencer?.profile?.content?.about as string, 160) ||
-        "<p>No content available.</p>",
+        truncateText(influencer?.profile?.content?.about ?? '', 160) ||
+        "<p>No content available.</p>",
📝 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.

              <RenderHTML
                contentWidth={screenWidth}
                source={{
                  html:
                    truncateText(influencer?.profile?.content?.about ?? '', 160) ||
                    "<p>No content available.</p>",
                }}
                defaultTextProps={{
                  style: {
                    color: Colors(theme).text,
                    fontSize: 16,
                    lineHeight: 22,
                  },
                }}
              />
            </Text>
          </Pressable>

272-274: 🛠️ Refactor suggestion

Replace hardcoded job statistics with dynamic data

The job statistics are currently hardcoded. Use actual data from the influencer object to provide accurate information.

Apply this fix:

-10 Jobs completed 100% success rate
+{influencer.jobsCompleted} Jobs completed ({influencer.successRate}% success rate)

Ensure that jobsCompleted and successRate properties are available in the influencer object.

📝 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.

              {/* {influencer.jobsCompleted} Jobs completed ({influencer.successRate}{" "}
              success rate) */}
              {influencer.jobsCompleted} Jobs completed ({influencer.successRate}% success rate)
components/create-collaboration/index.tsx (4)

147-149: ⚠️ Potential issue

Handle the case when the user is not logged in

If the user is not logged in, the function logs an error but continues execution, which may lead to unexpected behavior. Consider returning early to prevent further execution.

Apply this diff to handle the case:

if (!AuthApp.currentUser) {
  console.error("User not logged in");
+ return;
}
📝 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.

      if (!AuthApp.currentUser) {
        console.error("User not logged in");
        return;
      }

151-164: 🛠️ Refactor suggestion

Validate budget inputs and ensure logical correctness

The current validation checks if budgetMin and budgetMax are non-empty strings, but does not validate whether they are valid numbers or if budgetMin is less than or equal to budgetMax. This could result in inconsistent or incorrect data. Consider adding validation to ensure that budgetMin and budgetMax are valid numbers and maintain logical consistency.

Apply this diff to enhance validation:

if (
  !collaborationName ||
  !aboutCollab ||
  !budgetMin ||
  !budgetMax ||
  !promotionType.length ||
  !collabType.length ||
  !numInfluencers ||
  !platform.length ||
  !location
) {
  Toaster.error("Please fill all fields");
  return;
}
+ if (isNaN(Number(budgetMin)) || isNaN(Number(budgetMax))) {
+   Toaster.error("Budget values must be valid numbers");
+   return;
+ }
+ if (Number(budgetMin) > Number(budgetMax)) {
+   Toaster.error("Minimum budget cannot be greater than maximum budget");
+   return;
+ }
📝 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.

      if (
        !collaborationName ||
        !aboutCollab ||
        !budgetMin ||
        !budgetMax ||
        !promotionType.length ||
        !collabType.length ||
        !numInfluencers ||
        !platform.length ||
        !location
      ) {
        Toaster.error("Please fill all fields");
        return;
      }
      if (isNaN(Number(budgetMin)) || isNaN(Number(budgetMax))) {
        Toaster.error("Budget values must be valid numbers");
        return;
      }
      if (Number(budgetMin) > Number(budgetMax)) {
        Toaster.error("Minimum budget cannot be greater than maximum budget");
        return;
      }

151-161: ⚠️ Potential issue

Validate that arrays have elements before submission

The current validation checks whether promotionType, collabType, and platform are truthy, but does not check if they have elements. An empty array is truthy in JavaScript, which may lead to runtime errors when accessing index 0. Consider validating that these arrays have at least one element before proceeding.

Apply this diff to enhance validation:

if (
  !collaborationName ||
  !aboutCollab ||
  !budgetMin ||
  !budgetMax ||
- !promotionType ||
- !collabType ||
- !numInfluencers ||
- !platform ||
  !location
+ !promotionType.length ||
+ !collabType.length ||
+ !numInfluencers ||
+ !platform.length ||
) {
  Toaster.error("Please fill all fields");
  return;
}
📝 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.

      if (
        !collaborationName ||
        !aboutCollab ||
        !budgetMin ||
        !budgetMax ||
        !promotionType.length ||
        !collabType.length ||
        !numInfluencers ||
        !platform.length ||
        !location
      ) {

187-190: ⚠️ Potential issue

Ensure arrays have elements before accessing index 0

The code assumes that promotionType, collabType, and platform arrays have at least one element by accessing index 0 directly. This may cause runtime errors if any of these arrays are empty. Consider adding checks or default values before accessing these arrays.

Apply this diff to prevent potential errors:

await handleCollaboration({
  //...
- promotionType: promotionType[0].value as PromotionType,
+ promotionType: promotionType[0]?.value as PromotionType,
- collaborationType: collabType[0].value as CollaborationType,
+ collaborationType: collabType[0]?.value as CollaborationType,
  //...
- platform: platform[0].value as SocialPlatform,
+ platform: platform[0]?.value as SocialPlatform,
  //...
});

Additionally, ensure that these arrays have elements before accessing them or provide default values if necessary.

Committable suggestion skipped: line range outside the PR's diff.

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

107-109: ⚠️ Potential issue

Ensure influencer.name is defined before calling toLowerCase()

If influencer.name is undefined or null, calling toLowerCase() will cause a runtime error. Consider adding a null check or a default value to prevent this error.

Apply this diff to handle undefined names:

const isSearchQueryMatch = influencer.name
-  .toLowerCase()
+  ?.toLowerCase()
   .includes(searchQuery.toLowerCase());

Or provide a default empty string:

const isSearchQueryMatch = (influencer.name || "")
  .toLowerCase()
  .includes(searchQuery.toLowerCase());
📝 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.

      const isSearchQueryMatch = influencer.name
        ?.toLowerCase()
        .includes(searchQuery.toLowerCase());
      const isSearchQueryMatch = (influencer.name || "")
        .toLowerCase()
        .includes(searchQuery.toLowerCase());
utils/conversion.ts (1)

2-4: 🛠️ Refactor suggestion

Handle non-finite numbers like Infinity

The function checks if num is NaN, but does not handle cases where num is Infinity or -Infinity. Consider using Number.isFinite(num) to ensure num is a finite number before proceeding.

Apply this diff to handle non-finite numbers:

export const convertToKUnits = (num: number) => {
-  if (Number.isNaN(num)) {
+  if (!Number.isFinite(num)) {
    return 0;
  }
📝 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.

  if (!Number.isFinite(num)) {
    return 0;
  }
constants/Influencer.ts (2)

4-9: ⚠️ Potential issue

Use obviously fake data for mock objects.

The current mock data contains realistic-looking personal information which could accidentally be committed or deployed.

Use clearly fake data:

-  name: "John Doe",
-  profileImage: "https://www.pngkey.com/png/full/114-1149878_setting-user-avatar-in-specific-size-without-breaking.png",
-  email: "johndoe@gmail.com",
-  phoneNumber: "1234567890",
-  location: "New York",
+  name: "MOCK_USER_NAME",
+  profileImage: "https://example.com/mock-avatar.png",
+  email: "mock.user@example.com",
+  phoneNumber: "000-000-0000",
+  location: "MOCK_LOCATION",
📝 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.

  name: "MOCK_USER_NAME",
  profileImage: "https://example.com/mock-avatar.png",
  email: "mock.user@example.com",
  phoneNumber: "000-000-0000",
  location: "MOCK_LOCATION",

52-55: ⚠️ Potential issue

Remove @ts-ignore and properly type the arrays.

Using @ts-ignore masks potential type issues that could cause runtime errors.

Fix the type issues:

-  //@ts-ignore
-  notifications: [],
-  //@ts-ignore
-  socials: [],
+  notifications: Array<never>,
+  socials: Array<never>,

Consider adding proper types if these arrays are expected to contain data in the future.

Committable suggestion skipped: line range outside the PR's diff.

contexts/collaboration-context.provider.tsx (3)

17-21: 🛠️ Refactor suggestion

Add loading and error states to the context.

The context should provide loading and error states for better UX.

Add state management to the interface:

 interface CollaborationContextProps {
+  loading: boolean;
+  error: Error | null;
   getCollaborationById: (id: string) => Promise<Collaboration>;
   createCollaboration: (collaboration: ICollaboration) => Promise<void>;
   updateCollaboration: (id: string, collaboration: Partial<ICollaboration>) => Promise<void>;
+  clearError: () => void;
 }
📝 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.

interface CollaborationContextProps {
  loading: boolean;
  error: Error | null;
  getCollaborationById: (id: string) => Promise<Collaboration>;
  createCollaboration: (collaboration: ICollaboration) => Promise<void>;
  updateCollaboration: (id: string, collaboration: Partial<ICollaboration>) => Promise<void>;
  clearError: () => void;
}

42-47: ⚠️ Potential issue

Add error handling and validation for collaboration creation.

The createCollaboration function lacks error handling and validation.

Implement proper error handling and validation:

 const createCollaboration = async (
   collaboration: ICollaboration,
 ): Promise<void> => {
+  try {
+    // Validate collaboration data
+    if (!collaboration.title || !collaboration.description) {
+      throw new Error('Missing required fields');
+    }
+
     const collaborationRef = collection(FirestoreDB, "collaborations");
-    await addDoc(collaborationRef, collaboration);
+    await addDoc(collaborationRef, {
+      ...collaboration,
+      createdAt: new Date().toISOString(),
+    });
+  } catch (error) {
+    console.error('Failed to create collaboration:', error);
+    throw error;
+  }
 }
📝 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.

const createCollaboration = async (
    collaboration: ICollaboration,
  ): Promise<void> => {
    try {
      // Validate collaboration data
      if (!collaboration.title || !collaboration.description) {
        throw new Error('Missing required fields');
      }

      const collaborationRef = collection(FirestoreDB, "collaborations");
      await addDoc(collaborationRef, {
        ...collaboration,
        createdAt: new Date().toISOString(),
      });
    } catch (error) {
      console.error('Failed to create collaboration:', error);
      throw error;
    }
  }

49-56: ⚠️ Potential issue

Add error handling and optimistic updates for collaboration updates.

The updateCollaboration function should handle errors and implement optimistic updates for better UX.

Implement error handling and optimistic updates:

 const updateCollaboration = async (
   id: string,
   collaboration: Partial<ICollaboration>,
 ): Promise<void> => {
+  try {
+    // Validate id
+    if (!id) {
+      throw new Error('Missing collaboration ID');
+    }
+
     const collaborationRef = doc(FirestoreDB, "collaborations", id);
+    
+    // Verify document exists
+    const docSnap = await getDoc(collaborationRef);
+    if (!docSnap.exists()) {
+      throw new Error('Collaboration not found');
+    }
 
-    await updateDoc(collaborationRef, collaboration);
+    await updateDoc(collaborationRef, {
+      ...collaboration,
+      updatedAt: new Date().toISOString(),
+    });
+  } catch (error) {
+    console.error('Failed to update collaboration:', error);
+    throw error;
+  }
 }

Committable suggestion skipped: line range outside the PR's diff.

components/ui/bottom-sheet/BottomSheet.tsx (2)

28-31: ⚠️ Potential issue

Add dependency array for snapPoints memoization

The useMemo hook is missing dependencies in its dependency array. This could lead to stale values if snapPointsRange changes.

  const snapPoints = React.useMemo(
    () => [snapPointsRange[0], snapPointsRange[1]],
-    []
+    [snapPointsRange]
  );
📝 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.

  const snapPoints = React.useMemo(
    () => [snapPointsRange[0], snapPointsRange[1]],
    [snapPointsRange]
  );

40-65: 🛠️ Refactor suggestion

Add accessibility support for modal interactions

The bottom sheet modal lacks proper accessibility attributes. Consider adding:

  • ARIA labels for the modal
  • Focus management
  • Screen reader support
  <Modal
    visible={isVisible}
    transparent
    animationType="fade"
    onRequestClose={handleClose}
+   accessible={true}
+   accessibilityLabel="Bottom sheet modal"
+   accessibilityRole="dialog"
  >

Committable suggestion skipped: line range outside the PR's diff.

app/_layout.tsx (1)

153-153: 🛠️ Refactor suggestion

Add consistent modal configuration

The new edit-collaboration route lacks the same modal configuration as create-collaboration. Consider applying consistent presentation options.

- <Stack.Screen name="(modal)/edit-collaboration" />
+ <Stack.Screen 
+   name="(modal)/edit-collaboration"
+   options={{
+     presentation: "formSheet",
+     gestureEnabled: true,
+   }}
+ />
📝 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.

          <Stack.Screen 
            name="(modal)/edit-collaboration"
            options={{
              presentation: "formSheet",
              gestureEnabled: true,
            }}
          />
components/create-collaboration/screen-two.tsx (2)

15-26: 🛠️ Refactor suggestion

Consider using a more specific type for the links array.

The links property in the data interface is typed as any[]. This could lead to runtime errors if the link objects don't match the expected structure.

-    links: any[];
+    links: Array<{
+      name: string;
+      url: string;
+    }>;
📝 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.

  data: {
    location: string;
    links: Array<{
      name: string;
      url: string;
    }>;
    mapRegion: {
      latitude: number;
      longitude: number;
      latitudeDelta: number;
      longitudeDelta: number;
    };
    newLinkName: string;
    newLinkUrl: string;
  };

142-155: ⚠️ Potential issue

Add URL validation for link inputs.

The link URL input field should validate the URL format before allowing submission.

         <TextInput
           label="Link URL"
           mode="outlined"
-          onChangeText={setState.newLinkUrl}
+          onChangeText={(text) => {
+            setState.newLinkUrl(text);
+            if (text && !text.match(/^(http|https):\/\/[^ "]+$/)) {
+              Toaster.error('Please enter a valid URL');
+            }
+          }}
           style={styles.input}
           value={data.newLinkUrl}
+          keyboardType="url"
         />
📝 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.

        <TextInput
          label="Link Name"
          mode="outlined"
          onChangeText={setState.newLinkName}
          style={styles.input}
          value={data.newLinkName}
        />
        <TextInput
          label="Link URL"
          mode="outlined"
          onChangeText={(text) => {
            setState.newLinkUrl(text);
            if (text && !text.match(/^(http|https):\/\/[^ "]+$/)) {
              Toaster.error('Please enter a valid URL');
            }
          }}
          style={styles.input}
          value={data.newLinkUrl}
          keyboardType="url"
        />
components/create-collaboration/screen-one.tsx (2)

185-197: 🛠️ Refactor suggestion

Enhance form validation.

The current validation only checks for empty fields. Consider adding more specific validation rules for each field type.

             if (
-              !data.collaborationName ||
-              !data.aboutCollab ||
-              !data.budgetMin ||
-              !data.budgetMax ||
-              !data.numInfluencers ||
-              !data.promotionType ||
-              !data.collabType ||
-              !data.platform
+              !data.collaborationName.trim() ||
+              !data.aboutCollab.trim() ||
+              !data.budgetMin || Number(data.budgetMin) <= 0 ||
+              !data.budgetMax || Number(data.budgetMax) <= Number(data.budgetMin) ||
+              !data.numInfluencers || data.numInfluencers < 1 ||
+              !data.promotionType.length ||
+              !data.collabType.length ||
+              !data.platform.length
             ) {
-              Toaster.error("Please fill all fields");
+              Toaster.error("Please fill all fields correctly");
📝 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.

            if (
              !data.collaborationName.trim() ||
              !data.aboutCollab.trim() ||
              !data.budgetMin || Number(data.budgetMin) <= 0 ||
              !data.budgetMax || Number(data.budgetMax) <= Number(data.budgetMin) ||
              !data.numInfluencers || data.numInfluencers < 1 ||
              !data.promotionType.length ||
              !data.collabType.length ||
              !data.platform.length
            ) {
              Toaster.error("Please fill all fields correctly");
              return;
            }

91-107: ⚠️ Potential issue

Add budget range validation.

The budget inputs should validate that the maximum budget is greater than the minimum budget.

           <TextInput
             label="Budget Max"
             mode="outlined"
-            onChangeText={(text) => setState.budgetMax(text)}
+            onChangeText={(text) => {
+              setState.budgetMax(text);
+              if (Number(text) <= Number(data.budgetMin)) {
+                Toaster.error('Maximum budget must be greater than minimum budget');
+              }
+            }}
             style={styles.budgetInput}
             textColor={Colors(theme).text}
             value={data.budgetMax}
+            keyboardType="numeric"
           />

Committable suggestion skipped: line range outside the PR's diff.

components/FilterModal.tsx (1)

134-140: 🛠️ Refactor suggestion

Optimize icon rendering and improve accessibility

The icon rendering logic could be optimized for performance and accessibility:

  1. The icon prop function is recreated on every render
  2. Missing accessibility label for the icon
+ const renderIcon = useCallback((category: string) => 
+   localInfluencerType === category ? (
+     <FontAwesomeIcon
+       color={Colors(theme).text}
+       icon={faCheckDouble}
+       size={14}
+       accessibilityLabel="Selected category"
+     />
+   ) : null
+ , [localInfluencerType, theme]);

  <Chip
-   icon={() => localInfluencerType === category ? (
-     <FontAwesomeIcon
-       color={Colors(theme).text}
-       icon={faCheckDouble}
-       size={14}
-     />
-   ) : null}
+   icon={() => renderIcon(category)}

Committable suggestion skipped: line range outside the PR's diff.

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.

3 participants