-
Notifications
You must be signed in to change notification settings - Fork 24
feat: Add create and join group functionality #93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…isting ones. - A "Create Group" modal has been added to the home screen. - A new "Join Group" screen has been created where you can enter a join code. - The groups list on the home screen automatically refreshes after a group is created or joined.
✅ Deploy Preview for splitwizer canceled.
|
|
Important Review skippedBot user detected. To trigger a single review, invoke the You can disable this status message by setting the WalkthroughThis update introduces the initial codebase for a React Native frontend application using Expo. It adds configuration files, authentication and group management API clients, context providers, navigation stacks, and a suite of screen components for user authentication, group management, expense tracking, and profile editing. Backend changes include enhancements to expense schemas and service logic to track and validate the payer of expenses. Supporting files, dependencies, and a GitHub Actions workflow for EAS preview builds are also included. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App (Root)
participant AuthProvider
participant AppNavigator
participant API (Backend)
User->>App (Root): Launches App
App (Root)->>AuthProvider: Wrap children with Auth context
AuthProvider->>AppNavigator: Provide auth state (token, isLoading)
AppNavigator->>User: Show loading spinner (if isLoading)
AppNavigator->>User: Show AuthNavigator (if !token)
AppNavigator->>User: Show MainNavigator (if token)
User->>AuthNavigator: Login/Signup
AuthNavigator->>AuthProvider: Call login/signup
AuthProvider->>API (Backend): POST /login or /signup
API (Backend)-->>AuthProvider: Respond with user, token
AuthProvider->>AppNavigator: Update token, user
AppNavigator->>User: Show MainNavigator (on successful auth)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Join our Discord community for assistance with any issues or questions. 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 (
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #93 +/- ##
==========================================
+ Coverage 71.78% 71.86% +0.08%
==========================================
Files 17 17
Lines 1662 1667 +5
Branches 152 153 +1
==========================================
+ Hits 1193 1198 +5
Misses 416 416
Partials 53 53
🚀 New features to boost your workflow:
|
…nd group details screens based on your feedback. - **Equal Split Member Selection:** You can now select which members to include when splitting an expense equally. - **Optimized Settlements Summary:** The group details page now displays a summary of optimized settlements for you, showing who you need to pay and how much. - **Transaction-level Balance Display:** Each expense in the group details now shows your financial relationship to it (e.g., "You borrowed $30").
…s page. The previous implementation did not correctly display the scenario where you are owed money. This has been corrected. The summary now shows: - What you owe to others. - What others owe to you. - A "settled up" message when there are no outstanding debts.
- A "Friends" tab has been added to the main navigation. - The new screen displays a list of friends (users from shared groups). - For each friend, it shows the net balance aggregated across all shared groups. - Each friend item can be expanded to show a breakdown of balances per group. - The client-side logic fetches all group data and calculates these balances.
The error was a `TypeError` caused by incorrectly accessing the expenses array when calculating friend balances. This has been corrected. The client-side calculation logic is now more robust and handles cases where groups may not have any expenses.
- An "Account" tab has been added to the main navigation. - The new screen displays user information and a list of options. - You can now edit your profile information (name). - The logout functionality is accessible from this page. - Placeholders are included for future features like email settings and feedback.
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (11)
frontend/app.json (1)
3-4: Consider using more descriptive app name and slug.The generic "frontend" name and slug should be replaced with more descriptive values that reflect the app's purpose (e.g., "SplitWiser" based on the repository name).
- "name": "frontend", - "slug": "frontend", + "name": "SplitWiser", + "slug": "splitwiser",frontend/navigation/AccountStackNavigator.js (1)
11-11: Consider consistent naming convention.The screen name "AccountRoot" could be simplified to "Account" for consistency with other navigators in the app.
- <Stack.Screen name="AccountRoot" component={AccountScreen} options={{ headerShown: false }}/> + <Stack.Screen name="Account" component={AccountScreen} options={{ headerShown: false }}/>frontend/screens/AccountScreen.js (2)
24-24: Add null safety for avatar fallback.The avatar generation could fail if
user?.nameis an empty string, ascharAt(0)would return an empty string.-<Avatar.Text size={80} label={user?.name?.charAt(0) || 'A'} /> +<Avatar.Text size={80} label={user?.name?.charAt(0)?.toUpperCase() || 'A'} />
59-77: Fix inconsistent indentation in styles.The styling has inconsistent indentation that affects code readability.
const styles = StyleSheet.create({ container: { flex: 1, }, content: { padding: 16, }, profileSection: { alignItems: 'center', marginBottom: 24, }, name: { - marginTop: 16, + marginTop: 16, }, - email: { - marginTop: 4, - color: 'gray', - } + email: { + marginTop: 4, + color: 'gray', + }, });frontend/api/auth.js (1)
3-3: Consider environment-based API URL configuration.The hardcoded production URL makes it difficult to test against different environments during development.
-const API_URL = 'https://splitwiser-production.up.railway.app'; +const API_URL = process.env.REACT_NATIVE_API_URL || 'https://splitwiser-production.up.railway.app';Add environment configuration support by creating a
.envfile for different deployment environments.frontend/context/AuthContext.js (1)
30-38: Consider auto-login after successful signup.The signup function handles errors well, but users must manually navigate to login after signup. Consider auto-logging them in after successful registration for better UX.
const signup = async (name, email, password) => { try { await authApi.signup(name, email, password); + // Auto-login after successful signup + return await login(email, password); - return true; } catch (error) { console.error('Signup failed:', error.response?.data?.detail || error.message); return false; } };frontend/screens/JoinGroupScreen.js (1)
13-30: Enhance input validation with whitespace trimming.The validation logic is good, but consider trimming whitespace from the join code to handle user input errors gracefully.
const handleJoinGroup = async () => { - if (!joinCode) { + const trimmedJoinCode = joinCode.trim(); + if (!trimmedJoinCode) { Alert.alert('Error', 'Please enter a join code.'); return; } setIsJoining(true); try { - await joinGroup(token, joinCode); + await joinGroup(token, trimmedJoinCode); Alert.alert('Success', 'Successfully joined the group.'); onGroupJoined(); // Call the callback to refresh the groups list navigation.goBack(); } catch (error) { console.error('Failed to join group:', error); Alert.alert('Error', 'Failed to join group. Please check the code and try again.'); } finally { setIsJoining(false); } };frontend/screens/SignupScreen.js (1)
78-80: Disable navigation button during loading for better UX.The login navigation button should be disabled during the signup process to prevent user confusion.
<Button onPress={() => navigation.navigate('Login')} style={styles.button} disabled={isLoading}> Already have an account? Log In </Button>This change is already implemented correctly. Good job!
frontend/screens/HomeScreen.js (1)
39-56: Add group name validation and trim whitespace.Consider enhancing the group creation validation to handle edge cases better.
const handleCreateGroup = async () => { - if (!newGroupName) { + const trimmedName = newGroupName.trim(); + if (!trimmedName) { Alert.alert('Error', 'Please enter a group name.'); return; } + if (trimmedName.length > 50) { + Alert.alert('Error', 'Group name must be 50 characters or less.'); + return; + } setIsCreatingGroup(true); try { - await createGroup(token, newGroupName); + await createGroup(token, trimmedName); hideModal(); setNewGroupName(''); await fetchGroups(); // Refresh the groups listfrontend/screens/FriendsScreen.js (1)
71-76: Optimize API calls to reduce performance impact.The current implementation makes sequential API calls for each group, which could be slow with many groups. Consider batching or implementing pagination.
- const groupsWithDetails = await Promise.all( - groups.map(async (group) => { - const details = await getGroupDetails(token, group._id); - return { ...group, id: group._id, details }; - }) - ); + // Consider implementing a batch API endpoint or limiting concurrent requests + const batchSize = 5; // Limit concurrent requests + const groupsWithDetails = []; + + for (let i = 0; i < groups.length; i += batchSize) { + const batch = groups.slice(i, i + batchSize); + const batchResults = await Promise.all( + batch.map(async (group) => { + const details = await getGroupDetails(token, group._id); + return { ...group, id: group._id, details }; + }) + ); + groupsWithDetails.push(...batchResults); + }frontend/api/groups.js (1)
39-44: Consider consistency with actual usage patterns.The
getGroupDetailsfunction doesn't include settlements fetching, butGroupDetailsScreenneeds all three (members, expenses, settlements). Consider either:
- Adding settlements to this function
- Removing this function if it's not used consistently
- Clearly documenting the intended use case
export const getGroupDetails = (token, groupId) => { return Promise.all([ getGroupMembers(token, groupId), getGroupExpenses(token, groupId), + getOptimizedSettlements(token, groupId), ]); };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (6)
frontend/assets/adaptive-icon.pngis excluded by!**/*.pngfrontend/assets/favicon.pngis excluded by!**/*.pngfrontend/assets/icon.pngis excluded by!**/*.pngfrontend/assets/splash-icon.pngis excluded by!**/*.pngfrontend/frontend/package-lock.jsonis excluded by!**/package-lock.jsonfrontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (23)
frontend/.gitignore(1 hunks)frontend/App.js(1 hunks)frontend/api/auth.js(1 hunks)frontend/api/groups.js(1 hunks)frontend/app.json(1 hunks)frontend/context/AuthContext.js(1 hunks)frontend/frontend/package.json(1 hunks)frontend/index.js(1 hunks)frontend/navigation/AccountStackNavigator.js(1 hunks)frontend/navigation/AppNavigator.js(1 hunks)frontend/navigation/AuthNavigator.js(1 hunks)frontend/navigation/GroupsStackNavigator.js(1 hunks)frontend/navigation/MainNavigator.js(1 hunks)frontend/package.json(1 hunks)frontend/screens/AccountScreen.js(1 hunks)frontend/screens/AddExpenseScreen.js(1 hunks)frontend/screens/EditProfileScreen.js(1 hunks)frontend/screens/FriendsScreen.js(1 hunks)frontend/screens/GroupDetailsScreen.js(1 hunks)frontend/screens/HomeScreen.js(1 hunks)frontend/screens/JoinGroupScreen.js(1 hunks)frontend/screens/LoginScreen.js(1 hunks)frontend/screens/SignupScreen.js(1 hunks)
🧰 Additional context used
🧠 Learnings (6)
frontend/app.json (1)
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to ui-poc/openapi.json : The frontend must reference the API specification in ui-poc/openapi.json.
frontend/package.json (1)
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to ui-poc/openapi.json : The frontend must reference the API specification in ui-poc/openapi.json.
frontend/screens/FriendsScreen.js (1)
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Settlements must track debt resolution between users in the expense tracking logic.
frontend/screens/AddExpenseScreen.js (1)
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Support for different expense split types (equal, unequal, percentage-based) must be implemented in the expense tracking logic.
frontend/api/auth.js (1)
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : Backend services should be modular, with authentication and user registration in app/auth/, user profile management in app/user/, group management in app/groups/, and expense tracking in app/expenses/.
frontend/api/groups.js (1)
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : Backend services should be modular, with authentication and user registration in app/auth/, user profile management in app/user/, group management in app/groups/, and expense tracking in app/expenses/.
🧬 Code Graph Analysis (11)
frontend/index.js (1)
frontend/App.js (1)
App(6-14)
frontend/navigation/AuthNavigator.js (2)
frontend/screens/LoginScreen.js (1)
LoginScreen(6-57)frontend/screens/SignupScreen.js (1)
SignupScreen(6-83)
frontend/navigation/MainNavigator.js (3)
frontend/navigation/GroupsStackNavigator.js (1)
GroupsStackNavigator(10-19)frontend/screens/FriendsScreen.js (1)
FriendsScreen(8-140)frontend/navigation/AccountStackNavigator.js (1)
AccountStackNavigator(8-15)
frontend/screens/LoginScreen.js (4)
frontend/screens/SignupScreen.js (5)
password(9-9)isLoading(11-11)useContext(12-12)styles(85-101)frontend/context/AuthContext.js (4)
isLoading(9-9)AuthContext(4-4)AuthContext(4-4)login(17-28)frontend/navigation/AppNavigator.js (2)
useContext(9-9)styles(26-32)frontend/api/auth.js (2)
login(12-14)login(12-14)
frontend/screens/AccountScreen.js (1)
frontend/context/AuthContext.js (4)
AuthContext(4-4)AuthContext(4-4)logout(40-43)user(7-7)
frontend/screens/HomeScreen.js (4)
frontend/navigation/AppNavigator.js (1)
useContext(9-9)frontend/screens/JoinGroupScreen.js (1)
useContext(8-8)frontend/context/AuthContext.js (5)
AuthContext(4-4)AuthContext(4-4)isLoading(9-9)token(8-8)logout(40-43)frontend/api/groups.js (4)
getGroups(15-21)getGroups(15-21)createGroup(62-68)createGroup(62-68)
frontend/screens/FriendsScreen.js (3)
frontend/screens/GroupDetailsScreen.js (2)
expenses(11-11)fetchData(15-33)frontend/context/AuthContext.js (2)
user(7-7)token(8-8)frontend/api/groups.js (4)
getGroups(15-21)getGroups(15-21)getGroupDetails(39-44)getGroupDetails(39-44)
frontend/navigation/AccountStackNavigator.js (2)
frontend/screens/AccountScreen.js (1)
AccountScreen(6-57)frontend/screens/EditProfileScreen.js (1)
EditProfileScreen(7-57)
frontend/screens/SignupScreen.js (3)
frontend/screens/LoginScreen.js (5)
password(8-8)isLoading(9-9)useContext(10-10)styles(59-75)frontend/context/AuthContext.js (4)
isLoading(9-9)AuthContext(4-4)AuthContext(4-4)signup(30-38)frontend/api/auth.js (2)
signup(16-18)signup(16-18)
frontend/screens/AddExpenseScreen.js (2)
frontend/context/AuthContext.js (5)
AuthContext(4-4)AuthContext(4-4)isLoading(9-9)token(8-8)user(7-7)frontend/api/groups.js (4)
getGroupMembers(46-52)getGroupMembers(46-52)createExpense(31-37)createExpense(31-37)
frontend/api/auth.js (2)
frontend/api/groups.js (2)
API_URL(3-3)apiClient(8-13)frontend/context/AuthContext.js (3)
login(17-28)signup(30-38)token(8-8)
🔇 Additional comments (48)
frontend/app.json (1)
7-7: All referenced asset files are presentI’ve verified that the following assets exist under
frontend/assets/:
icon.pngsplash-icon.pngadaptive-icon.pngfavicon.pngNo further action required here.
frontend/.gitignore (1)
1-37: LGTM! Comprehensive .gitignore configuration.This .gitignore file properly covers all essential patterns for a React Native/Expo project, including build artifacts, dependencies, sensitive credential files, and platform-specific outputs. The clear sectioning makes it maintainable.
frontend/navigation/AccountStackNavigator.js (1)
1-17: LGTM! Clean navigation stack implementation.The AccountStackNavigator is well-implemented with proper screen configuration and header management. The screens correctly implement their own headers using Appbar components.
frontend/navigation/AuthNavigator.js (1)
1-17: LGTM! Well-structured authentication navigator.The AuthNavigator is properly implemented with efficient use of
screenOptionsto hide headers globally. The navigation flow between login and signup screens is correctly handled by the screen components themselves.frontend/index.js (1)
1-8: LGTM! Clean and standard Expo entry point.This follows Expo's recommended pattern for registering the root component. The comments are helpful and the implementation is correct.
frontend/App.js (1)
1-14: LGTM! Well-structured root component.The component correctly wraps the navigation with the necessary context providers in the proper order. The implementation follows React best practices with clean imports and appropriate provider nesting.
frontend/navigation/GroupsStackNavigator.js (1)
1-21: LGTM! Well-organized group navigation stack.The stack navigator is properly configured with logical screen mappings and appropriate header options. The screen names align well with the PR objectives of adding group creation and joining functionality.
frontend/navigation/MainNavigator.js (1)
1-44: LGTM! Clean bottom tab navigation setup.The tab navigator is well-structured with appropriate icon choices and proper integration of stack navigators. The global header hiding is appropriate since individual stack navigators manage their own headers.
frontend/navigation/AppNavigator.js (1)
1-34: LGTM! Proper authentication-aware navigation setup.The component correctly handles authentication state with appropriate loading indicators and conditional navigation rendering. The NavigationContainer wrapping and context usage follow React Navigation best practices.
frontend/screens/AccountScreen.js (3)
1-4: LGTM!Clean imports with proper React Native Paper components and AuthContext integration.
6-11: LGTM!Proper use of useContext hook and clean logout handler implementation.
13-15: LGTM!Good UX practice to show "Coming Soon" alerts for unimplemented features rather than broken functionality.
frontend/screens/LoginScreen.js (5)
1-4: LGTM!Proper imports with necessary React hooks, React Native components, and context integration.
6-10: LGTM!Clean state management and context usage following React best practices.
12-23: LGTM!Solid validation and error handling implementation with proper loading state management and user feedback.
28-35: LGTM!Good UX practices with proper keyboard type, auto-capitalization disabled for email, and accessible form controls.
43-51: LGTM!Excellent UX implementation with loading states, button disabling, and clear user feedback during authentication.
frontend/api/auth.js (3)
5-10: LGTM!Proper axios client configuration with appropriate base URL and content-type headers.
12-18: LGTM!Clean API function implementations that follow RESTful conventions and match the backend endpoints.
20-26: LGTM!Proper implementation of authenticated API call with Bearer token authorization header.
frontend/screens/EditProfileScreen.js (5)
1-5: LGTM!Proper imports with necessary React hooks, components, and API integration.
7-10: LGTM!Clean state initialization with proper default values from user context.
12-29: LGTM!Excellent form handling with validation, proper error handling, context updates, and user feedback. The try-catch-finally pattern ensures loading state is always reset.
39-44: LGTM!Clean form implementation with proper label and controlled input handling.
8-8: updateUserInContext implementation verifiedThe
updateUserInContextfunction is declared infrontend/context/AuthContext.jsand exposed via the provider’s value. No further changes are needed.
- Defined in frontend/context/AuthContext.js (as
const updateUserInContext = (updatedUser) => { setUser(updatedUser); };)- Consumed correctly in frontend/screens/EditProfileScreen.js
frontend/context/AuthContext.js (1)
17-28: LGTM! Proper error handling and state management.The login function correctly handles API responses, updates both token and user state, and provides appropriate error handling with meaningful error messages.
frontend/screens/JoinGroupScreen.js (1)
32-59: LGTM! Clean UI implementation with proper loading states.The UI components are well-structured with appropriate loading states and user feedback. The auto-capitalization for join codes is a nice UX touch.
frontend/screens/SignupScreen.js (1)
37-83: LGTM! Clean UI implementation with proper form handling.The form structure and styling are consistent with the app's design. The loading states and navigation flow work well together.
frontend/screens/HomeScreen.js (2)
20-31: LGTM! Proper API integration with error handling.The fetchGroups function correctly handles loading states, API errors, and provides user feedback through alerts.
95-119: LGTM! Excellent UI implementation with proper loading and empty states.The conditional rendering for loading states, pull-to-refresh functionality, and action buttons create a great user experience.
frontend/screens/FriendsScreen.js (2)
93-116: LGTM! Clean UI implementation with proper expandable lists.The rendering logic correctly handles balance display with appropriate color coding and expandable group details.
88-91: Good use of isFocused for data freshness.The useEffect properly refreshes data when the screen comes into focus, ensuring users see up-to-date balance information.
frontend/screens/GroupDetailsScreen.js (8)
1-6: LGTM!The imports are well-organized and all dependencies are properly utilized throughout the component.
7-13: LGTM!Component setup follows React best practices with proper prop destructuring and state initialization.
15-33: Excellent concurrent data fetching implementation.Great use of
Promise.allfor performance optimization and proper error handling with user-friendly alerts. The optional chaining forsettlementsResponse.data.optimizedSettlementsis a good defensive programming practice.
35-40: LGTM!The useEffect is properly implemented with correct dependencies and appropriate guards for token and groupId.
42-76: Well-implemented expense calculation logic.The balance calculation correctly determines the user's financial position for each expense. Good use of fallback values and proper currency formatting.
78-109: Comprehensive settlement summary implementation.The settlement calculation and display logic is well-implemented with clear visual indicators and handles the empty state appropriately.
111-162: Well-structured UI with good UX considerations.The render method properly handles loading states and includes thoughtful UX details like padding to avoid FAB overlap and empty state handling.
164-198: Clean and well-organized styles.The StyleSheet follows React Native best practices with appropriate flex layouts and positioning.
frontend/screens/AddExpenseScreen.js (6)
1-22: Comprehensive state management for multiple split methods.The imports and state initialization properly handle the complex requirements for different expense split types, aligning with the retrieved learning about supporting equal, unequal, and percentage-based splits.
23-54: Good initialization logic with defensive programming.The member fetching and state initialization is well-implemented. The guard
numMembers > 0properly prevents division by zero when calculating initial percentages.
56-123: Robust expense creation with comprehensive validation.Excellent implementation of complex split logic with proper validation for each method. The floating-point tolerance checks (0.01) and comprehensive error handling demonstrate good attention to detail.
125-180: Well-structured input handling for different split methods.The dynamic input rendering based on split method is cleanly implemented with proper controlled component patterns and consistent key extraction.
182-241: Clean UI implementation with proper state management.The render method handles loading and submission states well, providing good user experience with appropriate button states and loading indicators.
243-273: Clean and organized styles.The StyleSheet follows React Native best practices with consistent spacing and layout patterns.
frontend/api/groups.js (2)
15-37: Consistent API function implementation.All functions follow a consistent pattern with proper HTTP methods and JWT bearer token authorization. Good adherence to REST conventions.
46-76: Well-implemented CRUD operations.The remaining API functions maintain consistency in structure and properly handle authorization and data payloads for their respective operations.
- The groups list now shows an icon for each group, with a fallback to the group's first initial. - The group details screen also displays the icon in its header for a consistent user experience.
… the Android APK for the frontend application. The workflow is triggered on push to the main branch and can also be run manually. It performs the following steps: - Sets up the Node.js and Java environment. - Installs project dependencies. - Builds the Android APK using Expo Application Services (EAS). - Uploads the generated APK as a build artifact. An `eas.json` configuration file has also been added to the frontend project.
updates the version of upload artifact
…for pull requests using Expo Application Services (EAS). - The workflow is now triggered on `pull_request`. - It uses the `expo/expo-github-action` to simplify the setup of the Expo environment. - The build step has been changed from `eas build` to `eas update` to create a preview of the changes, which is faster and more efficient for reviewing pull requests. - The workflow file has been renamed to `preview.yml` to better reflect its purpose.
This reverts commit e554381.
|
🚀 Expo preview is ready!
|
… adds a feature to select who paid for an expense. - The "Exact Value" and "Percentage" split methods now correctly handle floating-point inaccuracies and rounding. - The "Split by Shares" calculation has been corrected to include rounding. - A new "Who Paid" selector has been added to the "Add Expense" screen, allowing you to select the payer from the list of group members.
…lity and adds a feature to select who paid for an expense." This reverts commit 4068a50.
…nhance split methods and auto-balance percentages
…e expense calculation; ensure proper handling of rounding errors
…e payer membership in group during expense creation
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (1)
.github/workflows/preview.yml (1)
11-12: Add a concurrency group to auto-cancel superseded previews.Without this, every push to the same PR queues a new EAS build—expensive and noisy. A minimal addition:
preview: runs-on: ubuntu-latest + concurrency: + group: preview-${{ github.event.pull_request.number }} + cancel-in-progress: true
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (9)
.github/workflows/preview.yml(1 hunks)backend/app/expenses/schemas.py(2 hunks)backend/app/expenses/service.py(2 hunks)frontend/app.json(1 hunks)frontend/eas.json(1 hunks)frontend/package.json(1 hunks)frontend/screens/AddExpenseScreen.js(1 hunks)frontend/screens/GroupDetailsScreen.js(1 hunks)frontend/screens/HomeScreen.js(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- frontend/eas.json
- frontend/package.json
🚧 Files skipped from review as they are similar to previous changes (3)
- frontend/app.json
- frontend/screens/HomeScreen.js
- frontend/screens/GroupDetailsScreen.js
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/{auth,user,groups,expenses}/**/*.py : Backend services should be modular, with authentication and user registration in app/auth/, user profile management in app/user/, group management in app/groups/, and expense tracking in app/expenses/.
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Support for different expense split types (equal, unequal, percentage-based) must be implemented in the expense tracking logic.
📚 Learning: applies to backend/app/expenses/**/*.py : settlements must track debt resolution between users in th...
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Settlements must track debt resolution between users in the expense tracking logic.
Applied to files:
backend/app/expenses/schemas.pybackend/app/expenses/service.py
📚 Learning: applies to backend/app/expenses/**/*.py : support for different expense split types (equal, unequal,...
Learnt from: CR
PR: Devasy23/splitwiser#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-07-26T09:41:01.332Z
Learning: Applies to backend/app/expenses/**/*.py : Support for different expense split types (equal, unequal, percentage-based) must be implemented in the expense tracking logic.
Applied to files:
backend/app/expenses/schemas.pybackend/app/expenses/service.pyfrontend/screens/AddExpenseScreen.js
🪛 actionlint (1.7.7)
.github/workflows/preview.yml
15-15: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
18-18: the runner of "actions/setup-node@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🔇 Additional comments (20)
.github/workflows/preview.yml (1)
32-36: Sanitise / simplify the EAS branch name.
github.event.pull_request.head.refcan contain slashes (e.g.feature/add-group) which EAS rejects. A safer pattern is to key the branch off the PR number:- command: eas update --auto --branch ${{ github.event.pull_request.head.ref }} + command: eas update --auto --branch pr-${{ github.event.pull_request.number }}Confirm whether branch names with
/work for your EAS project; if not, apply the change.backend/app/expenses/schemas.py (2)
31-31: LGTM! Proper field validation for paidBy.The addition of the
paidByfield with required validation and clear description follows good schema design practices.
95-95: LGTM! Consistent schema extension.The
paidByfield is properly added to the response schema, maintaining consistency with the request schema.backend/app/expenses/service.py (3)
66-74: Excellent validation logic for payer membership.The validation ensures that the selected payer is actually a member of the group before creating the expense. This prevents invalid expense records and maintains data integrity.
81-81: LGTM! Proper inclusion of paidBy field.The
paidByfield is correctly stored in the expense document, enabling proper tracking of who actually paid for the expense.
98-98: Correct settlement logic using actual payer.Using
expense_data.paidByinstead ofuser_idfor settlement creation ensures that settlements are calculated based on who actually paid, not who created the expense record. This aligns with proper expense splitting business logic.frontend/screens/AddExpenseScreen.js (14)
1-6: LGTM! Proper imports for expense creation functionality.The imports include all necessary React Native components, React hooks, and API functions for the expense creation workflow.
7-24: Well-structured state management for complex split functionality.The component properly manages state for different split methods including equal splits, exact amounts, percentages, and shares. The initialization of
payerIdas null until members load is a good pattern.
74-87: Comprehensive input validation for expense creation.The validation logic properly checks for required fields, valid payer selection, and numeric amount validation. The error messages are clear and user-friendly.
96-111: Good rounding logic for equal splits.The equal split calculation properly handles rounding by distributing any remainder to the first member, ensuring the total always matches the expense amount.
112-124: Proper validation for exact amount splits.The exact amount validation ensures the sum matches the total expense amount with appropriate tolerance for floating-point precision (0.01).
125-137: Good percentage split implementation.The percentage split logic properly validates that percentages sum to 100% and calculates amounts correctly with proper rounding.
138-166: Robust shares calculation with rounding adjustment.The shares implementation properly handles ratio calculations and adjusts for rounding errors by adding any difference to the first member.
168-175: Correct expense data structure for API.The expense data object includes all required fields including the new
paidByfield, properly aligning with the backend schema changes.
177-184: Proper error handling and navigation.The API call is properly wrapped in error handling with user-friendly alerts, and successful creation navigates back to the previous screen.
191-208: Smart auto-balancing for percentages.The
balancePercentagesfunction automatically adjusts the last member's percentage to ensure the total equals 100%, providing a good user experience.
210-268: Well-organized split input rendering.The
renderSplitInputsfunction properly handles different split methods with appropriate input types and validation. The switch statement is clean and handles all supported split types.
300-315: Good payer selection UI.The Menu component provides a clean interface for selecting the payer from group members, with proper state management for menu visibility.
318-328: Clear split method selection interface.The SegmentedButtons component provides an intuitive way to switch between different split methods with clear labels.
330-353: Helpful contextual guidance for users.The helper text for each split method provides clear instructions and real-time feedback (like current totals), improving the user experience.
…at/group-creation
for more information, see https://pre-commit.ci
- Upgrade actions/checkout and actions/setup-node to version 4 in preview.yml - Add caching for npm in Node.js setup - Introduce getUserBalanceSummary API call in groups.js - Improve percentage distribution logic in AddExpenseScreen.js to avoid floating-point errors - Fetch and display group settlement status in HomeScreen.js
…ns; refactor FriendsScreen and HomeScreen imports
Devasy
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
… size calculations, and generate detailed reports
This change adds the ability for users to create new groups and join existing ones.
Summary by CodeRabbit
New Features
Chores