Repository navigation
Feature/favorites - #136
Conversation
…creen closes #7, #8, #9, #40, #103 - Add analytics index screen with streak tracker, best time chart, stats cards and top match interests section - Add premium screen with Free, Essential and Premium plan cards - Implement frosted outline banner on analytics screen linking to premium - Style plan cards with accent colors, filled/ghost buttons and feature lists - Add bar width adjustment for best time to be online chart
closes #135 - Replace all hardcoded colors with theme values via useTheme - Keep #C3C3C3B3 hardcoded (not yet resolved)
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughIntroduces a redesigned Favorites area (date ideas, categories, tip details), a full Stats dashboard, a Personal Details editor with image picker, new Favorites routing/screens, expanded theme color tokens, settings/navigation tweaks, several new UI components, and package dependency additions. Changes
Sequence DiagramsequenceDiagram
actor User
participant UI as PersonalDetails Screen
participant Permissions as Permissions API
participant ImagePicker as Image Picker
participant Avatar as Avatar Display
participant Router as Expo Router
User->>UI: Tap pencil icon to change picture
UI->>Permissions: Request media library permission
Permissions-->>UI: Permission granted/denied
alt Permission Granted
UI->>ImagePicker: Launch image library (square crop)
ImagePicker-->>User: Show media library UI
User->>ImagePicker: Select image
ImagePicker-->>UI: Return selected image URI
UI->>Avatar: Update profile image URI
Avatar-->>UI: Render updated avatar
else Permission Denied
Permissions-->>UI: Denied
UI-->>User: Show error/skip update
end
User->>UI: Tap "Save and Exit"
UI->>Router: router.back()
Router-->>User: Navigate back
Estimated code review effort🎯 4 (Complex) | ⏱️ ~55 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/`(protected)/(tabs)/_layout.tsx:
- Around line 18-19: The Android tab bar paddingBottom (in _layout.tsx) is
larger than the bar height causing content clipping; adjust so paddingBottom
does not exceed height by deriving both from the same source (e.g., use safe
area inset or a single variable) or reduce Android padding to <= height.
Specifically update the Platform.OS conditional for height and paddingBottom so
they are consistent (for example set Android paddingBottom to 0 or increase
height to match the 60 padding) so icons/press targets remain inside the bar.
In `@app/`(protected)/(tabs)/favorites.tsx:
- Around line 145-163: The section header text color in makeStyles (symbol:
sectionTitle) is hardcoded to theme.white and disappears in the light theme;
update sectionTitle to use the semantic foreground token (theme.text) instead of
theme.white so it respects theme.rootBg and works in both light and dark modes
(search for makeStyles and sectionTitle in this file and replace theme.white
with theme.text).
- Around line 16-17: The module-level CARD_WIDTH calculated via
Dimensions.get("window") is stale after rotations/split-screen; move the width
calculation inside the component using useWindowDimensions() (e.g., const {
width } = useWindowDimensions(); const cardWidth = width - 28) and replace all
uses of CARD_WIDTH with cardWidth in the component — specifically update the
carousel snapInterval, the scroll index calculation (where CARD_WIDTH is used to
compute index/offset), and the card <View> style width to use cardWidth so the
carousel snapping and dot indicators stay correct on resize.
In `@app/`(protected)/(tabs)/stats.tsx:
- Around line 216-240: Several analytics card text styles use theme.white or
faint hardcoded grays which vanish in light mode; update the style entries
(e.g., premiumTitle, premiumSub, streakTitle, sectionTitle) to use theme.text
and muted variants (like theme.text and theme.text + "55" or an existing
theme.muted) instead of theme.white or hardcoded hex values so text contrasts
properly with theme.rootBg/theme.cardBg; apply the same change to the other
style blocks referenced (the additional style objects around the same file) so
all card headings/subtext use theme.text-based colors.
In `@app/`(protected)/analytics/premium.tsx:
- Around line 96-104: The styles in this file use hardcoded near-white grays for
foreground text (styles.screenTitle, styles.planTitle, styles.perText,
styles.featureText, styles.footerText) while the card background uses
theme.cardBgDeep, which breaks in light mode; replace those fixed color values
with semantic theme tokens (e.g., theme.text, theme.mutedText, theme.primary, or
other appropriate tokens from lib/theme/theme.ts) and ensure styles.card
continues to use theme.cardBgDeep for background and plan.accent for shadowColor
so text color is chosen from the theme tokens rather than hardcoded light-mode
colors; update all occurrences across the component (lines ~250-385 and the
shown card mapping) to use the theme tokens.
- Around line 227-229: The Text element in app/(protected)/analytics/premium.tsx
currently calls Linking.openURL("DEINE_PRIVACY_URL")—replace that placeholder
with the real privacy policy URL by referencing a constant (e.g.,
PRIVACY_POLICY_URL) imported from your config/env or constants module and use
Linking.openURL(PRIVACY_POLICY_URL) (ensure the value starts with https://).
Update the Text with style={styles.linkPink} and onPress to use that constant
and optionally handle the promise/errors from Linking.openURL to avoid silent
failures.
- Around line 157-170: The primary CTA Pressable currently uses an empty onPress
handler (onPress={() => {}}) which creates a dead button; update the Pressable
in app/(protected)/analytics/premium.tsx (the element using plan.filledButton
and plan.accent) to either disable interaction or wire it to a visible
placeholder: add the disabled prop and adjust styles/ accessibilityState to
appear non-actionable and set an accessible label like "Coming Soon", or replace
the empty handler with a function that opens a "Coming Soon" modal/toast or
navigates to the billing flow (e.g., call showComingSoonModal() or
navigateToBilling()) so clicks have a clear outcome and the UI reflects that
state.
In `@app/`(protected)/settings/personaldetails.tsx:
- Around line 62-69: The current "Save and Exit" flow only calls router.back()
and never persists component state (fullName, setFullName, email, setEmail,
phone, setPhone, country, setCountry, birthday, setBirthday, profileImage), so
edits are lost; modify the save handler (the function that currently invokes
router.back()) to first validate and persist these state values to the profile
store or API (e.g., call updateProfile or profileStore.update with { fullName,
email, phone, country, birthday, profileImage }), await the async response,
handle errors (show user feedback on failure), and only call router.back() after
a successful save (or on user confirmation if using optimistic UI).
In `@components/favorites/CategoryCard.tsx`:
- Around line 27-35: The label style in CategoryCard (the label object in the
styles) uses a hardcoded color "#aaa" which is low-contrast in light theme;
update the label color to use the theme (e.g., theme.text) or an accessible
alpha variant of theme.text so it adapts to light/dark palettes and remains
readable—locate the label style in CategoryCard.tsx and replace the "#aaa"
literal with theme.text or a themed alpha color.
In `@components/favorites/DateIdeaCard.tsx`:
- Around line 5-13: The DateIdeaCard renders an interactive-looking CTA
("Explore Details →") but provides no way to act on it; update the DateIdeaCard
component to accept a callback prop (e.g., onExplore or onOpenDetails) and wire
that prop to the CTA click/press handler (or, if navigation isn’t implemented
yet, change the CTA to non-interactive text styling). Locate the CTA rendering
inside the DateIdeaCard component and add the prop to the Props type, pass it
through to the clickable element, and ensure you handle optionality (no-op or
conditional rendering) so consumers can opt in; alternatively adjust the CTA
styling and remove any role/interactive attributes so it’s clearly
non-interactive until navigation exists.
- Around line 66-125: The card styles use hardcoded light/dark colors that break
in light theme; update makeStyles to replace literal colors (title,
metaValueWhite, metaLabel, locationText, priceText and any other hardcoded
hex/white values) with semantic theme tokens (e.g., theme.textPrimary,
theme.textSecondary, theme.muted, theme.onPrimary) so title and meta remain
readable across themes, and ensure priceText uses theme.onPrimary (or
equivalent) for contrast and metaValue uses theme.textPrimary/secondary instead
of fixed "#555" or "#aaa".
In `@components/favorites/TipRow.tsx`:
- Around line 37-50: The title and subtitle styles in TipRow.tsx use hardcoded
light colors which become unreadable in light mode; update the styles object so
the title uses theme.text instead of theme.white and the subtitle uses the
theme's muted text token (e.g., theme.muted or theme.textMuted) instead of the
hardcoded "#aaa" so the row respects both light and dark themes; modify the
style entries named title and subtitle (and any other hardcoded color in this
styles block such as textCol if present) to reference the theme tokens.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 52ab26da-1653-4e61-8f19-4539070c1e04
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (12)
app/(onboarding)/index.tsxapp/(protected)/(tabs)/_layout.tsxapp/(protected)/(tabs)/favorites.tsxapp/(protected)/(tabs)/settings.tsxapp/(protected)/(tabs)/stats.tsxapp/(protected)/analytics/premium.tsxapp/(protected)/settings/personaldetails.tsxcomponents/favorites/CategoryCard.tsxcomponents/favorites/DateIdeaCard.tsxcomponents/favorites/TipRow.tsxlib/theme/theme.tspackage.json
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (11)
app/(auth)/register/gender.tsx (1)
47-48: RedundantheaderShown: falseif parent layout already sets it.The
(auth)/_layout.tsxalready configuresscreenOptions={{ headerShown: false }}for all screens under this layout. ThisStack.Screenoverride is redundant but harmless — it provides explicit documentation of intent.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(auth)/register/gender.tsx around lines 47 - 48, The Stack.Screen in gender.tsx redundantly sets options={{ headerShown: false }} even though the parent (auth) layout already applies screenOptions={{ headerShown: false }}; remove the explicit options prop from the Stack.Screen (the Stack.Screen JSX element) to avoid duplication, or if you intended to document intent, replace it with a brief comment above the Stack.Screen instead of the duplicate options attribute.app/(protected)/_layout.tsx (1)
24-24: Unnecessary use ofStyleSheet.flattenon a plain object.
StyleSheet.flattenis designed to merge arrays of styles or registered style objects. For a simple inline object like{ flex: 1 }, you can pass it directly without the overhead.Simplified alternative (if Stack is retained)
- contentStyle: StyleSheet.flatten({ flex: 1 }), + contentStyle: { flex: 1 },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/_layout.tsx at line 24, Replace the unnecessary StyleSheet.flatten call for the contentStyle prop: remove StyleSheet.flatten(...) and pass the plain inline style object directly (e.g., { flex: 1 }) where contentStyle is set in the component (look for the contentStyle assignment in _layout.tsx). This removes overhead and keeps the styling correct for simple objects instead of using StyleSheet.flatten.app/(protected)/favorites/tipdetail.tsx (2)
173-181: Silent fallback to "be-present" may mask navigation bugs.If
tipis undefined (e.g., due to incorrect navigation), the code silently defaults to"be-present"content rather than showing the "Tip not found" fallback. This could hide bugs where the route parameter isn't passed correctly.Consider removing the fallback to make missing parameters explicit:
Proposed change
- const data = TIP_CONTENT[tip ?? "be-present"]; + const data = tip ? TIP_CONTENT[tip] : undefined; if (!data) { return ( <View style={s.root}> - <Text style={{ color: theme.text }}>Tip not found.</Text> + <Text style={{ color: theme.text }}> + {tip ? "Tip not found." : "No tip specified."} + </Text> </View> ); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/favorites/tipdetail.tsx around lines 173 - 181, Replace the silent default lookup that uses TIP_CONTENT[tip ?? "be-present"] with a direct lookup TIP_CONTENT[tip] so a missing route param doesn't get masked; update the const data = ... in tipdetail.tsx to use TIP_CONTENT[tip] (or TIP_CONTENT[String(tip)] if tip is possibly non-string) and keep the existing if (!data) return fallback UI so "Tip not found" is shown when tip is undefined or not found; ensure references to TIP_CONTENT and the data const and the conditional render remain consistent.
287-287: UseThemetype instead ofanyfor type safety.The
makeStylesfunction parameter loses type safety withany. Import and use theThemetype for consistent typing with other components in the codebase.Proposed fix
+import { Theme } from "@/lib/theme/theme"; + // ... at bottom of file ... -const makeStyles = (theme: any) => +const makeStyles = (theme: Theme) =>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/favorites/tipdetail.tsx at line 287, The makeStyles parameter currently uses any which removes type safety; change its signature to accept a Theme type (e.g., import the Theme type from your UI library such as `@mui/material/styles` or your app's central theme typedef) and update the function to const makeStyles = (theme: Theme) => { ... } so the theme parameter is strongly typed; ensure you add the Theme import and adjust any downstream usages of makeStyles if needed.app/(protected)/settings/interests.tsx (1)
90-178: Consider extracting skeleton section into a reusable component.The skeleton loading UI repeats the same structure three times with only the chip count varying. This could be extracted into a
SkeletonSectioncomponent to reduce duplication.Example extraction
const SkeletonSection = ({ chipCount, theme }: { chipCount: number; theme: Theme }) => ( <View style={styles.section}> <View style={[styles.skeletonTitle, { backgroundColor: theme.text + "22" }]} /> <View style={[styles.divider, { backgroundColor: theme.text + "22" }]} /> <View style={styles.wrap}> {Array.from({ length: chipCount }).map((_, i) => ( <View key={i} style={[styles.skeletonChip, { backgroundColor: theme.text + "22" }]} /> ))} </View> </View> ); // Usage: {loading && ( <> <SkeletonSection chipCount={10} theme={theme} /> <SkeletonSection chipCount={8} theme={theme} /> <SkeletonSection chipCount={12} theme={theme} /> </> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/settings/interests.tsx around lines 90 - 178, Duplicate skeleton markup inside the loading branch should be extracted into a reusable component; create a new functional component (e.g., SkeletonSection) that accepts chipCount and theme props and renders the block that currently repeats (the Views using styles.section, styles.skeletonTitle, styles.divider, styles.wrap and the Array.from(...) over styles.skeletonChip), then replace the three repeated blocks in the loading conditional with three <SkeletonSection chipCount={...} theme={theme} /> calls; ensure keys for chips are still stable (use index or composite key) and that the new component is imported/defined in the same file so it can reference the existing styles and theme variable.app/(auth)/register/addProfilePicture.tsx (1)
27-27: Placeholderalert()for profile picture upload.This appears to be a work-in-progress placeholder. Consider adding a TODO comment or tracking this as a follow-up task to implement the actual image picker functionality (the PR summary mentions
expo-image-pickerwas added as a dependency).Would you like me to help generate the image picker implementation or open an issue to track this?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(auth)/register/addProfilePicture.tsx at line 27, The Pressable in addProfilePicture.tsx currently uses a placeholder alert in its onPress handler; replace that placeholder with a real image picker flow (or at minimum a TODO and issue link) by wiring up expo-image-picker: call requestMediaLibraryPermissionsAsync, open launchImageLibraryAsync from the Pressable's onPress, handle user cancellation, and set the selected image into the component state (e.g., update the profile image state/prop used to render the avatar) so the UI shows the chosen picture; if you want to defer implementation instead, replace the alert with a clear TODO comment referencing an issue/PR to implement the picker.app/(protected)/favorites/allcategories.tsx (3)
764-769: Passing unusedideasprop toCategoryGridCard.
ideas={cat.ideas}is passed here, but as noted inCategoryCard.tsx, theCategoryGridCardcomponent does not use this prop. Either remove it from the call site (and type), or utilize it within the component.If removing from the type as suggested in CategoryCard.tsx
<CategoryGridCard label={cat.label} icon={cat.icon} - ideas={cat.ideas} onPress={() => setSelected(cat)} />🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/favorites/allcategories.tsx around lines 764 - 769, The CategoryGridCard call is passing an unused ideas prop (ideas={cat.ideas}); remove this prop from the JSX here and also remove the corresponding prop from the CategoryGridCard/CategoryCard type/interface so the component signature no longer expects ideas; update the CategoryGridCard component (file CategoryCard.tsx or the component's declaration) to delete the ideas prop from its props destructuring/definition and remove any related types/imports, and search for other call sites of CategoryGridCard to delete any remaining ideas references to keep types consistent.
825-825: Consider typingthemeparameter properly.Same as in
CategoryCard.tsx, usinganyloses type safety. Use theThemetype from your theme module.Proposed fix
+import { Theme } from "@/lib/theme/theme"; + -const makeStyles = (theme: any) => +const makeStyles = (theme: Theme) =>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/favorites/allcategories.tsx at line 825, The parameter type for makeStyles is currently any; replace it with the proper Theme type used elsewhere (e.g., import and use Theme from your theme module) so the signature becomes makeStyles = (theme: Theme) => ...; update the import to bring in Theme (matching how CategoryCard.tsx does it) and fix any resulting type errors in the function body by narrowing properties to the Theme interface.
42-45:Dimensions.getat module level won't update on orientation/resize.
widthis captured once at module load. If the app supports rotation or runs on tablets with resizable windows, the card sizing will be stale. Consider usinguseWindowDimensionshook inside the component for reactive sizing.Proposed fix
-import { - Dimensions, - Modal, +import { + Modal, Pressable, ScrollView, StyleSheet, Text, View, + useWindowDimensions, } from "react-native"; -const { width } = Dimensions.get("window"); -const H_PAD = 16; -const COL_GAP = 10; -const CARD_SIZE = (width - H_PAD * 2 - COL_GAP * 2) / 3; +const H_PAD = 16; +const COL_GAP = 10; export default function AllCategories() { const { theme } = useTheme(); + const { width } = useWindowDimensions(); + const CARD_SIZE = (width - H_PAD * 2 - COL_GAP * 2) / 3; const s = makeStyles(theme);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/favorites/allcategories.tsx around lines 42 - 45, The module-level Dimensions.get("window") call captures width once; replace it by using the useWindowDimensions hook inside the component and compute the responsive card size there: remove or stop using the module-level const width and CARD_SIZE, import useWindowDimensions from react-native, call const { width } = useWindowDimensions() inside the component, then compute CARD_SIZE = (width - H_PAD * 2 - COL_GAP * 2) / 3 (keeping H_PAD and COL_GAP constants) and use that CARD_SIZE where the component currently references the module-level CARD_SIZE (e.g., in allcategories.tsx render/layout).components/favorites/CategoryCard.tsx (2)
91-91: Consider typingthemeparameter properly.Using
anyfor thethemeparameter loses type safety. Import and use theThemetype from your theme module.Proposed fix
+import { Theme } from "@/lib/theme/theme"; + -function IdeaCard({ idea, theme }: { idea: DateIdea; theme: any }) { +function IdeaCard({ idea, theme }: { idea: DateIdea; theme: Theme }) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/favorites/CategoryCard.tsx` at line 91, The IdeaCard function currently types the theme parameter as any; import the proper Theme type from the project's theme module (e.g., import { Theme } from "path/to/theme") and change the signature to function IdeaCard({ idea, theme }: { idea: DateIdea; theme: Theme }) so callers and internal usages gain type safety; update any places that pass a theme to satisfy the Theme interface if needed.
13-20:ideasprop declared but unused inCategoryGridCard.The
Propstype includesideas: DateIdea[], butCategoryGridCard(line 20) destructures onlylabel,icon, andonPress. Either removeideasfrom the type or use it in the component.Proposed fix
type Props = { label: string; icon: LucideIcon; - ideas: DateIdea[]; onPress: () => void; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/favorites/CategoryCard.tsx` around lines 13 - 20, The Props type declares ideas: DateIdea[] but CategoryGridCard only destructures { label, icon: Icon, onPress }, so remove the unused ideas prop from the Props type if the component does not need it, or if it should be used, add ideas to the component signature (CategoryGridCard({ label, icon: Icon, onPress, ideas }: Props)) and incorporate it where appropriate (e.g., render a count, preview, or pass it to a child); update any callers/consumers to match the new prop shape accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/_layout.tsx`:
- Line 1: Root-level Stack nesting breaks navigation; keep a single Stack in
app/_layout.tsx and replace the Stack components in group and nested layouts
(symbols: Stack usage in app/(auth)/_layout.tsx, app/(protected)/_layout.tsx and
nested layouts like app/(auth)/register/_layout.tsx,
app/(protected)/favorites/_layout.tsx, app/(protected)/videocall/_layout.tsx,
app/(protected)/settings/_layout.tsx) with Slot so they no longer declare their
own navigators; remove Stack imports and JSX from those group/layout files,
import and render Slot instead, and ensure only app/_layout.tsx declares the
Stack to restore proper transitions, gestures, and history handling.
In `@app/`(protected)/_layout.tsx:
- Around line 20-27: The protected layout currently returns a nested Stack
component (Stack) which causes double-stack navigation issues; replace the
nested Stack return with a Slot so the parent navigator drives routing—open the
_layout.tsx where Stack is returned and remove the Stack wrapper and its
screenOptions/contentStyle, and return <Slot /> (apply any needed container
styling around Slot instead of using Stack props) so routes under this layout
are rendered by the parent navigator.
In `@app/`(protected)/favorites/_layout.tsx:
- Around line 1-5: The FavoritesLayout currently returns a Stack which creates a
triple-nested navigator; change the parent "protected" layout to use Slot
(replace its use of Stack with Slot) so that the favorites-level Stack
(FavoritesLayout using Stack) is the only navigator for favorites-specific
routes; specifically, update the protected layout component (the component that
conditionally renders authenticated routes) to import and return Slot instead of
Stack, leaving FavoritesLayout and its Stack/ screenOptions intact to manage
allcategories and tipdetail.
In `@app/`(protected)/settings/interests.tsx:
- Around line 59-67: The onContinue handler is still wired to the registration
flow: it uses registration-only stores/translations and navigates to
/register/addProfileData; update it to operate in the settings context by
removing/renaming any useRegisterStore usage and instead call the settings-state
updater (e.g., setInterests from the settings store or context) with the
selected interests, replace registration i18n keys
(createT("auth.register.interests")) with the settings namespace keys, and
change the navigation from router.push("/register/addProfileData") to
router.back() (or call the profile update API if you intend to persist
immediately); ensure the function named onContinue, the state setter
setInterests, the selected variable, and router.back()/API call are updated
accordingly.
In `@components/favorites/CategoryCard.tsx`:
- Around line 203-217: The styles premiumBadgeText, premiumTitle, and premiumSub
in CategoryCard currently hardcode white colors which will be unreadable on
light theme.primary; change these to derive contrast-safe colors from the theme
(e.g., use an existing theme variable like theme.colors.textOnPrimary or compute
a readable color based on theme.primary) and replace the hardcoded "#fff" and
"rgba(255,255,255,0.7)" with those theme-derived values so text color adapts to
light/dark primary backgrounds.
---
Nitpick comments:
In `@app/`(auth)/register/addProfilePicture.tsx:
- Line 27: The Pressable in addProfilePicture.tsx currently uses a placeholder
alert in its onPress handler; replace that placeholder with a real image picker
flow (or at minimum a TODO and issue link) by wiring up expo-image-picker: call
requestMediaLibraryPermissionsAsync, open launchImageLibraryAsync from the
Pressable's onPress, handle user cancellation, and set the selected image into
the component state (e.g., update the profile image state/prop used to render
the avatar) so the UI shows the chosen picture; if you want to defer
implementation instead, replace the alert with a clear TODO comment referencing
an issue/PR to implement the picker.
In `@app/`(auth)/register/gender.tsx:
- Around line 47-48: The Stack.Screen in gender.tsx redundantly sets options={{
headerShown: false }} even though the parent (auth) layout already applies
screenOptions={{ headerShown: false }}; remove the explicit options prop from
the Stack.Screen (the Stack.Screen JSX element) to avoid duplication, or if you
intended to document intent, replace it with a brief comment above the
Stack.Screen instead of the duplicate options attribute.
In `@app/`(protected)/_layout.tsx:
- Line 24: Replace the unnecessary StyleSheet.flatten call for the contentStyle
prop: remove StyleSheet.flatten(...) and pass the plain inline style object
directly (e.g., { flex: 1 }) where contentStyle is set in the component (look
for the contentStyle assignment in _layout.tsx). This removes overhead and keeps
the styling correct for simple objects instead of using StyleSheet.flatten.
In `@app/`(protected)/favorites/allcategories.tsx:
- Around line 764-769: The CategoryGridCard call is passing an unused ideas prop
(ideas={cat.ideas}); remove this prop from the JSX here and also remove the
corresponding prop from the CategoryGridCard/CategoryCard type/interface so the
component signature no longer expects ideas; update the CategoryGridCard
component (file CategoryCard.tsx or the component's declaration) to delete the
ideas prop from its props destructuring/definition and remove any related
types/imports, and search for other call sites of CategoryGridCard to delete any
remaining ideas references to keep types consistent.
- Line 825: The parameter type for makeStyles is currently any; replace it with
the proper Theme type used elsewhere (e.g., import and use Theme from your theme
module) so the signature becomes makeStyles = (theme: Theme) => ...; update the
import to bring in Theme (matching how CategoryCard.tsx does it) and fix any
resulting type errors in the function body by narrowing properties to the Theme
interface.
- Around line 42-45: The module-level Dimensions.get("window") call captures
width once; replace it by using the useWindowDimensions hook inside the
component and compute the responsive card size there: remove or stop using the
module-level const width and CARD_SIZE, import useWindowDimensions from
react-native, call const { width } = useWindowDimensions() inside the component,
then compute CARD_SIZE = (width - H_PAD * 2 - COL_GAP * 2) / 3 (keeping H_PAD
and COL_GAP constants) and use that CARD_SIZE where the component currently
references the module-level CARD_SIZE (e.g., in allcategories.tsx
render/layout).
In `@app/`(protected)/favorites/tipdetail.tsx:
- Around line 173-181: Replace the silent default lookup that uses
TIP_CONTENT[tip ?? "be-present"] with a direct lookup TIP_CONTENT[tip] so a
missing route param doesn't get masked; update the const data = ... in
tipdetail.tsx to use TIP_CONTENT[tip] (or TIP_CONTENT[String(tip)] if tip is
possibly non-string) and keep the existing if (!data) return fallback UI so "Tip
not found" is shown when tip is undefined or not found; ensure references to
TIP_CONTENT and the data const and the conditional render remain consistent.
- Line 287: The makeStyles parameter currently uses any which removes type
safety; change its signature to accept a Theme type (e.g., import the Theme type
from your UI library such as `@mui/material/styles` or your app's central theme
typedef) and update the function to const makeStyles = (theme: Theme) => { ... }
so the theme parameter is strongly typed; ensure you add the Theme import and
adjust any downstream usages of makeStyles if needed.
In `@app/`(protected)/settings/interests.tsx:
- Around line 90-178: Duplicate skeleton markup inside the loading branch should
be extracted into a reusable component; create a new functional component (e.g.,
SkeletonSection) that accepts chipCount and theme props and renders the block
that currently repeats (the Views using styles.section, styles.skeletonTitle,
styles.divider, styles.wrap and the Array.from(...) over styles.skeletonChip),
then replace the three repeated blocks in the loading conditional with three
<SkeletonSection chipCount={...} theme={theme} /> calls; ensure keys for chips
are still stable (use index or composite key) and that the new component is
imported/defined in the same file so it can reference the existing styles and
theme variable.
In `@components/favorites/CategoryCard.tsx`:
- Line 91: The IdeaCard function currently types the theme parameter as any;
import the proper Theme type from the project's theme module (e.g., import {
Theme } from "path/to/theme") and change the signature to function IdeaCard({
idea, theme }: { idea: DateIdea; theme: Theme }) so callers and internal usages
gain type safety; update any places that pass a theme to satisfy the Theme
interface if needed.
- Around line 13-20: The Props type declares ideas: DateIdea[] but
CategoryGridCard only destructures { label, icon: Icon, onPress }, so remove the
unused ideas prop from the Props type if the component does not need it, or if
it should be used, add ideas to the component signature (CategoryGridCard({
label, icon: Icon, onPress, ideas }: Props)) and incorporate it where
appropriate (e.g., render a count, preview, or pass it to a child); update any
callers/consumers to match the new prop shape accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 56234695-ced1-45da-a35a-c2a626021e66
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (14)
app/(auth)/register/addProfilePicture.tsxapp/(auth)/register/gender.tsxapp/(protected)/(tabs)/favorites.tsxapp/(protected)/(tabs)/settings.tsxapp/(protected)/_layout.tsxapp/(protected)/favorites/_layout.tsxapp/(protected)/favorites/allcategories.tsxapp/(protected)/favorites/tipdetail.tsxapp/(protected)/settings/interests.tsxapp/(protected)/settings/personaldetails.tsxapp/_layout.tsxcomponents/favorites/CategoryCard.tsxcomponents/favorites/TipSection.tsxpackage.json
✅ Files skipped from review due to trivial changes (1)
- package.json
🚧 Files skipped from review as they are similar to previous changes (3)
- app/(protected)/(tabs)/settings.tsx
- app/(protected)/settings/personaldetails.tsx
- app/(protected)/(tabs)/favorites.tsx
…y, and dead UI controls (#136)
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (2)
app/(protected)/settings/interests.tsx (1)
32-33:⚠️ Potential issue | 🟠 MajorPersist and hydrate interests before returning.
selectedstarts empty andonContinueonly callsrouter.back(), so existing interests are not shown and any edits are discarded. Wire this to the user profile/settings state or save API before leaving the screen.Do you want me to draft the profile hydration/save flow once the intended settings API or store is confirmed?
Also applies to: 59-66
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/settings/interests.tsx around lines 32 - 33, The settings page currently initializes selected via useState and onContinue only calls router.back(), so interests are neither hydrated nor persisted; update the component to hydrate selected from the user profile/store on mount (replace/remove useRegisterStore and read from the intended profile state or settings API) and persist changes before navigating away in the onContinue handler (call the profile/settings save API or update the global store with setSelected/state setter, await the save, then router.back()); ensure the same persistence/hydration logic is applied to the other related handlers/fields referenced in lines 59-66.app/(protected)/(tabs)/stats.tsx (1)
270-282:⚠️ Potential issue | 🟠 MajorReplace remaining hardcoded muted grays with theme-derived text colors.
Small labels still use fixed gray values, which can fail contrast depending on the active theme. Use
theme.textwith an alpha instead so light/dark palettes stay readable.🎨 Proposed contrast fix
- statLabel: { color: "#aaa", fontSize: 12, lineHeight: 16 }, + statLabel: { color: theme.text + "99", fontSize: 12, lineHeight: 16 }, - streakSub: { color: "#aaa", fontSize: 12 }, + streakSub: { color: theme.text + "99", fontSize: 12 }, - dayLabel: { color: "#555", fontSize: 10 }, + dayLabel: { color: theme.text + "99", fontSize: 10 }, - barLabel: { color: "#555", fontSize: 9 }, - chartNote: { color: "#666", fontSize: 11, lineHeight: 15, marginTop: 2 }, + barLabel: { color: theme.text + "99", fontSize: 9 }, + chartNote: { color: theme.text + "99", fontSize: 11, lineHeight: 15, marginTop: 2 },Also applies to: 321-340
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/(tabs)/stats.tsx around lines 270 - 282, Replace hardcoded muted grays with theme-derived translucent text colors: update the style objects (statLabel and streakSub, and any other entries still using "#aaa") to use the theme text color with an alpha instead of "#aaa" — e.g., call the existing color helper (or create a small helper like withAlpha(theme.text, 0.6)) and set statLabel: { color: withAlpha(theme.text, 0.6), ... } and streakSub: { color: withAlpha(theme.text, 0.6), ... } so light/dark themes keep proper contrast; apply the same change to the other occurrences mentioned (the remaining entries between the later block).
🧹 Nitpick comments (5)
app/(protected)/(tabs)/stats.tsx (1)
206-206: Type the style factory with the sharedTheme.
anymasks theme token mistakes in this screen. SinceThemeis already exported fromlib/theme/theme, use it here.♻️ Proposed typing improvement
import { router } from "expo-router"; import { View, Text, TouchableOpacity, StyleSheet } from "react-native"; import { useTheme } from "@/lib/theme/context"; +import type { Theme } from "@/lib/theme/theme"; import { Check, Clock, Flame, Heart, Snowflake } from "lucide-react-native";-const makeStyles = (theme: any) => +const makeStyles = (theme: Theme) =>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/(tabs)/stats.tsx at line 206, The style factory makeStyles is currently typed with any which hides theme token errors; import the shared Theme type from lib/theme/theme and change the signature to use it (e.g., makeStyles = (theme: Theme) => ...) so the function and any theme token usages are type-checked; update the import list to include Theme and adjust any downstream references to the theme parameter if needed.components/favorites/CategoryCard.tsx (1)
134-140: Unused stylesiconWrapandpremiumInner.Neither key is referenced anywhere in this file. Safe to delete to avoid future confusion.
Also applies to: 195-198
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/favorites/CategoryCard.tsx` around lines 134 - 140, Remove the unused style keys iconWrap and premiumInner from the styles object in CategoryCard.tsx: locate the style definitions named iconWrap and premiumInner in the exported styles (references to iconWrap around the block with width/height/borderRadius and premiumInner around lines ~195-198) and delete those key/value entries (and any dangling commas) so the styles object no longer contains these unused properties.components/favorites/DateIdeaCard.tsx (1)
70-70: Typethemeparameter with the exportedThemetype.
makeStyles(theme: any)loses all safety on a palette you already control.Themeis exported from@/lib/theme/themeand is the literal return type ofuseTheme().theme, so typing it here would catch stale token references (e.g. thetheme.white/theme.planPremium/cardBgDeepfields you're reading).♻️ Proposed change
-import { useTheme } from "@/lib/theme/context"; +import { useTheme } from "@/lib/theme/context"; +import type { Theme } from "@/lib/theme/theme"; @@ -const makeStyles = (theme: any) => +const makeStyles = (theme: Theme) =>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/favorites/DateIdeaCard.tsx` at line 70, The makeStyles function currently types its parameter as any; change its signature to accept the exported Theme type so TS can validate usage of palette tokens. Import Theme from "@/lib/theme/theme" and update const makeStyles = (theme: any) => to use that type (e.g., makeStyles = (theme: Theme) =>), then ensure any places reading theme.white, theme.planPremium, cardBgDeep, etc., match the Theme shape so stale token names are caught by the compiler.app/(protected)/(tabs)/favorites.tsx (1)
132-132:scrollRefis assigned but never used.The ref is attached to the horizontal
ScrollViewon line 153 but is never read (no imperativescrollTo, no tap-to-page-from-dots behavior). Either wire the dot row to callscrollRef.current?.scrollTo({ x: i * cardWidth, animated: true })on tap to make the dots interactive, or drop the ref/useRefimport.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/(tabs)/favorites.tsx at line 132, scrollRef is created but never used; either make the dot-row buttons call scrollRef.current?.scrollTo({ x: i * cardWidth, animated: true }) to jump the horizontal ScrollView (ensure the ScrollView uses ref={scrollRef} and cardWidth/spacing used to compute x), or remove the useRef import and the const scrollRef = useRef<ScrollView>(null) line and delete the unused ref on the ScrollView; update the dot click handler (e.g., onPress for the dots) to invoke scrollTo if you choose the interactive dots route.app/(protected)/favorites/tipdetail.tsx (1)
287-287: TypemakeStylesparameter withTheme.Same note as
DateIdeaCard: importThemefrom@/lib/theme/themeand drop theanysotheme.rootBg ?? theme.background,theme.text, etc. are type-checked.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/favorites/tipdetail.tsx at line 287, Change the makeStyles parameter from any to the concrete Theme type: import Theme from "@/lib/theme/theme" (or named import as exported) and update the signature from makeStyles = (theme: any) => to makeStyles = (theme: Theme) => so usages like theme.rootBg ?? theme.background, theme.text, etc. are type-checked; update any related local references/signatures to match the Theme import.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/`(protected)/(tabs)/favorites.tsx:
- Line 325: The dot style currently hardcodes backgroundColor: "#333" in the
style object named dot, which makes the inactive indicator low-contrast in dark
mode; change dot's backgroundColor to use the theme palette (e.g.,
theme.barInactive or derive from theme.text with an alpha like theme.text +
"33") so the inactive dot adapts to light/dark themes and matches the rest of
the UI (update the dot style in favorites.tsx where the dot style object is
defined).
In `@app/`(protected)/(tabs)/stats.tsx:
- Line 31: Replace the fragile relative route used in the onPress router push
with the absolute protected route: find the onPress handler that calls
router.push("../(protected)/subscriptions") in the stats component (in the
onPress lambda) and the similar router.push call in favorites.tsx (around the
handler at line ~298) and change the argument to "/(protected)/subscriptions" so
navigation uses the absolute path consistent with other routes like
"/(protected)/videocall" and "/(protected)/info".
In `@app/`(protected)/favorites/tipdetail.tsx:
- Around line 40-166: TIP_CONTENT and its types are duplicated and the detail
route is unreachable; extract the tip dataset and TipData/Section types into a
shared module (e.g., lib/favorites/tips.ts) and replace the inline TIP_CONTENT
in tipdetail.tsx and the copy in favorites.tsx with imports of that module (keep
TIP_CONTENT, TipData, and Section as the canonical symbols), update the modal
rendering in favorites.tsx to only use the freeSections subset from the shared
data, and either wire TipRow to navigate to the detail screen by calling
router.push('/favorites/tipdetail?tip=' + tipKey) (passing tipKey as tip)
instead of opening the in-place Modal or remove the /favorites/tipdetail route
if you intend to keep the modal-only flow.
In `@app/`(protected)/settings/interests.tsx:
- Around line 249-252: The Button is currently disabled when !canContinue which
prevents onContinue from running and showing validation for selections below
MIN; change the disabled prop to only block while loading (and any explicit
fetch/error state if present) so that onContinue can always run
validation—update the Button's disabled from disabled={!canContinue || loading}
to disabled={loading /* || fetchError */} and keep onContinue responsible for
checking canContinue/MIN and showing the validation overlay.
In `@components/favorites/CategoryCard.tsx`:
- Around line 15-41: The Props type declares ideas: DateIdea[] but
CategoryGridCard never uses it; remove ideas from Props (rename to
CategoryGridCardProps if you like), update the function signature export
function CategoryGridCard({ label, icon: Icon, onPress }: CategoryGridCardProps)
and delete the unused DateIdea import, then update callers (e.g., the
favorites.tsx call site) to stop passing ideas={[]} (or move ideas to a
different component that actually renders them if you need that data elsewhere).
Ensure all references to Props.ideas are removed or replaced with the
appropriate component that consumes ideas.
- Line 74: Replace the relative route that incorrectly includes the group
segment with the absolute path "/subscriptions": find the onPress using
router.push("../(protected)/subscriptions") in CategoryCard (and the other two
spots flagged) and change it to router.push("/subscriptions"); likewise update
any Link or href occurrences that reference "../(protected)/subscriptions" to
use "/subscriptions" so the group segment is not embedded in the URL.
In `@hooks/usePushNotifications.ts`:
- Line 4: The import of expo-notifications is incorrect: replace the default
import with a namespace import so Notifications is defined (change the import
that currently reads importing Notifications and EventSubscription to use import
* as Notifications for the Notifications namespace while still importing the
EventSubscription type), then ensure all calls like
Notifications.setNotificationHandler(...) and any other Notifications.* usages
continue to reference the namespace; update the import statement referencing
EventSubscription accordingly to avoid runtime "Cannot read properties of
undefined" errors.
---
Duplicate comments:
In `@app/`(protected)/(tabs)/stats.tsx:
- Around line 270-282: Replace hardcoded muted grays with theme-derived
translucent text colors: update the style objects (statLabel and streakSub, and
any other entries still using "#aaa") to use the theme text color with an alpha
instead of "#aaa" — e.g., call the existing color helper (or create a small
helper like withAlpha(theme.text, 0.6)) and set statLabel: { color:
withAlpha(theme.text, 0.6), ... } and streakSub: { color: withAlpha(theme.text,
0.6), ... } so light/dark themes keep proper contrast; apply the same change to
the other occurrences mentioned (the remaining entries between the later block).
In `@app/`(protected)/settings/interests.tsx:
- Around line 32-33: The settings page currently initializes selected via
useState and onContinue only calls router.back(), so interests are neither
hydrated nor persisted; update the component to hydrate selected from the user
profile/store on mount (replace/remove useRegisterStore and read from the
intended profile state or settings API) and persist changes before navigating
away in the onContinue handler (call the profile/settings save API or update the
global store with setSelected/state setter, await the save, then router.back());
ensure the same persistence/hydration logic is applied to the other related
handlers/fields referenced in lines 59-66.
---
Nitpick comments:
In `@app/`(protected)/(tabs)/favorites.tsx:
- Line 132: scrollRef is created but never used; either make the dot-row buttons
call scrollRef.current?.scrollTo({ x: i * cardWidth, animated: true }) to jump
the horizontal ScrollView (ensure the ScrollView uses ref={scrollRef} and
cardWidth/spacing used to compute x), or remove the useRef import and the const
scrollRef = useRef<ScrollView>(null) line and delete the unused ref on the
ScrollView; update the dot click handler (e.g., onPress for the dots) to invoke
scrollTo if you choose the interactive dots route.
In `@app/`(protected)/(tabs)/stats.tsx:
- Line 206: The style factory makeStyles is currently typed with any which hides
theme token errors; import the shared Theme type from lib/theme/theme and change
the signature to use it (e.g., makeStyles = (theme: Theme) => ...) so the
function and any theme token usages are type-checked; update the import list to
include Theme and adjust any downstream references to the theme parameter if
needed.
In `@app/`(protected)/favorites/tipdetail.tsx:
- Line 287: Change the makeStyles parameter from any to the concrete Theme type:
import Theme from "@/lib/theme/theme" (or named import as exported) and update
the signature from makeStyles = (theme: any) => to makeStyles = (theme: Theme)
=> so usages like theme.rootBg ?? theme.background, theme.text, etc. are
type-checked; update any related local references/signatures to match the Theme
import.
In `@components/favorites/CategoryCard.tsx`:
- Around line 134-140: Remove the unused style keys iconWrap and premiumInner
from the styles object in CategoryCard.tsx: locate the style definitions named
iconWrap and premiumInner in the exported styles (references to iconWrap around
the block with width/height/borderRadius and premiumInner around lines ~195-198)
and delete those key/value entries (and any dangling commas) so the styles
object no longer contains these unused properties.
In `@components/favorites/DateIdeaCard.tsx`:
- Line 70: The makeStyles function currently types its parameter as any; change
its signature to accept the exported Theme type so TS can validate usage of
palette tokens. Import Theme from "@/lib/theme/theme" and update const
makeStyles = (theme: any) => to use that type (e.g., makeStyles = (theme: Theme)
=>), then ensure any places reading theme.white, theme.planPremium, cardBgDeep,
etc., match the Theme shape so stale token names are caught by the compiler.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 37de470c-1c18-49c8-82a0-840ae68238b8
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (17)
.claude/settings.local.json.gitignoreapp/(auth)/register/addProfilePicture.tsxapp/(protected)/(tabs)/favorites.tsxapp/(protected)/(tabs)/settings.tsxapp/(protected)/(tabs)/stats.tsxapp/(protected)/_layout.tsxapp/(protected)/favorites/tipdetail.tsxapp/(protected)/settings/interests.tsxapp/(protected)/settings/personaldetails.tsxcomponents/ServerStatusSheet.tsxcomponents/favorites/CategoryCard.tsxcomponents/favorites/DateIdeaCard.tsxcomponents/favorites/TipRow.tsxhooks/usePushNotifications.tslib/theme/theme.tspackage.json
✅ Files skipped from review due to trivial changes (5)
- components/ServerStatusSheet.tsx
- .gitignore
- .claude/settings.local.json
- app/(protected)/_layout.tsx
- package.json
🚧 Files skipped from review as they are similar to previous changes (5)
- app/(auth)/register/addProfilePicture.tsx
- app/(protected)/settings/personaldetails.tsx
- components/favorites/TipRow.tsx
- lib/theme/theme.ts
- app/(protected)/(tabs)/settings.tsx
| styles.blurOverlay, | ||
| { backgroundColor: theme.background + "CC" }, | ||
| ]} | ||
| onPress={() => router.push("../(protected)/subscriptions")} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm the canonical route used across the app and flag any other callers of the (protected) group path.
rg -nP --type=tsx --type=ts -C1 '(router\.(push|replace|navigate)|href=)[^)]*subscriptions'Repository: MindsofD23b/Frontend-Elysio
Length of output: 98
🏁 Script executed:
#!/bin/bash
# Search for router.push/replace patterns with subscriptions (using correct syntax)
rg 'router\.(push|replace|navigate).*subscriptions' --max-count 20Repository: MindsofD23b/Frontend-Elysio
Length of output: 419
🏁 Script executed:
#!/bin/bash
# Read the specific file mentioned in the review
cat -n components/favorites/CategoryCard.tsx | sed -n '70,80p'Repository: MindsofD23b/Frontend-Elysio
Length of output: 654
🏁 Script executed:
#!/bin/bash
# Read the other file mentioned
cat -n app/\(protected\)/\(tabs\)/favorites.tsx | sed -n '295,305p'Repository: MindsofD23b/Frontend-Elysio
Length of output: 707
🏁 Script executed:
#!/bin/bash
# Read the correct pattern from settings.tsx
cat -n app/\(protected\)/\(tabs\)/settings.tsx | sed -n '70,75p'Repository: MindsofD23b/Frontend-Elysio
Length of output: 329
🏁 Script executed:
#!/bin/bash
# Search for absolute /subscriptions route usage
rg '/subscriptions' --max-count 20Repository: MindsofD23b/Frontend-Elysio
Length of output: 789
🏁 Script executed:
#!/bin/bash
# Check app structure to understand route organization
find app -type f -name "*.tsx" -o -name "*.ts" | head -20Repository: MindsofD23b/Frontend-Elysio
Length of output: 713
🏁 Script executed:
#!/bin/bash
# Search more broadly in settings.tsx for subscriptions pattern
cat -n app/\(protected\)/\(tabs\)/settings.tsx | grep -i subscriptionsRepository: MindsofD23b/Frontend-Elysio
Length of output: 168
🏁 Script executed:
#!/bin/bash
# Check the stats.tsx file mentioned in search results
cat -n app/\(protected\)/\(tabs\)/stats.tsx | grep -B2 -A2 'router.push.*subscriptions'Repository: MindsofD23b/Frontend-Elysio
Length of output: 301
Use absolute route /subscriptions in three locations.
The relative path router.push("../(protected)/subscriptions") embeds the group segment in the navigation path. Group segments wrapped in parentheses are meant to organize files without affecting the URL and should not appear in route references. Additionally, the relative path's correctness depends on the component's location (the .. resolves differently per parent route).
The canonical route used elsewhere in the app is the absolute path /subscriptions:
app/(protected)/(tabs)/settings.tsxlines 79, 87:href="/subscriptions"app/(protected)/favorites/tipdetail.tsx:<Link href="/subscriptions"
Fix these three locations:
components/favorites/CategoryCard.tsxline 74app/(protected)/(tabs)/favorites.tsxline 298app/(protected)/(tabs)/stats.tsxline 31
Example fix
- onPress={() => router.push("../(protected)/subscriptions")}
+ onPress={() => router.push("/subscriptions")}📝 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.
| onPress={() => router.push("../(protected)/subscriptions")} | |
| onPress={() => router.push("/subscriptions")} |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@components/favorites/CategoryCard.tsx` at line 74, Replace the relative route
that incorrectly includes the group segment with the absolute path
"/subscriptions": find the onPress using
router.push("../(protected)/subscriptions") in CategoryCard (and the other two
spots flagged) and change it to router.push("/subscriptions"); likewise update
any Link or href occurrences that reference "../(protected)/subscriptions" to
use "/subscriptions" so the group segment is not embedded in the URL.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
app/(protected)/(tabs)/favorites.tsx (1)
148-148:⚠️ Potential issue | 🟡 MinorInactive dot color still hardcoded to
"#333".This was raised previously and remains unresolved:
"#333"is nearly invisible against the darkrootBg(#141414). Derive from the theme for parity with the rest of the screen.🎨 Proposed fix
- dot: { width: 6, height: 6, borderRadius: 3, backgroundColor: "#333" }, + dot: { width: 6, height: 6, borderRadius: 3, backgroundColor: theme.barInactive },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/(tabs)/favorites.tsx at line 148, The inactive dot's color is hardcoded as "#333" in the "dot" style; replace it with a color derived from the app theme (e.g., obtain the theme via useTheme() or the app's color hook and use the appropriate dim/secondary text token such as theme.colors.muted or theme.textDim) and update the dot style's backgroundColor to use that token instead of "#333" in the Favorites component (the "dot" style object in favorites.tsx).
🧹 Nitpick comments (3)
app/(protected)/(tabs)/stats.tsx (2)
206-206: TypemakeStyleswithThemeinstead ofany.The
Themetype is already exported fromlib/theme/theme.tsand consumed byuseTheme(). Usinganyhere silently drops autocomplete and would hide typos liketheme.matchColourthat a typed parameter would catch at build time.♻️ Proposed refactor
-const makeStyles = (theme: any) => +import type { Theme } from "@/lib/theme/theme"; + +const makeStyles = (theme: Theme) => StyleSheet.create({🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/(tabs)/stats.tsx at line 206, Change the makeStyles parameter from any to the exported Theme type: import Theme from lib/theme/theme.ts (the same Theme used by useTheme()) and update the signature const makeStyles = (theme: Theme) => ... so the theme parameter is strongly typed; this will restore autocomplete and catch typos like theme.matchColour at compile time. Ensure the import uses the correct named/default export as defined in lib/theme/theme.ts and update any downstream usages if necessary.
98-99: Dead default forIconComp.The default
<Check size={14} color="#3b3a3b" />is never rendered: whenisInactiveis true, line 124 gates it out, and every other branch reassignsIconComp. You can drop the default icon (and simplify the hardcoded color) to make the control flow clearer.🧹 Proposed cleanup
- let circleStyle: object[] = [s.dayCircle]; - let IconComp = <Check size={14} color="#3b3a3b" />; - - if (isSingleDone) { + let circleStyle: object[] = [s.dayCircle]; + let IconComp: React.ReactNode = null; + + if (isSingleDone) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/`(protected)/(tabs)/stats.tsx around lines 98 - 99, The default assignment of IconComp to <Check size={14} color="#3b3a3b" /> is dead code because isInactive and all other branches overwrite it; remove the initial IconComp default from the declaration (leave it undefined or null), and move any required color/size into the actual branch renderings so branches set the icon explicitly; update references around circleStyle and IconComp (the s.dayCircle usage and the isInactive conditional) to rely on the branch-assigned IconComp instead of a hardcoded default.lib/favorites/tips.ts (1)
61-61: Optional: narrow theTIP_CONTENTkey type.
Record<string, TipData>allows any string lookup to type-check, which loses compile-time safety whentipdetail.tsxindexes with a search param. Consider a literal union keyed offTIPS[number]["tipKey"]so invalid keys are caught at the call site:♻️ Proposed refactor
-export const TIP_CONTENT: Record<string, TipData> = { +export type TipKey = "be-present" | "active-listening" | "stay-curious"; + +export const TIP_CONTENT: Record<TipKey, TipData> = {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/favorites/tips.ts` at line 61, TIP_CONTENT is typed as Record<string, TipData>, which permits any string key and prevents compile-time checks when tipdetail.tsx indexes by a search param; change the key type to a literal union derived from your declared list of tips (e.g. use the tip key union like TIPS[number]["tipKey"] or extract a type alias from the TIPS array) so TIP_CONTENT becomes Record<TipKeyUnion, TipData> (or a mapped type) to ensure invalid keys are caught at the call site; update TIP_CONTENT's declaration and any usages in tipdetail.tsx to use that union type instead of plain string while keeping TipData as the value type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@app/`(protected)/(tabs)/favorites.tsx:
- Line 142: Change the loose theme parameter typing in makeStyles to use the
proper Theme type: import Theme from "@/lib/theme/theme" and update the function
signature from makeStyles = (theme: any) => to makeStyles = (theme: Theme) => so
theme.rootBg and theme.primary are type-checked; ensure the import is added and
any existing usages of makeStyles still accept the typed Theme.
In `@app/`(protected)/(tabs)/stats.tsx:
- Line 270: Several text style entries in stats.tsx (statLabel, streakSub,
dayLabel, barLabel, chartNote) use hardcoded gray hexes (`#aaa/`#555/#666) which
fail contrast in light mode; replace those hardcoded colors with theme-aware
muted text like theme.text + "99" or theme.text + "AA" (or another appropriate
opacity) so the muted copy adapts to both palettes; update the style
objects/variables where statLabel and streakSub are defined and also the entries
referenced around the other occurrences (dayLabel, barLabel, chartNote) to use
theme.text + opacity instead of the fixed hex values.
- Around line 286-295: The pillTrack style uses inconsistent magic multipliers
(105 and 90) so it won’t align with the day circles when DAYS_LEN, LINE_START or
LINE_END change; update the left and width calculations in the pillTrack block
to use the same base percent: set left to `${(LINE_START / DAYS_LEN) * 100}%`
and width to `${((LINE_END - LINE_START + 1) / DAYS_LEN) * 100}%`, then subtract
or add a consistent centering offset for the circle diameter (or alternatively
compute exact pixel positions via onLayout and derive left/width from those
measurements) so the pillTrack aligns with the circle centers (referencing
pillTrack, LINE_START, LINE_END, DAYS_LEN).
---
Duplicate comments:
In `@app/`(protected)/(tabs)/favorites.tsx:
- Line 148: The inactive dot's color is hardcoded as "#333" in the "dot" style;
replace it with a color derived from the app theme (e.g., obtain the theme via
useTheme() or the app's color hook and use the appropriate dim/secondary text
token such as theme.colors.muted or theme.textDim) and update the dot style's
backgroundColor to use that token instead of "#333" in the Favorites component
(the "dot" style object in favorites.tsx).
---
Nitpick comments:
In `@app/`(protected)/(tabs)/stats.tsx:
- Line 206: Change the makeStyles parameter from any to the exported Theme type:
import Theme from lib/theme/theme.ts (the same Theme used by useTheme()) and
update the signature const makeStyles = (theme: Theme) => ... so the theme
parameter is strongly typed; this will restore autocomplete and catch typos like
theme.matchColour at compile time. Ensure the import uses the correct
named/default export as defined in lib/theme/theme.ts and update any downstream
usages if necessary.
- Around line 98-99: The default assignment of IconComp to <Check size={14}
color="#3b3a3b" /> is dead code because isInactive and all other branches
overwrite it; remove the initial IconComp default from the declaration (leave it
undefined or null), and move any required color/size into the actual branch
renderings so branches set the icon explicitly; update references around
circleStyle and IconComp (the s.dayCircle usage and the isInactive conditional)
to rely on the branch-assigned IconComp instead of a hardcoded default.
In `@lib/favorites/tips.ts`:
- Line 61: TIP_CONTENT is typed as Record<string, TipData>, which permits any
string key and prevents compile-time checks when tipdetail.tsx indexes by a
search param; change the key type to a literal union derived from your declared
list of tips (e.g. use the tip key union like TIPS[number]["tipKey"] or extract
a type alias from the TIPS array) so TIP_CONTENT becomes Record<TipKeyUnion,
TipData> (or a mapped type) to ensure invalid keys are caught at the call site;
update TIP_CONTENT's declaration and any usages in tipdetail.tsx to use that
union type instead of plain string while keeping TipData as the value type.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 6b8cb22e-0ca9-4d3a-a002-43f2ce8d22f5
📒 Files selected for processing (5)
app/(protected)/(tabs)/favorites.tsxapp/(protected)/(tabs)/stats.tsxapp/(protected)/favorites/tipdetail.tsxcomponents/favorites/CategoryCard.tsxlib/favorites/tips.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- app/(protected)/favorites/tipdetail.tsx
- components/favorites/CategoryCard.tsx
Jamie-Poeffel
left a comment
There was a problem hiding this comment.
Needs to be fixed before merge
| <BackWrapper> | ||
| <Text style={[gs.h1, { marginTop: 35 }]}>{t("title")}</Text> | ||
| <> | ||
| <Stack.Screen options={{ headerShown: false }} /> |
There was a problem hiding this comment.
| <Stack.Screen options={{ headerShown: false }} /> |
| style={[styles.card, getCardStyle("male")]} | ||
| onPress={() => setSelected("male")} | ||
| <> | ||
| <Stack.Screen options={{ headerShown: false }} /> |
There was a problem hiding this comment.
| <Stack.Screen options={{ headerShown: false }} /> |
|
|
||
| return ( | ||
| <> | ||
| <Stack.Screen options={{ headerShown: false }} /> |
There was a problem hiding this comment.
| <Stack.Screen options={{ headerShown: false }} /> |
…date layout to reflect server status
Check if its to your liking
closes #62
closes #67
closes #63
closes #66
closes #65
closes #49
Summary by CodeRabbit
Release Notes
New Features
Improvements