-
Notifications
You must be signed in to change notification settings - Fork 1
feat(profile): complete profile page and related pages #46
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
base: master
Are you sure you want to change the base?
Conversation
|
Warning Rate limit exceeded@FleetAdmiralJakob has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 0 minutes and 25 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
WalkthroughAdds a profile feature with an internal router and six profile screens, multiple new UI components (Button, Toggle, FAB, BottomNavigation, ProfileMenuItem), expands theme color tokens/types, updates pnpm workspace and packageManager, and applies small editor/tooling tweaks. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant App
participant ProfileApp as ProfileApp (ThemeProvider)
participant Router as ProfileAppContent
participant Profile as ProfileScreen
participant Limits as LimitsScreen
User->>App: Open /profile
App->>ProfileApp: Mount
ProfileApp->>Router: Render router
Router->>Profile: Render ProfileScreen (onNavigate)
User->>Profile: Tap "Limits"
Profile-->>Router: onNavigate("Limits")
Router->>Limits: Render LimitsScreen
User->>Limits: Interact (toggle / FAB / bottom nav)
sequenceDiagram
autonumber
actor User
participant Screen as AnyProfileScreen
participant BottomNav as BottomNavigation
Screen->>BottomNav: Render(activeTab, onTabPress)
User->>BottomNav: Tap "Insights"
BottomNav-->>Screen: onTabPress("Insights")
Screen->>Screen: Handle tab press (log or navigate)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
How to use the Graphite Merge QueueAdd the label merge-queue to this PR to add it to the merge queue. You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. |
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: 12
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/contexts/ThemeContext.tsx (1)
5-17: ThemeColors missing fields used elsewhere (secondary, backgroundText); new fields should be required.CardComponent reads colors.secondary and colors.backgroundText. Also make stroke/good/error non-optional since both palettes provide them.
interface ThemeColors { background: string cardBackground: string text: string textSecondary: string accent: string border: string success: string primary: string - stroke?: string - good?: string - error?: string + stroke: string + good: string + error: string + secondary: string + backgroundText: string } const lightColors: ThemeColors = { background: "#f5f5f5", cardBackground: "#ffffff", text: "#000000", textSecondary: "#666666", accent: "#00ff88", border: "#e0e0e0", success: "#00ff88", primary: "#007AFF", stroke: "#d1deeb", good: "#63b37e", - error: "#ea2b19" + error: "#ea2b19", + secondary: "#f0f4f8", + backgroundText: "#0f172a" } const darkColors: ThemeColors = { background: "#000000", cardBackground: "#1a1a1a", text: "#ffffff", textSecondary: "#a0a0a0", accent: "#00ff88", border: "#2a2a2a", success: "#4CAF50", primary: "#4A90E2", stroke: "#1c1c1c", good: "#63b37e", - error: "#ea2b19" + error: "#ea2b19", + secondary: "#1f2937", + backgroundText: "#e5e7eb" }Also applies to: 24-36, 38-50
🧹 Nitpick comments (41)
.vscode/settings.json (1)
4-4: Potential typo in custom dictionary ("Verticborder").If this isn’t an intentional token, correct/remove to keep spell‑check noise low.
Apply:
- "Verticborder" + "VerticalBorder"src/components/AppText.tsx (3)
11-12: Type the style prop correctly for strict mode.Use React Native’s StyleProp instead of object.
Apply:
-import { Text } from "react-native" +import { Text } from "react-native" +import type { StyleProp, TextStyle } from "react-native" @@ - style?: object + style?: StyleProp<TextStyle>
24-33: Avoid loading fonts in every AppText render tree.Per-instance useFonts can cause jank when many texts mount. Prefer loading once at app root and gating the app until loaded (e.g., in your root layout or provider), then assume fontsLoaded here.
43-55: Font selection/merging looks good.The style array with fontFamily first is correct; NativeWind className remains effective. Minor nit: spacing in
{ fontFamily}.- { fontFamily}, + { fontFamily },src/components/Button.tsx (1)
21-37: Remove inline color override; rely on NativeWind classes.
style={{ color: undefined }}is unnecessary and violates the “avoid inline styles” guideline.Apply:
- <AppText - semibold - className={`text-base ${ - disabled ? "text-gray-200" : "text-white" - } ${textClassName}`} - style={{ color: undefined }} - > + <AppText + semibold + className={`text-base ${ + disabled ? "text-gray-200" : "text-white" + } ${textClassName}`} + >Also consider adding
accessibilityRole="button"andaria-disabled={disabled}for better a11y.src/components/AccountItem.tsx (2)
26-45: Rename H_size/W_size to camelCase and consider extracting IconWrapper.Use conventional prop names and dedupe: similar wrappers exist across multiple screens.
Apply:
- const IconWrapper = ({ - children, - H_size = 40, - W_size = 60, + const IconWrapper = ({ + children, + height = 40, + width = 60, }: { children: React.ReactNode - H_size?: number - W_size?: number + height?: number + width?: number }) => ( <View className="rounded-2xl items-center justify-center" style={{ - width: W_size, - height: H_size, + width, + height, backgroundColor: colors.border, }} >And update call sites accordingly.
56-59: Prefer Tailwind classes for static dimensions/margins.You already use tw classes; keep inline styles only for theme colors. Dimensions like padding/margins can stay in className.
package.json (1)
27-27: Remove unused @react-navigation deps or justify keeping themExpo Router is the app router (package.json "main": "expo-router/entry", dep "expo-router": "~5.0.6"; src/app/* import expo-router — e.g. src/app/_layout.tsx, src/app/index.tsx). I found no direct imports/usages of @react-navigation in source, but package.json still lists "@react-navigation/bottom-tabs" and "@react-navigation/native" (package.json lines 26–27).
- If unused: remove those package.json entries (lines 26–27) and update the lockfile.
- If intentional: document why and ensure peer deps are aligned (gesture-handler, reanimated, screens, safe-area-context).
src/components/profile/Limits.tsx (3)
2-2: Type icon source precisely.Use ImageSourcePropType instead of any.
-import { ScrollView, StatusBar, SafeAreaView, Image, View } from "react-native" +import { ScrollView, StatusBar, SafeAreaView, Image, View, ImageSourcePropType } from "react-native" ... - }: { - source: any + }: { + source: ImageSourcePropTypeAlso applies to: 21-25
45-45: Copy update.Pluralize “Limit”.
- <Header title="Julia's - Limit" /> + <Header title="Julia's - Limits" />
16-35: Deduplicate IconWrapper across profile screens.Extract a shared IconWrapper to reduce repetition and ensure consistent sizing/colors.
src/components/Header.tsx (2)
11-11: Avoid createAnimatedComponent(Animated.View); just use Animated.View.Simpler and less error‑prone with Reanimated 3.
-const AnimatedView = Animated.createAnimatedComponent(Animated.View) +const AnimatedView = Animated.ViewAlso applies to: 29-31, 48-48
31-35: Use themed border color, not hardcoded Tailwind color.Keeps light/dark parity.
- className="absolute top-0 left-0 right-0 flex-row items-center justify-center space-x-4 py-6 px-6 border-b border-gray-800" - style={[ - headerAnimatedStyle, - { backgroundColor: colors.cardBackground }, - ]} + className="absolute top-0 left-0 right-0 flex-row items-center justify-center space-x-4 py-6 px-6 border-b" + style={[ + headerAnimatedStyle, + { backgroundColor: colors.cardBackground, borderColor: colors.border }, + ]}src/components/DashboardAccount.tsx (1)
24-26: Prefer Tailwind class for static flex; keep dynamic color in style.Aligns with styling guideline.
- <SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}> + <SafeAreaView className="flex-1" style={{ backgroundColor: colors.background }}>src/components/FloatingActionButton.tsx (2)
8-9: Remove unused import.-import AppText from "./AppText"
36-47: Add basic accessibility.<TouchableOpacity className="w-full h-full items-center justify-center" onPress={onPress} onPressIn={handlePressIn} onPressOut={handlePressOut} activeOpacity={1} + accessibilityRole="button" + accessibilityLabel="Add" >src/components/BottomNavigation.tsx (3)
41-45: Inactive label color equals active — fix visual state.- <AppText - className="mt-1 text-xs" - style={{ color: isActive ? colors.text : colors.text }} - > + <AppText + className="mt-1 text-xs" + style={{ color: isActive ? colors.text : colors.textSecondary }} + >
2-2: Tighten icon type.-import { View, TouchableOpacity, Image } from "react-native" +import { View, TouchableOpacity, Image, ImageSourcePropType } from "react-native" ... - iconSource: any + iconSource: ImageSourcePropTypeAlso applies to: 21-25
28-46: Accessibility: expose tab role and selected state.- <TouchableOpacity + <TouchableOpacity className="flex-1 items-center py-3" onPress={() => onTabPress(tab)} + accessibilityRole="tab" + accessibilityState={{ selected: isActive }} + accessibilityLabel={label} >src/components/profile/Notification.tsx (3)
49-50: Copy fix (user name + plural).- <Header title="Jutia's - Notification" /> + <Header title="Julia's - Notifications" />
51-58: Use class for width instead of inline "100%".- <View - className="mx-auto mt-10 flex-row items-center rounded-xl border px-4 py-3" - style={{ - backgroundColor: colors.cardBackground, - borderColor: colors.border, - width: "100%", - }} - > + <View + className="mx-auto mt-10 w-full flex-row items-center rounded-xl border px-4 py-3" + style={{ + backgroundColor: colors.cardBackground, + borderColor: colors.border, + }} + >
17-36: Deduplicate IconWrapper across profile screens.src/components/Toggle.tsx (3)
1-2: Import useEffect for prop-sync.-import type React from "react" +import type React from "react" +import { useEffect } from "react"
45-47: Remove conflicting static bg-white; color is themed via style.- className="h-4 w-4 rounded-full bg-white" + className="h-4 w-4 rounded-full"
39-49: Accessibility: use switch role and state.- <TouchableOpacity onPress={handlePress} activeOpacity={0.8}> + <TouchableOpacity + onPress={handlePress} + activeOpacity={0.8} + accessibilityRole="switch" + accessibilityState={{ checked: value }} + accessibilityLabel="Toggle setting" + >src/components/profile/ProfileScreen.tsx (2)
25-33: Tailwind over inline styles per repo guidelines.Replace theme-driven inline styles with Tailwind/NativeWind tokens (e.g., bg-card, border-border, text-text). Example changes:
- <View - className="w-10 h-10 rounded-full items-center justify-center" - style={{ backgroundColor: colors.border }} - > + <View className="w-10 h-10 rounded-full items-center justify-center bg-border">- <SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}> + <SafeAreaView className="flex-1 bg-background">- <ScrollView - className="flex-1" - contentContainerClassName="px-5 pt-20 pb-36" - > + <ScrollView className="flex-1" contentContainerClassName="px-5 pt-20 pb-36">- <BottomNavigation - activeTab="Settings" - onTabPress={(tab) => console.log(tab)} - /> + <BottomNavigation activeTab="Settings" onTabPress={(tab) => console.log(tab)} />Confirm that bg-background, bg-border, text-text, bg-card are defined in your Tailwind theme. If not, I can draft the tailwind.config mapping to theme tokens.
Also applies to: 38-42, 44-47, 105-108
48-48: Avoid hard-coded UI strings; prep for i18n.Move "Julia's - Profile" to a strings module or i18n resource.
src/components/profile/Income.tsx (4)
26-33: Replace inline styles with Tailwind classes.Follow repo guideline (Tailwind via NativeWind).
- <View - className="w-10 h-10 rounded-full items-center justify-center" - style={{ backgroundColor: colors.border }} - > + <View className="w-10 h-10 rounded-full items-center justify-center bg-border">- <SafeAreaView className="flex-1" style={{ backgroundColor: colors.background }}> + <SafeAreaView className="flex-1 bg-background">- <ScrollView - className="flex-1" - contentContainerClassName="px-4 pt-16 pb-28" - > + <ScrollView className="flex-1" contentContainerClassName="px-4 pt-16 pb-28">Confirm tokens (bg-background, bg-border) exist in Tailwind config.
Also applies to: 38-39, 45-48
106-110: Accessibility: label interactive controls.Provide accessibility labels for FAB and tabs.
-<FloatingActionButton onPress={() => console.log("Add income/expense")} /> +<FloatingActionButton + onPress={() => console.log("Add income/expense")} + accessibilityLabel="Add income or expense" />You can also pass accessible labels into BottomNavigation’s tab items if supported.
11-13: ProponNavigateis unused.Either wire it (e.g., on FAB press) or remove from props to avoid dead API.
- interface IncomeScreenProps { - onNavigate: (screen: string) => void - } + interface IncomeScreenProps { + onNavigate: (screen: string) => void + }Example usage (outside range):
-<FloatingActionButton onPress={() => console.log("Add income/expense")} /> +<FloatingActionButton onPress={() => onNavigate("AddIncome")} />Also applies to: 15-15
100-102: Currency formatting consistency.Prefer a formatter (Intl.NumberFormat) to avoid mixed 1000€ vs 10,99€ styles.
src/components/profile/UserProfile.tsx (4)
51-52: Theme tokens: verifycolors.success/colors.textSecondary.Theme summary mentions
good/errortokens; code usessuccess/textSecondary. Align keys or update ThemeContext.Example change:
- borderColor: !touched ? colors.border : error ? colors.error : colors.success, + borderColor: !touched ? colors.border : error ? colors.error : colors.good,- placeholderTextColor={colors.textSecondary} + placeholderTextColor={colors.mutedText}Update to the actual keys present in ThemeContext.
Also applies to: 72-87, 91-97
42-45: Inline styles → Tailwind where possible.Prefer Tailwind tokens over inline colors/borders.
-<AppText semibold className="text-base mb-2" style={{ color: colors.text }}> +<AppText semibold className="text-base mb-2 text-text">-<View - className="flex-row items-center rounded-xl border px-4 py-3" - style={{ - backgroundColor: "transparent", - borderColor: !touched ? colors.border : error ? colors.error : colors.good, - }} -> +<View + className={` + flex-row items-center rounded-xl border px-4 py-3 bg-transparent + ${!touched ? "border-border" : error ? "border-error" : "border-good"} + `} +>Ensure these Tailwind tokens are configured.
Also applies to: 47-53
168-174: Improve email field UX.Set appropriate keyboard and capitalization.
<TextInput ... - placeholder="Enter your email address" + placeholder="Enter your email address" + keyboardType="email-address" + autoCapitalize="none" + autoCorrect={false} />For name fields, consider
autoCapitalize="words".
196-206: Button accessibility and disabled state.Add
accessibilityStateand avoid purely color-cued state.-<TouchableOpacity - disabled={!allValid} +<TouchableOpacity + disabled={!allValid} + accessibilityRole="button" + accessibilityState={{ disabled: !allValid }} onPress={handleSave} className={`mt-8 rounded-xl px-5 py-4 ${ allValid ? "bg-accent" : "bg-gray-400" }`} >src/components/ProfileMenuItem.tsx (4)
4-4: Use path alias consistently.Import ThemeContext via "~" alias to match the rest of the codebase.
-import { useTheme } from "../contexts/ThemeContext" +import { useTheme } from "~/contexts/ThemeContext"
25-30: Tailwind over inline styles for themed colors.Replace inline background/border with Tailwind tokens.
- <TouchableOpacity - className="flex-row items-center rounded-xl border px-5 py-4" - style={{ - backgroundColor: colors.cardBackground, - borderColor: colors.border, - }} + <TouchableOpacity + className="flex-row items-center rounded-xl border px-5 py-4 bg-card border-border" onPress={onPress} activeOpacity={0.7} >Confirm bg-card and border-border exist in Tailwind config.
45-51: Minor: avoid inline sizing for arrow image.Use Tailwind arbitrary values to drop inline style.
- <View className="w-8 h-8 rounded-full items-center justify-center"> + <View className="w-8 h-8 rounded-full items-center justify-center"> <Image source={require("~/assets/Icons/arrow.png")} - style={{ width: 14, height: 14 }} // 👈 explicit sizing + className="w-[14px] h-[14px]" resizeMode="contain" /> </View>
24-32: Accessibility: label the row.Add accessibility label/role for screen readers.
- <TouchableOpacity + <TouchableOpacity + accessibilityRole="button" + accessibilityLabel={`${title} menu item`} className="flex-row items-center rounded-xl border px-5 py-4 bg-card border-border"src/components/profile/BankAccounts.tsx (2)
25-33: Inline styles → Tailwind tokens.Adopt Tailwind/NativeWind classes for themed colors.
-<View - className="w-10 h-10 rounded-full items-center justify-center" - style={{ backgroundColor: colors.border }} -> +<View className="w-10 h-10 rounded-full items-center justify-center bg-border">-<SafeAreaView className="flex-1" style={{ backgroundColor: colors.background }}> +<SafeAreaView className="flex-1 bg-background">-<ScrollView - className="flex-1" - contentContainerClassName="px-4 pt-28 pb-28" -> +<ScrollView className="flex-1" contentContainerClassName="px-4 pt-28 pb-28">Ensure tokens (bg-background, bg-border) exist.
Also applies to: 38-39, 45-48, 51-84
9-11: ProponNavigatecurrently unused.Either wire it (e.g., on PayPal press) or drop from props.
- onPress={() => console.log("PayPal")} + onPress={() => onNavigate("PayPal")}Also applies to: 13-13
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (17)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlsrc/assets/Icons/Y.pngis excluded by!**/*.pngsrc/assets/Icons/arrow.pngis excluded by!**/*.pngsrc/assets/Icons/bank_account.pngis excluded by!**/*.pngsrc/assets/Icons/banking.pngis excluded by!**/*.pngsrc/assets/Icons/entertainment.pngis excluded by!**/*.pngsrc/assets/Icons/income.pngis excluded by!**/*.pngsrc/assets/Icons/insights.pngis excluded by!**/*.pngsrc/assets/Icons/key-2.pngis excluded by!**/*.pngsrc/assets/Icons/key.pngis excluded by!**/*.pngsrc/assets/Icons/limits.pngis excluded by!**/*.pngsrc/assets/Icons/netflix.pngis excluded by!**/*.pngsrc/assets/Icons/notification.pngis excluded by!**/*.pngsrc/assets/Icons/plus.pngis excluded by!**/*.pngsrc/assets/Icons/profile.pngis excluded by!**/*.pngsrc/assets/Icons/rent.pngis excluded by!**/*.pngsrc/assets/Icons/settings.pngis excluded by!**/*.png
📒 Files selected for processing (21)
.vscode/settings.json(1 hunks)package.json(1 hunks)pnpm-workspace.yaml(1 hunks)src/app/profile/index.tsx(1 hunks)src/components/AccountItem.tsx(2 hunks)src/components/AppText.tsx(2 hunks)src/components/BottomNavigation.tsx(1 hunks)src/components/Button.tsx(1 hunks)src/components/DashboardAccount.tsx(1 hunks)src/components/FloatingActionButton.tsx(1 hunks)src/components/Header.tsx(3 hunks)src/components/ProfileMenuItem.tsx(1 hunks)src/components/Toggle.tsx(1 hunks)src/components/profile/BankAccounts.tsx(1 hunks)src/components/profile/Income.tsx(1 hunks)src/components/profile/Limits.tsx(1 hunks)src/components/profile/Notification.tsx(1 hunks)src/components/profile/ProfileScreen.tsx(1 hunks)src/components/profile/UserProfile.tsx(1 hunks)src/contexts/ThemeContext.tsx(3 hunks)src/types/index.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.tsx
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.tsx: Use instead of from react-native in UI components
All styling should use TailwindCSS classes via NativeWind (avoid inline StyleSheet definitions)
Files:
src/components/Toggle.tsxsrc/components/AccountItem.tsxsrc/components/profile/UserProfile.tsxsrc/components/profile/Notification.tsxsrc/components/FloatingActionButton.tsxsrc/components/profile/Income.tsxsrc/components/profile/Limits.tsxsrc/components/BottomNavigation.tsxsrc/contexts/ThemeContext.tsxsrc/components/profile/BankAccounts.tsxsrc/components/Button.tsxsrc/components/DashboardAccount.tsxsrc/app/profile/index.tsxsrc/components/profile/ProfileScreen.tsxsrc/components/ProfileMenuItem.tsxsrc/components/Header.tsxsrc/components/AppText.tsx
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Follow TypeScript strict mode requirements across the codebase
Files:
src/components/Toggle.tsxsrc/components/AccountItem.tsxsrc/components/profile/UserProfile.tsxsrc/components/profile/Notification.tsxsrc/components/FloatingActionButton.tsxsrc/types/index.tssrc/components/profile/Income.tsxsrc/components/profile/Limits.tsxsrc/components/BottomNavigation.tsxsrc/contexts/ThemeContext.tsxsrc/components/profile/BankAccounts.tsxsrc/components/Button.tsxsrc/components/DashboardAccount.tsxsrc/app/profile/index.tsxsrc/components/profile/ProfileScreen.tsxsrc/components/ProfileMenuItem.tsxsrc/components/Header.tsxsrc/components/AppText.tsx
src/app/**/*.tsx
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Use Expo Router file-based routing; screens and routes live under src/app/
Files:
src/app/profile/index.tsx
🧠 Learnings (4)
📚 Learning: 2025-08-24T14:28:33.803Z
Learnt from: CR
PR: The-Creative-Programming-Group/finance-io#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-24T14:28:33.803Z
Learning: Applies to src/**/*.tsx : Use <AppText> instead of <Text> from react-native in UI components
Applied to files:
src/components/Button.tsxsrc/components/AppText.tsx
📚 Learning: 2025-07-01T08:06:09.826Z
Learnt from: murtazanoori
PR: The-Creative-Programming-Group/finance-io#29
File: src/components/Icons.tsx:58-68
Timestamp: 2025-07-01T08:06:09.826Z
Learning: In React Native projects using custom fonts, replace native Text components with a custom AppText component located in the components folder. AppText provides automatic font handling and consistent theming. Use the `bold`, `semibold`, or `medium` props instead of `fontWeight` in styles. This is enforced by ESLint rules (no-restricted-syntax).
Applied to files:
src/components/Button.tsxsrc/components/AppText.tsx
📚 Learning: 2025-08-24T14:28:33.804Z
Learnt from: CR
PR: The-Creative-Programming-Group/finance-io#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-24T14:28:33.804Z
Learning: Applies to src/app/**/*.tsx : Use Expo Router file-based routing; screens and routes live under src/app/
Applied to files:
src/app/profile/index.tsx
📚 Learning: 2025-08-24T14:28:33.803Z
Learnt from: CR
PR: The-Creative-Programming-Group/finance-io#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-24T14:28:33.803Z
Learning: Applies to src/**/*.tsx : All styling should use TailwindCSS classes via NativeWind (avoid inline StyleSheet definitions)
Applied to files:
src/components/AppText.tsx
🧬 Code graph analysis (16)
src/components/Toggle.tsx (1)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)
src/components/AccountItem.tsx (3)
src/components/AppText.tsx (1)
AppText(14-55)src/app/dashboard/banking/index.tsx (3)
account(59-68)account(71-80)account(84-93)src/components/Icons.tsx (3)
View(72-83)View(50-70)AppImage(96-102)
src/components/profile/UserProfile.tsx (4)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/AppText.tsx (1)
AppText(14-55)src/components/Header.tsx (1)
Header(17-50)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/profile/Notification.tsx (5)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/Header.tsx (1)
Header(17-50)src/components/AppText.tsx (1)
AppText(14-55)src/components/Toggle.tsx (1)
Toggle(15-51)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/FloatingActionButton.tsx (2)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/CardComponent.tsx (1)
useTheme(16-67)
src/components/profile/Income.tsx (7)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/Header.tsx (1)
Header(17-50)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/AppText.tsx (1)
AppText(14-55)src/components/AccountItem.tsx (1)
AccountItem(15-77)src/components/FloatingActionButton.tsx (1)
FloatingActionButton(15-51)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/profile/Limits.tsx (6)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/Header.tsx (1)
Header(17-50)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/AccountItem.tsx (1)
AccountItem(15-77)src/components/FloatingActionButton.tsx (1)
FloatingActionButton(15-51)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/BottomNavigation.tsx (3)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/AppText.tsx (1)
AppText(14-55)src/app/_layout.tsx (1)
RootLayoutNav(43-70)
src/contexts/ThemeContext.tsx (1)
src/app/dashboard/banking/index.tsx (1)
useTheme(9-115)
src/components/profile/BankAccounts.tsx (4)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/Header.tsx (1)
Header(17-50)src/components/ProfileMenuItem.tsx (1)
ProfileMenuItem(14-55)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/Button.tsx (2)
src/components/AppText.tsx (1)
AppText(14-55)src/components/ui/button.tsx (2)
props(31-83)event(40-66)
src/components/DashboardAccount.tsx (1)
src/components/Header.tsx (1)
Header(17-50)
src/app/profile/index.tsx (7)
src/components/profile/ProfileScreen.tsx (1)
ProfileScreen(13-111)src/components/profile/Limits.tsx (1)
LimitsScreen(14-77)src/components/profile/Income.tsx (1)
IncomeScreen(15-113)src/components/profile/Notification.tsx (1)
NotificationScreen(13-80)src/components/profile/UserProfile.tsx (1)
UserProfileScreen(101-212)src/components/profile/BankAccounts.tsx (1)
BankAccountsScreen(13-93)src/contexts/ThemeContext.tsx (1)
ThemeProvider(54-60)
src/components/profile/ProfileScreen.tsx (5)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/Header.tsx (1)
Header(17-50)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/ProfileMenuItem.tsx (1)
ProfileMenuItem(14-55)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/ProfileMenuItem.tsx (2)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/AppText.tsx (1)
AppText(14-55)
src/components/Header.tsx (2)
src/components/SectionHeader.tsx (2)
SectionHeaderProps(6-10)useTheme(12-35)src/components/CardComponent.tsx (2)
CardComponentProps(9-14)useTheme(16-67)
🔇 Additional comments (8)
src/types/index.ts (1)
31-35: ProfileData type looks fine.No issues with the new interface.
pnpm-workspace.yaml (1)
3-8: Confirm onlyBuiltDependencies are necessaryRepository search shows these names only in pnpm-workspace.yaml and pnpm-lock.yaml (no matches in package.json or workspace packages). Confirm why each entry was added — if not required for postinstall/builds, remove to reduce CI time.
Location: pnpm-workspace.yaml (repo root), lines 3–8.
src/components/Button.tsx (1)
1-39: Incorrect — no router-aware Button at src/components/ui/button.tsxSearch shows only src/components/Button.tsx and src/components/FloatingActionButton.tsx; no other Button component or any usages under src. FloatingActionButton is imported in src/components/profile/Limits.tsx and src/components/profile/Income.tsx. If a router-aware Button exists in a different path or external package, provide its location.
Likely an incorrect or invalid review comment.
src/components/profile/Limits.tsx (1)
73-75: Consider wiring BottomNavigation to navigation.Right now it only logs; if this screen participates in a router, call onNavigate accordingly.
src/components/DashboardAccount.tsx (1)
32-33: Header prop usage updated — good.Matches new API.
src/components/profile/Notification.tsx (1)
77-78: Consider wiring BottomNavigation to navigation.src/components/Header.tsx (1)
usages remain in src/; all Header components use
13-18: Prop rename verified: Headername→titlemigration complete.
Notitle.src/contexts/ThemeContext.tsx (1)
24-50: No missing theme tokens — all used tokens are defined.
All tokens referenced (background, border, cardBackground, text, textSecondary, primary, success, good, error) are present in ThemeColors and implemented in both lightColors and darkColors; accent and stroke are defined but currently unused.
pnpm-workspace.yaml
Outdated
| packages: | ||
| - 'src/*' |
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.
Treating every folder under src/ as a workspace package is risky for Expo/Metro.*
Metro + pnpm symlinks can misresolve modules unless you add custom metro.config and monorepo setup. Unless you truly have package boundaries in src/*, avoid making them workspace packages.
Recommended:
-packages:
- - 'src/*'
+packages:
+ - 'apps/*'
+ - 'packages/*'
+# Keep app source under src/ inside the app package instead of top-level workspace packages.If you must keep monorepo in src/*, ensure Metro is configured (watchFolders, resolver.disableHierarchicalLookup=false or equivalent) and NativeWind/babel paths handle symlinks.
📝 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.
| packages: | |
| - 'src/*' | |
| packages: | |
| - 'apps/*' | |
| - 'packages/*' | |
| # Keep app source under src/ inside the app package instead of top-level workspace packages. |
🤖 Prompt for AI Agents
In pnpm-workspace.yaml around lines 1-2, listing packages: - 'src/*' treats
every folder under src as a workspace package which breaks Expo/Metro; either
restrict the workspace globs to explicit package folders (e.g. move true
packages into a dedicated packages/ dir or list only the actual package paths
under src) or keep src/* but add the required Metro/React Native monorepo
config: add watchFolders pointing to workspace roots, set
resolver.disableHierarchicalLookup=false (or equivalent) and ensure
NativeWind/babel config handles symlinks; update pnpm-workspace.yaml to a narrow
set of package globs or move package folders and document the Metro config
changes.
src/app/profile/index.tsx
Outdated
| const ProfileAppContent: React.FC = () => { | ||
| const [currentScreen, setCurrentScreen] = React.useState("Profile") | ||
|
|
||
| const handleNavigate = (screen: string) => { | ||
| setCurrentScreen(screen) | ||
| } | ||
|
|
||
| const renderScreen = () => { | ||
| switch (currentScreen) { | ||
| case "Profile": | ||
| return <ProfileScreen onNavigate={handleNavigate} /> | ||
| case "Limits": | ||
| return <LimitsScreen onNavigate={handleNavigate} /> | ||
| case "Income": | ||
| return <IncomeScreen onNavigate={handleNavigate} /> | ||
| case "Notification": | ||
| return <NotificationScreen onNavigate={handleNavigate} /> | ||
| case "UserProfile": | ||
| return <UserProfileScreen onNavigate={handleNavigate} /> | ||
| case "BankAccounts": | ||
| return <BankAccountsScreen onNavigate={handleNavigate} /> | ||
| default: | ||
| return <ProfileScreen onNavigate={handleNavigate} /> | ||
| } | ||
| } | ||
|
|
||
| return renderScreen() | ||
| } |
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.
Do not implement a manual “router”; use Expo Router file-based routes.
Guideline: screens and routes live under src/app/. Replace local state switching with Expo Router (Stack/Tabs) and split each screen into its own route file: e.g., src/app/profile/index.tsx (menu), src/app/profile/limits.tsx, income.tsx, notification.tsx, user.tsx, bank-accounts.tsx. Pass data via params instead of custom onNavigate.
Minimal interim typing improvement if you keep this temporarily:
- const [currentScreen, setCurrentScreen] = React.useState("Profile")
+ type Screen = "Profile" | "Limits" | "Income" | "Notification" | "UserProfile" | "BankAccounts"
+ const [currentScreen, setCurrentScreen] = React.useState<Screen>("Profile")
- const handleNavigate = (screen: string) => {
+ const handleNavigate = (screen: Screen) => {
setCurrentScreen(screen)
}Also consider removing @react-navigation/native if you won’t use it directly.
📝 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 ProfileAppContent: React.FC = () => { | |
| const [currentScreen, setCurrentScreen] = React.useState("Profile") | |
| const handleNavigate = (screen: string) => { | |
| setCurrentScreen(screen) | |
| } | |
| const renderScreen = () => { | |
| switch (currentScreen) { | |
| case "Profile": | |
| return <ProfileScreen onNavigate={handleNavigate} /> | |
| case "Limits": | |
| return <LimitsScreen onNavigate={handleNavigate} /> | |
| case "Income": | |
| return <IncomeScreen onNavigate={handleNavigate} /> | |
| case "Notification": | |
| return <NotificationScreen onNavigate={handleNavigate} /> | |
| case "UserProfile": | |
| return <UserProfileScreen onNavigate={handleNavigate} /> | |
| case "BankAccounts": | |
| return <BankAccountsScreen onNavigate={handleNavigate} /> | |
| default: | |
| return <ProfileScreen onNavigate={handleNavigate} /> | |
| } | |
| } | |
| return renderScreen() | |
| } | |
| const ProfileAppContent: React.FC = () => { | |
| type Screen = "Profile" | "Limits" | "Income" | "Notification" | "UserProfile" | "BankAccounts" | |
| const [currentScreen, setCurrentScreen] = React.useState<Screen>("Profile") | |
| const handleNavigate = (screen: Screen) => { | |
| setCurrentScreen(screen) | |
| } | |
| const renderScreen = () => { | |
| switch (currentScreen) { | |
| case "Profile": | |
| return <ProfileScreen onNavigate={handleNavigate} /> | |
| case "Limits": | |
| return <LimitsScreen onNavigate={handleNavigate} /> | |
| case "Income": | |
| return <IncomeScreen onNavigate={handleNavigate} /> | |
| case "Notification": | |
| return <NotificationScreen onNavigate={handleNavigate} /> | |
| case "UserProfile": | |
| return <UserProfileScreen onNavigate={handleNavigate} /> | |
| case "BankAccounts": | |
| return <BankAccountsScreen onNavigate={handleNavigate} /> | |
| default: | |
| return <ProfileScreen onNavigate={handleNavigate} /> | |
| } | |
| } | |
| return renderScreen() | |
| } |
🤖 Prompt for AI Agents
In src/app/profile/index.tsx around lines 10 to 37, the component implements a
manual router via local state and onNavigate props; replace this with Expo
Router file-based routes: create separate route files (src/app/profile/index.tsx
as the menu and src/app/profile/limits.tsx, income.tsx, notification.tsx,
user.tsx, bank-accounts.tsx) and navigate between them using Expo Router
navigation/Link or Stack/Tabs, passing any required data via route params
instead of onNavigate callbacks; remove the local currentScreen state and
onNavigate props from the child screens (or convert them to accept params), and
if you stop using react-navigation directly, remove @react-navigation/native
from dependencies; if you temporarily keep the manual switch for an interim
change, at minimum tighten typing by creating a ScreenName union type and typing
handleNavigate and currentScreen accordingly.
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.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
src/components/AccountItem.tsx
Outdated
| const Component = onPress ? TouchableOpacity : View | ||
|
|
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.
Union element misuse: passing activeOpacity to View triggers type/runtime issues.
const Component = onPress ? TouchableOpacity : View and always passing activeOpacity causes TS prop mismatch and RN warnings. Render conditionally or switch to Pressable.
Apply:
- const Component = onPress ? TouchableOpacity : View
+ // Use explicit branches to avoid invalid props on ViewAnd in render:
- <Component
- onPress={onPress}
- activeOpacity={onPress ? 0.7 : 1}
- className="flex-row items-center py-4 px-5 rounded-xl border"
- style={{
- backgroundColor: colors.cardBackground,
- borderColor: colors.border,
- }}
- >
+ {onPress ? (
+ <TouchableOpacity
+ onPress={onPress}
+ activeOpacity={0.7}
+ className="flex-row items-center rounded-xl border px-5 py-4"
+ style={{ backgroundColor: colors.cardBackground, borderColor: colors.border }}
+ >
+ <View className="mr-4 h-10 w-10">{icon}</View>
+ <AppText medium className="flex-1 text-base" style={{ color: colors.text }}>
+ {name}
+ </AppText>
+ <IconWrapper height={40} width={60}>
+ <AppText semibold className="text-base" style={{ color: colors.text }}>
+ {amount}
+ </AppText>
+ </IconWrapper>
+ </TouchableOpacity>
+ ) : (
+ <View
+ className="flex-row items-center rounded-xl border px-5 py-4"
+ style={{ backgroundColor: colors.cardBackground, borderColor: colors.border }}
+ >
+ <View className="mr-4 h-10 w-10">{icon}</View>
+ <AppText medium className="flex-1 text-base" style={{ color: colors.text }}>
+ {name}
+ </AppText>
+ <IconWrapper height={40} width={60}>
+ <AppText semibold className="text-base" style={{ color: colors.text }}>
+ {amount}
+ </AppText>
+ </IconWrapper>
+ </View>
+ )}📝 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 Component = onPress ? TouchableOpacity : View | |
| // Use explicit branches to avoid invalid props on View | |
| {onPress ? ( | |
| <TouchableOpacity | |
| onPress={onPress} | |
| activeOpacity={0.7} | |
| className="flex-row items-center rounded-xl border px-5 py-4" | |
| style={{ backgroundColor: colors.cardBackground, borderColor: colors.border }} | |
| > | |
| <View className="mr-4 h-10 w-10">{icon}</View> | |
| <AppText medium className="flex-1 text-base" style={{ color: colors.text }}> | |
| {name} | |
| </AppText> | |
| <IconWrapper height={40} width={60}> | |
| <AppText semibold className="text-base" style={{ color: colors.text }}> | |
| {amount} | |
| </AppText> | |
| </IconWrapper> | |
| </TouchableOpacity> | |
| ) : ( | |
| <View | |
| className="flex-row items-center rounded-xl border px-5 py-4" | |
| style={{ backgroundColor: colors.cardBackground, borderColor: colors.border }} | |
| > | |
| <View className="mr-4 h-10 w-10">{icon}</View> | |
| <AppText medium className="flex-1 text-base" style={{ color: colors.text }}> | |
| {name} | |
| </AppText> | |
| <IconWrapper height={40} width={60}> | |
| <AppText semibold className="text-base" style={{ color: colors.text }}> | |
| {amount} | |
| </AppText> | |
| </IconWrapper> | |
| </View> | |
| )} |
🤖 Prompt for AI Agents
In src/components/AccountItem.tsx around lines 24-25, you currently assign
Component = onPress ? TouchableOpacity : View and then always pass activeOpacity
which causes a prop/type mismatch; fix by either (A) rendering TouchableOpacity
conditionally only when onPress is present (i.e. return <TouchableOpacity ...>
when onPress else <View ...>), ensuring activeOpacity is only passed to
TouchableOpacity, or (B) switch to React Native Pressable for both cases and use
its supported props (remove activeOpacity and use press retention/opacity
styles), and update imports/types accordingly so TypeScript no longer complains.
| export const NotificationScreen: React.FC<NotificationScreenProps> = ({ onNavigate }) => { | ||
| const { colors, isDark } = useTheme() | ||
| const [notificationEnabled, setNotificationEnabled] = React.useState(true) | ||
|
|
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.
Unused onNavigate prop (likely TS strict error).
export const NotificationScreen: React.FC<NotificationScreenProps> = ({ onNavigate }) => {
const { colors, isDark } = useTheme()
const [notificationEnabled, setNotificationEnabled] = React.useState(true)
+ void onNavigate📝 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.
| export const NotificationScreen: React.FC<NotificationScreenProps> = ({ onNavigate }) => { | |
| const { colors, isDark } = useTheme() | |
| const [notificationEnabled, setNotificationEnabled] = React.useState(true) | |
| export const NotificationScreen: React.FC<NotificationScreenProps> = ({ onNavigate }) => { | |
| const { colors, isDark } = useTheme() | |
| const [notificationEnabled, setNotificationEnabled] = React.useState(true) | |
| void onNavigate |
🤖 Prompt for AI Agents
In src/components/profile/Notification.tsx around lines 13 to 16, the component
destructures an onNavigate prop but never uses it causing a TS/strict unused
prop error; either remove onNavigate from the component signature and from
NotificationScreenProps (or make it optional in the type) if it’s not needed, or
deliberately mark it as unused by renaming to _onNavigate (or otherwise
reference it with a noop like void _onNavigate) so TypeScript/linters stop
complaining—apply the chosen change consistently to the prop type and all call
sites.
| color: "white", // make text white | ||
| backgroundColor: "transparent", // remove input fill | ||
| outlineStyle: "none" as any, // remove browser yellow outline | ||
| }} |
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.
Web-only style leaks and any cast in TextInput styles.
outlineStyle is RN-web specific; casting to any breaks TS strict guarantees.
- style={{
- color: "white", // make text white
- backgroundColor: "transparent", // remove input fill
- outlineStyle: "none" as any, // remove browser yellow outline
- }}
+ style={{
+ backgroundColor: "transparent",
+ // Use theme color; avoid hard-coded white
+ color: colors.text,
+ ...(Platform.OS === "web" ? ({ outlineStyle: "none" } as any) : {}),
+ }}Add missing import (outside range):
-import {
+import {
ScrollView,
StatusBar,
SafeAreaView,
View,
Image,
TouchableOpacity,
TextInput,
+ Platform,
} from "react-native"Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In src/components/profile/UserProfile.tsx around lines 66 to 69, the TextInput
styles include a web-only property outlineStyle with an `as any` cast; remove
the unsafe cast and avoid leaking web-specific styles by conditionally adding
outlineStyle only on web. Import Platform from 'react-native' at the top of the
file (outside the shown range), then change the style object to merge a
Platform.OS === 'web' ? { outlineStyle: 'none' } : {} into the styles (no
casting) so non-web platforms do not receive the property.
src/components/Toggle.tsx
Outdated
| const translateX = useSharedValue(value ? 16 : 0) | ||
|
|
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.
Controlled component sync: update thumb when value prop changes.
Without syncing, external value changes won't move the thumb.
const translateX = useSharedValue(value ? 16 : 0)
+ useEffect(() => {
+ translateX.value = withSpring(value ? 16 : 0, {
+ damping: 15,
+ stiffness: 150,
+ })
+ }, [value])Also applies to: 29-36
🤖 Prompt for AI Agents
In src/components/Toggle.tsx around lines 18-19 (and similarly 29-36), the
thumb's shared value is initialized from the value prop but not updated when
value changes, so external prop updates won't move the thumb; add an effect that
watches the value prop and updates translateX (using reanimated's withTiming or
set) to the target (16 or 0) so the thumb animates to the correct position when
value changes, and ensure any related animated style/gesture handlers read the
updated shared value.
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: 2
🧹 Nitpick comments (8)
src/components/profile/UserProfile.tsx (8)
184-189: Replace inline icon sizing with Tailwind classes.Adhere to “no inline StyleSheet” guideline for static dimensions.
- <Image - source={require("~/assets/Icons/key-2.png")} - style={{ width: 18, height: 18 }} - resizeMode="contain" - className="mr-2" - /> + <Image + source={require("~/assets/Icons/key-2.png")} + className="w-[18px] h-[18px] mr-2" + resizeMode="contain" + />
20-32: Pass TextInput props through InputField; fix capitalization/autofill for better UX.
- Names shouldn’t use autoCapitalize="none".
- Email should set proper keyboard/autofill props.
- Add a pass‑through prop and remove the hard‑coded autoCapitalize.
Edits:
-const InputField = ({ +const InputField = ({ label, value, onChangeText, placeholder, validate, + inputProps, }: { label: string value: string onChangeText: (text: string) => void placeholder?: string validate?: (text: string) => string | null + inputProps?: TextInputProps }) => {- <TextInput + <TextInput className="flex-1 text-base " - autoCapitalize="none" onChangeText={(text) => { if (!touched) setTouched(true) onChangeText(text) }} placeholder={placeholder} placeholderTextColor={colors.textSecondary} selectionColor={colors.primary} value={value} + {...inputProps} style={{Use it at call sites:
<InputField label="First Name" value={firstName} onChangeText={setFirstName} validate={validateRequired} placeholder="Enter your first name" + inputProps={{ autoCapitalize: "words", autoComplete: "name", textContentType: "givenName" }} /><InputField label="Last Name" value={lastName} onChangeText={setLastName} validate={validateRequired} placeholder="Enter your last name" + inputProps={{ autoCapitalize: "words", autoComplete: "name", textContentType: "familyName" }} /><InputField label="Email" value={email} onChangeText={setEmail} validate={validateEmail} placeholder="Enter your email address" + inputProps={{ + keyboardType: "email-address", + autoComplete: "email", + textContentType: "emailAddress", + autoCapitalize: "none", + autoCorrect: false, + }} />Add missing type import (outside range):
+import type { TextInputProps } from "react-native"Also applies to: 54-61, 153-160, 162-167, 169-174
119-123: Make validity check explicit for readability.Truthiness on strings works but is brittle; compare to null.
- const allValid = - !validateRequired(firstName) && - !validateRequired(lastName) && - !validateEmail(email) + const allValid = + validateRequired(firstName) === null && + validateRequired(lastName) === null && + validateEmail(email) === null
124-127: Avoid logging PII (names, email) in production.Gate dev logging and keep production clean.
- const handleSave = () => { - console.log("Saving profile:", { firstName, lastName, email }) - // Replace with API call - } + const handleSave = () => { + // Replace with API call + if (__DEV__) { + console.log("Saving profile (dev):", { firstName, lastName, email }) + } + }
196-206: Improve accessibility of the Save button.Expose role/state and give a clear disabled affordance.
- <TouchableOpacity - disabled={!allValid} - onPress={handleSave} - className={`mt-8 rounded-xl px-5 py-4 ${ - allValid ? "bg-accent" : "bg-gray-400" - }`} - > + <TouchableOpacity + accessibilityRole="button" + accessibilityState={{ disabled: !allValid }} + disabled={!allValid} + onPress={handleSave} + className={`mt-8 rounded-xl px-5 py-4 ${ + allValid ? "bg-accent" : "bg-gray-400 opacity-60" + }`} + >
140-140: Avoid hard‑coded header title.Prefer deriving from profile state (e.g.,
${firstName || "User"} ${lastName}) or route params.
42-45: Prepare for i18n.User‑facing strings (“First Name”, “This field is required”, etc.) should be sourced from your i18n layer.
Also applies to: 91-97
48-52: Minimize inline styles per repo guideline.Keep dynamic theme colors in style if needed, but move static layout values (spacing, radius) to Tailwind classes. Current blocks mix both.
If NativeWind lacks tokens for your theme colors, we can add CSS variables or class utilities to reduce style usage. Want a quick PR to set that up?
Also applies to: 130-134, 176-183
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/components/profile/UserProfile.tsx(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.tsx
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.tsx: Use instead of from react-native in UI components
All styling should use TailwindCSS classes via NativeWind (avoid inline StyleSheet definitions)
Files:
src/components/profile/UserProfile.tsx
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Follow TypeScript strict mode requirements across the codebase
Files:
src/components/profile/UserProfile.tsx
🧬 Code graph analysis (1)
src/components/profile/UserProfile.tsx (4)
src/contexts/ThemeContext.tsx (1)
useTheme(62-68)src/components/AppText.tsx (1)
AppText(14-55)src/components/Header.tsx (1)
Header(17-50)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
🔇 Additional comments (2)
src/components/profile/UserProfile.tsx (2)
65-69: Fix a11y + theme/strict issues in TextInput style.
- Don’t hard‑code "white"; use theme color.
- Avoid removing the browser focus outline; it harms keyboard a11y. If you must, gate it on web only (not globally) and avoid leaking the prop to native.
Apply this diff:
- style={{ - color: "white", - backgroundColor: colors.cardBackground, // add background color - outlineStyle: "none" as any, // remove browser yellow outline - }} + style={{ + color: colors.text, + backgroundColor: colors.cardBackground, + }}Optional (web‑only gating, if product insists on hiding outline):
+// at top-level imports +import { Platform, type TextInputProps } from "react-native"- style={{ - color: colors.text, - backgroundColor: colors.cardBackground, - }} + style={[ + { color: colors.text, backgroundColor: colors.cardBackground }, + Platform.OS === "web" ? ({ outlineStyle: "none" } as any) : null, + ]}
77-81: Verified — Theme tokens and Tailwind "accent" are present.
ThemeContext defines success, error and textSecondary; tailwind.config.js includes an accent color.
| export const UserProfileScreen: React.FC<UserProfileScreenProps> = ({ onNavigate }) => { | ||
| const { colors, isDark } = useTheme() | ||
|
|
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.
Wire up navigation; current UI is non‑functional.
- onNavigate prop is unused.
- “Change Password” button has no onPress.
- Bottom nav logs instead of navigating.
- <TouchableOpacity
+ <TouchableOpacity
+ onPress={() => onNavigate("ChangePassword")}
className="mt-6 flex-row items-center self-center rounded-xl border px-3 py-2"- <BottomNavigation activeTab="Settings" onTabPress={(tab) => console.log(tab)} />
+ <BottomNavigation activeTab="Settings" onTabPress={(tab) => onNavigate(tab)} />Also applies to: 176-193, 209-209
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.
Please split this PR its to big to review here :D
Noted |
|
No dependency changes detected. Learn more about Socket for GitHub. 👍 No dependency changes detected in pull request |
|
@Psamcyite You need to fix the GitHub checks |
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: 1
🧹 Nitpick comments (1)
src/components/profile/Notification.tsx (1)
19-37: Type-safe IconWrapper sourceLet’s keep strict typing here too—typing
sourceasImageSourcePropTypepreserves safety for asset usage.-import { ScrollView, StatusBar, SafeAreaView, View, Image } from "react-native"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + Image, + ImageSourcePropType, +} from "react-native"; @@ - }: { - source: any; + }: { + source: ImageSourcePropType;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
.vscode/settings.json(1 hunks)pnpm-workspace.yaml(1 hunks)src/app/dashboard/banking/index.tsx(3 hunks)src/app/profile/index.tsx(1 hunks)src/components/AccountItem.tsx(2 hunks)src/components/BottomNavigation.tsx(1 hunks)src/components/Button.tsx(1 hunks)src/components/FloatingActionButton.tsx(1 hunks)src/components/Header.tsx(3 hunks)src/components/ProfileMenuItem.tsx(1 hunks)src/components/Toggle.tsx(1 hunks)src/components/profile/BankAccounts.tsx(1 hunks)src/components/profile/Income.tsx(1 hunks)src/components/profile/Limits.tsx(1 hunks)src/components/profile/Notification.tsx(1 hunks)src/components/profile/ProfileScreen.tsx(1 hunks)src/components/profile/UserProfile.tsx(1 hunks)src/components/ui/AppText.tsx(0 hunks)src/contexts/ThemeContext.tsx(1 hunks)
💤 Files with no reviewable changes (1)
- src/components/ui/AppText.tsx
🚧 Files skipped from review as they are similar to previous changes (9)
- src/components/AccountItem.tsx
- src/components/profile/ProfileScreen.tsx
- .vscode/settings.json
- src/components/profile/BankAccounts.tsx
- src/app/profile/index.tsx
- src/components/profile/UserProfile.tsx
- src/components/BottomNavigation.tsx
- src/components/Button.tsx
- src/app/dashboard/banking/index.tsx
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.tsx
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.tsx: Use instead of from react-native in UI components
All styling should use TailwindCSS classes via NativeWind (avoid inline StyleSheet definitions)
Files:
src/components/Header.tsxsrc/contexts/ThemeContext.tsxsrc/components/profile/Notification.tsxsrc/components/profile/Limits.tsxsrc/components/profile/Income.tsxsrc/components/FloatingActionButton.tsxsrc/components/Toggle.tsxsrc/components/ProfileMenuItem.tsx
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Follow TypeScript strict mode requirements across the codebase
Files:
src/components/Header.tsxsrc/contexts/ThemeContext.tsxsrc/components/profile/Notification.tsxsrc/components/profile/Limits.tsxsrc/components/profile/Income.tsxsrc/components/FloatingActionButton.tsxsrc/components/Toggle.tsxsrc/components/ProfileMenuItem.tsx
🧠 Learnings (1)
📚 Learning: 2025-08-24T14:28:33.803Z
Learnt from: CR
PR: The-Creative-Programming-Group/finance-io#0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-08-24T14:28:33.803Z
Learning: Applies to src/**/*.tsx : Use <AppText> instead of <Text> from react-native in UI components
Applied to files:
src/components/Header.tsx
🧬 Code graph analysis (6)
src/components/profile/Notification.tsx (5)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/ui/AppText.tsx (1)
AppText(14-47)src/components/Toggle.tsx (1)
Toggle(15-51)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/profile/Limits.tsx (6)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/AccountItem.tsx (1)
AccountItem(17-103)src/components/FloatingActionButton.tsx (1)
FloatingActionButton(14-52)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/profile/Income.tsx (7)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/ui/AppText.tsx (1)
AppText(14-47)src/components/AccountItem.tsx (1)
AccountItem(17-103)src/components/FloatingActionButton.tsx (1)
FloatingActionButton(14-52)src/components/BottomNavigation.tsx (1)
BottomNavigation(11-75)
src/components/FloatingActionButton.tsx (1)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)
src/components/Toggle.tsx (1)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)
src/components/ProfileMenuItem.tsx (2)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/ui/AppText.tsx (1)
AppText(14-47)
🔇 Additional comments (5)
pnpm-workspace.yaml (1)
2-3: Revert thesrc/*workspace glob unless Metro is reconfiguredAdding
src/*turns every folder undersrcinto its own pnpm package, so Metro/Expo will now see symlinked modules that it cannot resolve without the full monorepo overrides (watchFolders, disableHierarchicalLookup, custom resolver, etc.). Until those Metro changes land, this breaks the bundler. Please drop the glob or replace it with real package directories.packages: - - "src/*" - "."src/components/profile/Limits.tsx (1)
14-76: Wire the BottomNavigation toonNavigate
onNavigateis declared but never used, triggering TS strict (noUnusedParameters) and, more importantly, the bottom nav now ignores navigation requests. Call the prop so taps actually navigate (and the TypeScript error disappears).<BottomNavigation activeTab="Settings" - onTabPress={(tab) => console.log(tab)} + onTabPress={(tab) => onNavigate(tab)} />src/components/Toggle.tsx (1)
1-35: Keep the thumb animation in sync with controlledvaluechanges
translateXis only initialized once, so if the parent flipsvalue(e.g. via props, async data, reset) the track color updates but the thumb stays put. Add an effect that springs the thumb whenevervaluechanges, and importuseEffect.-import type React from "react"; +import type React from "react"; +import { useEffect } from "react"; @@ const translateX = useSharedValue(value ? 16 : 0); + useEffect(() => { + translateX.value = withSpring(value ? 16 : 0, { + damping: 15, + stiffness: 150, + }); + }, [value]); +src/components/profile/Income.tsx (1)
17-35: Replaceanyin IconWrapper propsEchoing the earlier bot note: keeping
sourceasanydrops strict-mode safety. Please type it asImageSourcePropTypeso we retain compile-time validation. As per coding guidelines.-import { ScrollView, StatusBar, SafeAreaView, View, Image } from "react-native"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + Image, + ImageSourcePropType, +} from "react-native"; @@ - }: { - source: any; + }: { + source: ImageSourcePropType;src/components/profile/Notification.tsx (1)
83-86: Replace tab logging with onNavigateThis is still unresolved from coderabbit’s earlier note:
onNavigateis unused, so tab presses only log and we’ll fail unused-parameter checks. Please wire the callback so navigation works.- <BottomNavigation - activeTab="Settings" - onTabPress={(tab) => console.log(tab)} - /> + <BottomNavigation + activeTab="Settings" + onTabPress={(tab) => onNavigate(tab)} + />
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
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/components/BottomNavigation.tsx(1 hunks)src/components/FloatingActionButton.tsx(1 hunks)src/components/ProfileMenuItem.tsx(1 hunks)src/components/profile/BankAccounts.tsx(1 hunks)src/components/profile/Income.tsx(1 hunks)src/components/profile/Limits.tsx(1 hunks)src/components/profile/Notification.tsx(1 hunks)src/components/profile/ProfileScreen.tsx(1 hunks)src/components/profile/UserProfile.tsx(1 hunks)src/i18n.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/ProfileMenuItem.tsx
- src/components/profile/UserProfile.tsx
- src/components/profile/Income.tsx
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Follow TypeScript strict mode requirements across the codebase
Files:
src/i18n.tssrc/components/profile/ProfileScreen.tsxsrc/components/BottomNavigation.tsxsrc/components/profile/Limits.tsxsrc/components/profile/BankAccounts.tsxsrc/components/FloatingActionButton.tsxsrc/components/profile/Notification.tsx
src/**/*.tsx
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
src/**/*.tsx: Use instead of from react-native in UI components
All styling should use TailwindCSS classes via NativeWind (avoid inline StyleSheet definitions)
Files:
src/components/profile/ProfileScreen.tsxsrc/components/BottomNavigation.tsxsrc/components/profile/Limits.tsxsrc/components/profile/BankAccounts.tsxsrc/components/FloatingActionButton.tsxsrc/components/profile/Notification.tsx
🧬 Code graph analysis (6)
src/components/profile/ProfileScreen.tsx (5)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/ProfileMenuItem.tsx (1)
ProfileMenuItem(15-59)src/components/BottomNavigation.tsx (1)
BottomNavigation(12-73)
src/components/BottomNavigation.tsx (2)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/ui/AppText.tsx (1)
AppText(14-47)
src/components/profile/Limits.tsx (6)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/SectionHeader.tsx (1)
SectionHeader(12-35)src/components/AccountItem.tsx (1)
AccountItem(17-103)src/components/FloatingActionButton.tsx (1)
FloatingActionButton(15-53)src/components/BottomNavigation.tsx (1)
BottomNavigation(12-73)
src/components/profile/BankAccounts.tsx (4)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/ProfileMenuItem.tsx (1)
ProfileMenuItem(15-59)src/components/BottomNavigation.tsx (1)
BottomNavigation(12-73)
src/components/FloatingActionButton.tsx (1)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)
src/components/profile/Notification.tsx (5)
src/contexts/ThemeContext.tsx (1)
useTheme(82-88)src/components/Header.tsx (1)
Header(21-52)src/components/ui/AppText.tsx (1)
AppText(14-47)src/components/Toggle.tsx (1)
Toggle(15-51)src/components/BottomNavigation.tsx (1)
BottomNavigation(12-73)
🔇 Additional comments (4)
src/components/profile/Limits.tsx (1)
15-17: Consume the onNavigate prop to avoid strict build failure.
onNavigateis destructured but never referenced, which violates our strictnoUnusedParameterssetting and will block the build. Touch it explicitly or wire it into one of the handlers. One lightweight fix is to mark it as intentionally used. As per coding guidelines.export const LimitsScreen: React.FC<LimitsScreenProps> = ({ onNavigate }) => { const { colors, isDark } = useTheme(); + void onNavigate;src/components/profile/ProfileScreen.tsx (1)
17-25: Tighten the icon source type to ImageSourcePropType.The local
IconWrapperstill usesanyforsource, violating our strict TS rules. ImportImageSourcePropTypeand use it for the prop instead. As per coding guidelines.-import { ScrollView, StatusBar, SafeAreaView, View } from "react-native"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + ImageSourcePropType, +} from "react-native"; ... - }: { - source: any; + }: { + source: ImageSourcePropType;src/components/profile/BankAccounts.tsx (1)
18-25: Type icon sources with ImageSourcePropType.The local
IconWrapperstill relies onany, which violates our strict TS requirements. ImportImageSourcePropTypeand apply it to the prop. As per coding guidelines.-import { ScrollView, StatusBar, SafeAreaView, View } from "react-native"; +import { + ScrollView, + StatusBar, + SafeAreaView, + View, + ImageSourcePropType, +} from "react-native"; ... - }: { - source: any; + }: { + source: ImageSourcePropType;src/components/profile/Notification.tsx (1)
14-16: Hook bottom navigation intoonNavigate.
onNavigateis destructured but never used, which will fail TS strict checks and leaves the bottom nav emitting only a console log—no screen transition happens when users tap a tab. Wire the callback through so navigation actually occurs (and drop the noop log).<BottomNavigation activeTab="Settings" - onTabPress={(tab) => console.log(tab)} + onTabPress={(tab) => { + onNavigate(tab); + }} />Also applies to: 84-87
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
|
@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: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
package.json(1 hunks)src/components/BottomNavigation.tsx(1 hunks)src/components/profile/BankAccounts.tsx(1 hunks)src/components/profile/Income.tsx(1 hunks)src/components/profile/Limits.tsx(1 hunks)src/components/profile/ProfileScreen.tsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/profile/ProfileScreen.tsx
- src/components/BottomNavigation.tsx
- src/components/profile/Income.tsx
🔇 Additional comments (1)
package.json (1)
97-97: pnpm bump looks good.Confirmed pnpm 10.17.1 shipped on September 22, 2025, so the updated
packageManagerpin aligns with the latest supported release. 👍
| <ProfileMenuItem | ||
| icon={ | ||
| <IconWrapper | ||
| iconH={35} | ||
| iconW={35} | ||
| source={require("~/assets/images/paypal-logo.png")} | ||
| /> | ||
| } | ||
| title="PayPal" | ||
| onPress={() => console.log("PayPal")} | ||
| delay={100} | ||
| /> | ||
|
|
||
| <ProfileMenuItem | ||
| icon={<IconWrapper source={require("~/assets/Icons/banking.png")} />} | ||
| title="DebitCard" | ||
| onPress={() => console.log("DebitCard")} | ||
| delay={200} | ||
| /> | ||
|
|
||
| <ProfileMenuItem | ||
| icon={ | ||
| <IconWrapper source={require("~/assets/Icons/bank_account.png")} /> | ||
| } | ||
| title="Safe Account" | ||
| onPress={() => console.log("Safe Account")} | ||
| delay={300} | ||
| /> |
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.
Hook menu items into real navigation
All three ProfileMenuItem handlers just console.log, so tapping them is a no-op for the user. That’s a regression for a production screen that should either navigate or trigger a meaningful action. Please swap the placeholders for real onNavigate(...) calls (or whatever route/action the profile router expects) so the menu items actually work.
🤖 Prompt for AI Agents
In src/components/profile/BankAccounts.tsx around lines 61 to 88, the three
ProfileMenuItem onPress handlers currently only call console.log which makes the
items no-ops; replace those placeholders with real navigation calls (for example
call the screen router: onNavigate('PayPal') / onNavigate('DebitCard') /
onNavigate('SafeAccount') or use React Navigation: navigation.navigate('PayPal')
/ navigation.navigate('DebitCard') / navigation.navigate('SafeAccount')), and
ensure the component either receives an onNavigate prop or imports/uses
useNavigation (and add the necessary import and typing) so tapping each menu
item performs the intended navigation.
# Conflicts: # pnpm-lock.yaml
|
Work has moved to #62 |

Summary by CodeRabbit
New Features
Enhancements
Chores