Repository navigation
New profile changes - #43
Conversation
WalkthroughThe pull request introduces significant modifications across multiple components, primarily focusing on the Changes
Possibly related PRs
Suggested reviewers
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? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Outside diff range and nitpick comments (5)
components/explore-influencers/index.tsx (1)
87-95: Consider removing commented-out codeThe code contains several commented-out filtering conditions. Maintaining commented code can clutter the codebase and reduce readability. If these filters are no longer needed, consider removing them or adding comments to explain why they're commented out.
Also applies to: 103-105
components/InfluencerCard.tsx (1)
272-274: Avoid hardcoding job completion dataThe code is currently hardcoding
10 Jobs completed 100% success rate, which may display incorrect information to users. Consider using dynamic values frominfluencer.jobsCompletedandinfluencer.successRateinstead.Apply this diff to use dynamic data and remove the commented-out code:
- {/* {influencer.jobsCompleted} Jobs completed ({influencer.successRate}{" "} - success rate) */} - 10 Jobs completed 100% success rate + {influencer.jobsCompleted} Jobs completed ({influencer.successRate} success rate)utils/conversion.ts (1)
2-4: Ensure consistent return types inconvertToKUnitsfunctionCurrently, the function may return a number or a string, which can lead to type inconsistencies. Consider returning a string in all cases to maintain consistent return types.
Apply this diff to always return a string:
export const convertToKUnits = (num: number) => { if (Number.isNaN(num)) { - return 0; + return '0'; } if (num >= 1000) { return `${(num / 1000).toFixed(1)}k`; } - return num; + return num.toString(); };components/ui/bottom-sheet/BottomSheet.tsx (1)
33-38: Consider adding animation before closing.The current implementation immediately closes the sheet. Consider adding a smooth animation by using the
close()method's promise to delay theonClosecallback.const handleClose = () => { if (sheetRef.current) { - sheetRef.current.close(); + sheetRef.current.close().then(() => { + onClose(); + }); } - onClose(); };components/collaboration/collaboration-details/InvitationsTabContent.tsx (1)
120-128: Consider extracting profile transformation.The profile transformation logic should be moved to a utility function for reusability and testing.
+ const transformProfileImage = (image: string) => ({ + profile: { + attachments: [ + { + type: "image", + imageUrl: image, + }, + ] + } + }); <InfluencerCard type="invitation" alreadyInvited={checkIfAlreadyInvited} influencer={{ ...item, - profile: { - attachments: [ - { - type: "image", - imageUrl: item.profileImage, - }, - ] - } + ...transformProfileImage(item.profileImage) }}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (10)
components/InfluencerCard.tsx(9 hunks)components/collaboration/collaboration-details/ApplicationsTabContent.tsx(3 hunks)components/collaboration/collaboration-details/InvitationsTabContent.tsx(1 hunks)components/explore-influencers/index.tsx(4 hunks)components/ui/bottom-sheet/BottomSheet.tsx(1 hunks)constants/Influencer.ts(0 hunks)package.json(1 hunks)styles/InfluencerCard.styles.tsx(0 hunks)utils/conversion.ts(1 hunks)utils/text.ts(1 hunks)
💤 Files with no reviewable changes (2)
- styles/InfluencerCard.styles.tsx
- constants/Influencer.ts
🔇 Additional comments (4)
components/explore-influencers/index.tsx (1)
125-131:
Missing return statement in renderBackdrop function
The renderBackdrop function lacks a return statement, so it won't return the desired JSX element. You should include a return statement to ensure the backdrop renders correctly.
Apply this diff to fix the issue:
const renderBackdrop = (props: any) => {
+ return (
<BottomSheetBackdrop
{...props}
disappearsOnIndex={-1}
appearsOnIndex={0}
/>
+ );
};Likely invalid or redundant comment.
utils/text.ts (1)
1-5: LGTM!
The truncateText function is implemented correctly and effectively handles text truncation.
components/collaboration/collaboration-details/ApplicationsTabContent.tsx (1)
74-74: LGTM: Color handling improvement.
The change to use Colors(theme).primary instead of theme.colors.primary aligns with the app's color system.
components/collaboration/collaboration-details/InvitationsTabContent.tsx (1)
120-128: Verify profile image transformation logic.
The transformation of profileImage to an attachments array structure needs verification:
- Ensure
item.profileImageis always defined - Check if this structure matches what InfluencerCard expects
✅ Verification successful
Profile image transformation is correctly structured
The transformation matches the expected structure in InfluencerCard component:
- InfluencerCard accepts
profile.attachmentsand processes them viaprocessRawAttachment - The transformation from
profileImageto{ type: "image", imageUrl: item.profileImage }follows the correct attachment structure profileImageis used consistently across the codebase, including in user and manager contexts
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for profileImage usage and attachments structure
rg "profileImage|attachments.*type.*image" --type typescript --type javascript
# Search for InfluencerCard prop type definition
ast-grep --pattern 'interface $name {
$$$
profile?: {
$$$
}
$$$
}'
Length of output: 196
Script:
#!/bin/bash
# Search for profileImage and attachments with proper file extensions
rg "profileImage|attachments.*type.*image" -t ts -t tsx -t js -t jsx
# Search for InfluencerCard component usage and definition
rg "InfluencerCard" -t ts -t tsx -t js -t jsx -A 5
# Search for profile type definitions
ast-grep --pattern 'type $name = {
$$$
profile?: {
$$$
}
$$$
}'
ast-grep --pattern 'interface $name {
$$$
profile?: {
$$$
}
$$$
}'
Length of output: 336
Script:
#!/bin/bash
# Search for profileImage and attachments using ripgrep without file type filters
rg "profileImage|attachments.*type.*image"
# Search for InfluencerCard component and its usage
rg "InfluencerCard" -A 5
# Search for files containing both profile and attachments
rg "profile.*attachments|attachments.*profile" -A 3
Length of output: 7244
| "react-native-paper": "^5.12.5", | ||
| "react-native-reanimated": "~3.10.1", | ||
| "react-native-reanimated-carousel": "^3.5.1", | ||
| "react-native-render-html": "^6.3.4", |
There was a problem hiding this comment.
💡 Codebase verification
HTML content needs sanitization before rendering
The implementation in InfluencerCard.tsx directly renders HTML content from influencer?.profile?.content?.about without any sanitization, which could pose XSS risks. Key issues:
- Raw HTML is passed directly to
RenderHTMLcomponent without sanitization - No content validation or purification is implemented
- The truncation happens after the HTML content is processed
To fix this:
- Sanitize HTML content before passing it to
RenderHTML - Consider using the built-in
ignoredDomTagsorignoredStylesprops ofreact-native-render-html - Apply truncation after HTML has been sanitized but before rendering
🔗 Analysis chain
LGTM! Verify HTML sanitization implementation.
The addition of react-native-render-html is appropriate for the HTML rendering requirements. However, ensure proper HTML sanitization is implemented when using this library to prevent XSS attacks.
Let's verify the implementation and latest version information:
The previous script had issues with file type recognition. Let's try with modified search parameters and gather more context about the implementation and project setup.
The previous output showed that InfluencerCard.tsx likely contains the HTML rendering implementation. Let's examine its contents to verify the HTML sanitization approach.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for security advisories and verify implementation
# Check latest version and security advisories
gh api graphql -f query='
{
securityVulnerabilities(first: 5, ecosystem: NPM, package: "react-native-render-html") {
nodes {
advisory {
summary
severity
publishedAt
}
vulnerableVersionRange
firstPatchedVersion {
identifier
}
}
}
}'
# Search for usage to verify sanitization
rg -A 5 "RenderHTML|render-html" --type ts --type tsx
Length of output: 440
Script:
#!/bin/bash
# Search for RenderHTML usage with correct file type (TypeScript/React)
rg -A 5 "RenderHTML|render-html" --type typescript --type tsx
# Find all TypeScript/React files that might contain HTML rendering
fd "\.(tsx?|jsx?)$" | xargs rg -l "html|HTML"
# Check package.json for React Native version
cat package.json
Length of output: 3657
Script:
#!/bin/bash
# Let's check the specific implementation in InfluencerCard.tsx
cat components/InfluencerCard.tsx
# Also check for any HTML sanitization utilities or configurations
rg -l "sanitize|purify|clean.*html" --type-add 'ts:*.{ts,tsx}'
Length of output: 9621
| useEffect(() => { | ||
| setIsLoading(true); | ||
| const influencersRef = collection(FirestoreDB, "users"); | ||
| const q = query(influencersRef, where("profile.completionPercentage", ">=", 60)); | ||
|
|
||
| const unsubscribe = onSnapshot(q, (querySnapshot) => { | ||
| const fetchedInfluencers: User[] = []; | ||
| querySnapshot.forEach((doc) => { | ||
| fetchedInfluencers.push({ | ||
| ...doc.data(), | ||
| id: doc.id, | ||
| } as User); | ||
| }); | ||
|
|
||
| setInfluencers(fetchedInfluencers); | ||
| setIsLoading(false); | ||
| }); | ||
|
|
||
| return () => { | ||
| unsubscribe(); | ||
| }; | ||
| }, []); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add error handling to data fetching logic
Currently, the data fetching logic using onSnapshot does not handle errors. Consider adding an error callback to handle any errors that occur during data retrieval.
Apply this change to handle errors:
const unsubscribe = onSnapshot(
q,
(querySnapshot) => {
// existing success logic
const fetchedInfluencers: User[] = [];
querySnapshot.forEach((doc) => {
fetchedInfluencers.push({
...doc.data(),
id: doc.id,
} as User);
});
setInfluencers(fetchedInfluencers);
setIsLoading(false);
},
(error) => {
console.error("Error fetching influencers: ", error);
setIsLoading(false);
}
);| influencer={selectedInfluencer as User} | ||
| theme={theme} | ||
| isBrandsApp={true} | ||
| /> |
There was a problem hiding this comment.
Potential null reference exception with selectedInfluencer
selectedInfluencer is of type User | null, but it's being cast to User when passed to ProfileBottomSheet. If selectedInfluencer is null, this could cause a runtime error. Consider adding a null check before rendering ProfileBottomSheet.
Apply this change to prevent a null reference exception:
- <ProfileBottomSheet
- influencer={selectedInfluencer as User}
- theme={theme}
- isBrandsApp={true}
- />
+ {selectedInfluencer && (
+ <ProfileBottomSheet
+ influencer={selectedInfluencer}
+ theme={theme}
+ isBrandsApp={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.
| influencer={selectedInfluencer as User} | |
| theme={theme} | |
| isBrandsApp={true} | |
| /> | |
| {selectedInfluencer && ( | |
| <ProfileBottomSheet | |
| influencer={selectedInfluencer} | |
| theme={theme} | |
| isBrandsApp={true} | |
| /> | |
| )} |
| const snapPoints = React.useMemo( | ||
| () => [snapPointsRange[0], snapPointsRange[1]], | ||
| [] | ||
| ); |
There was a problem hiding this comment.
Add missing dependency to useMemo.
The snapPoints array is memoized but snapPointsRange is missing from the dependency array. This could cause 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]], | |
| [] | |
| ); | |
| const snapPoints = React.useMemo( | |
| () => [snapPointsRange[0], snapPointsRange[1]], | |
| [snapPointsRange] | |
| ); |
| bottomSheet: { | ||
| zIndex: 9999, | ||
| }, |
There was a problem hiding this comment.
💡 Codebase verification
The z-index value of 9999 is indeed high compared to other z-index values in the codebase
The codebase shows a consistent pattern of using z-index values between -1 and 100, with most values being 0, 1, or 2. The only exceptions are:
BottomSheet.tsxandBottomSheetActions.tsxboth using z-index: 9999UploadModal.styles.tsxusing z-index: 100
Recommendation:
- Consider reducing the z-index value to something more in line with the rest of the codebase, such as 100 or 200, unless there's a specific requirement for such a high value
- Document the reason if this high z-index must be maintained
🔗 Analysis chain
Review high z-index value.
The z-index of 9999 is extremely high and might cause issues with other overlays or modals in the app.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other z-index values in the codebase
rg -n "zIndex:|z-index:" --type css --type typescript --type javascript
Length of output: 108
Script:
#!/bin/bash
# Search for z-index values using ripgrep without file type restrictions
rg -n "zIndex:|z-index:"
Length of output: 1165
| jobsCompleted: 12, | ||
| successRate: 100, | ||
| }} | ||
| influencer={item} |
There was a problem hiding this comment.
Add type safety for influencer prop.
The item is passed directly to influencer prop without type checking. This could lead to runtime errors if the data structure changes.
+ type Influencer = {
+ id: string;
+ applicationID: string;
+ // Add other required fields
+ };
<InfluencerCard
type="application"
- influencer={item}
+ influencer={item as Influencer}Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Outside diff range and nitpick comments (3)
components/explore-influencers/index.tsx (3)
42-61: Consider consolidating filter statesThe multiple separate states for filters could be consolidated into a single filter state object for better maintainability and easier reset functionality.
- const [currentCollaborationType, setCurrentCollaborationType] = useState("All"); - const [currentInfluencerType, setCurrentInfluencerType] = useState("All"); - const [currentFollowersRange, setCurrentFollowersRange] = useState([0, 1000000]); - const [currentReachRange, setCurrentReachRange] = useState([0, 1000000]); - const [currentEngagementRange, setCurrentEngagementRange] = useState([0, 10000000]); + const [filters, setFilters] = useState({ + collaborationType: "All", + influencerType: "All", + followersRange: [0, 1000000], + reachRange: [0, 1000000], + engagementRange: [0, 10000000] + });
97-105: Clean up commented codeRemove or implement the commented filtering conditions. If these filters are planned for future implementation, consider adding a TODO comment with the ticket reference.
148-156: Extract loading styles to constantsConsider extracting the inline styles to a constants file or using a styled-components approach for better maintainability.
+ const styles = { + loadingContainer: { + flex: 1, + justifyContent: "center", + alignItems: "center", + }, + }; <View - style={{ - flex: 1, - justifyContent: "center", - alignItems: "center", - }} + style={styles.loadingContainer} >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
components/explore-influencers/index.tsx(4 hunks)
🔇 Additional comments (4)
components/explore-influencers/index.tsx (4)
68-89:
Add error handling to data fetching logic
The data fetching logic using onSnapshot still lacks error handling.
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const fetchedInfluencers: User[] = [];
querySnapshot.forEach((doc) => {
fetchedInfluencers.push({
...doc.data(),
id: doc.id,
} as User);
});
setInfluencers(fetchedInfluencers);
setIsLoading(false);
-});
+}, (error) => {
+ console.error("Error fetching influencers:", error);
+ setIsLoading(false);
+});272-276:
Potential null reference exception with selectedInfluencer
- <ProfileBottomSheet
- influencer={selectedInfluencer as User}
- theme={theme}
- isBrandsApp={true}
- />
+ {selectedInfluencer && (
+ <ProfileBottomSheet
+ influencer={selectedInfluencer}
+ theme={theme}
+ isBrandsApp={true}
+ />
+ )}219-235: 🛠️ Refactor suggestion
Add accessibility support
The List.Item components lack accessibility props. Add appropriate aria labels and roles for better screen reader support.
<List.Item
title="View Profile"
+ accessibilityLabel="View influencer profile"
+ accessibilityRole="button"
onPress={() => {
bottomSheetModalRef.current?.present();
ToggleModal();
}}
/>Likely invalid or redundant comment.
16-22: Verify Firebase initialization
Ensure that Firebase is properly initialized before using Firestore. The initialization typically happens in a separate configuration file.
✅ Verification successful
Firebase initialization is properly configured
The Firebase setup is correctly implemented:
- Firebase app is properly initialized in
utils/firebase.ts - Firestore instance is correctly initialized using the Firebase app in
utils/firestore.ts - The component imports
FirestoreDBwhich is a properly initialized Firestore instance
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for Firebase initialization
rg -l "initializeApp|firebase\.initializeApp"
Length of output: 90
Script:
#!/bin/bash
# Check the Firebase initialization implementation
cat utils/firebase.ts
Length of output: 268
Script:
#!/bin/bash
# Check if FirebaseApp is imported in the component
rg "import.*FirebaseApp.*from.*firebase" components/explore-influencers/index.tsx
# Check if FirestoreDB is properly initialized with FirebaseApp
cat utils/firestore.ts
Length of output: 274
| useEffect(() => { | ||
| filterInfluencers(); | ||
| }, [ | ||
| currentCollaborationType, | ||
| currentInfluencerType, | ||
| currentFollowersRange, | ||
| currentReachRange, | ||
| currentEngagementRange, | ||
| searchQuery, | ||
| influencers, | ||
| ]); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Optimize filter dependencies
The useEffect dependency array includes all filter states, which could cause unnecessary re-renders. Consider using useMemo for the filtered results or debouncing the filter operation.
+ const debouncedSearchQuery = useDebounce(searchQuery, 300);
useEffect(() => {
filterInfluencers();
}, [
currentCollaborationType,
currentInfluencerType,
- currentFollowersRange,
- currentReachRange,
- currentEngagementRange,
- searchQuery,
+ debouncedSearchQuery,
influencers,
]);Committable suggestion skipped: line range outside the PR's diff.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
components/FilterModal.tsx (2)
134-140: Consider improving the icon implementationThe current implementation could be enhanced for better maintainability and consistency:
- Icon size should be derived from theme or constants
- The conditional rendering could be simplified
Consider this refactoring:
- icon={() => localInfluencerType === category ? ( - <FontAwesomeIcon - color={Colors(theme).text} - icon={faCheckDouble} - size={14} - /> - ) : null} + icon={() => + localInfluencerType === category && ( + <FontAwesomeIcon + color={Colors(theme).text} + icon={faCheckDouble} + size={theme.iconSizes?.small ?? 14} + /> + ) + }
Line range hint
177-178: Fix incorrect value display and range in Reach and Engagement sectionsThere are two issues that need attention:
- The Reach section is incorrectly displaying followers range values instead of reach range values
- The Engagement range slider uses an incorrect maximum value (should be 0-100 as it's a percentage)
Apply these fixes:
- Min Reach: {localFollowersRange[0].toLocaleString() || "0"} + Min Reach: {localReachRange[0].toLocaleString() || "0"} - Max Reach: {localFollowersRange[1].toLocaleString() || "0"} + Max Reach: {localReachRange[1].toLocaleString() || "0"}And for the Engagement MultiSlider:
min={0} - max={1000000} + max={100} - step={1000} + step={1}Also applies to: 189-190
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
components/FilterModal.tsx(2 hunks)
🔇 Additional comments (2)
components/FilterModal.tsx (2)
10-10: LGTM: Clean import addition and interface update
The new icon import and interface property addition are well-structured and properly typed.
Also applies to: 28-28
Line range hint 91-91: Verify BottomSheet initial render behavior
While using index={isVisible ? 1 : -1} works for visibility control, ensure that the initial render doesn't cause any flickering when isVisible is false. Consider adding a enableDynamicSizing prop if the content height varies significantly.
* New profile changes (#43)
Summary by CodeRabbit
Release Notes
New Features
InfluencerCardwith new interactivity options for opening profiles and managing selected influencers.BottomSheetContainerfor improved modal interactions.truncateTextutility function for better text handling.ExploreInfluencers.ApplicationsTabContentandInvitationsTabContentcomponents to simplify influencer data handling.CollaborationFiltercomponent.Bug Fixes
convertToKUnitsfunction.Documentation
Chores