Skip to content

Feature/favorites - #136

Merged
Jamie-Poeffel merged 22 commits into
devfrom
feature/favorites
Apr 22, 2026
Merged

Jamie-Poeffel merged 22 commits into
devfrom
feature/favorites

Conversation

@Kush-Srigiri

@Kush-Srigiri Kush-Srigiri commented Apr 2, 2026 •

Copy link
Copy Markdown
Collaborator

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

    • Favorites section with curated date ideas, explore categories, and actionable tips featuring horizontal pagination and premium content access
    • Stats dashboard displaying mutual interests metrics, activity streaks, peak online times chart, and top interests
    • Personal details profile page for editing full name, contact info, and avatar upload
    • Interests preference selection with validation
    • Detailed tip pages with premium section previews
  • Improvements

    • Enhanced settings navigation with new personal details and subscription routes
    • Adjusted bottom tab bar spacing on non-iOS devices

…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)
…out (#67)

- #14: fix Field import (default export, no curly braces)
- #14: remove inline Field component from personaldetails.tsx
- #14: move Field into its own file under components/Field.tsx
- #67: start basic layout for datingInfo screen
- #14: Add Scroll
@coderabbitai

coderabbitai Bot commented Apr 2, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Introduces 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

Cohort / File(s) Summary
Favorites UI & Components
app/(protected)/(tabs)/favorites.tsx, components/favorites/DateIdeaCard.tsx, components/favorites/CategoryCard.tsx, components/favorites/TipRow.tsx, components/favorites/TipSection.tsx
Adds a full Favorites screen with horizontally paged "Date Ideas", active-dot pagination, category grid, tip rows, and new reusable UI components (DateIdeaCard, CategoryGridCard, TipRow, TipSection). Local makeStyles(theme) used for styling.
Favorites Routing & Detail Views
app/(protected)/favorites/_layout.tsx, app/(protected)/favorites/allcategories.tsx, app/(protected)/favorites/tipdetail.tsx
Adds Favorites layout (Stack with headers hidden), AllCategories grid with modal sheet, and TipDetail page rendering TIP_CONTENT with free/premium sections and premium CTA overlay.
Stats Screen
app/(protected)/(tabs)/stats.tsx
Replaces placeholder with themed dashboard: premium banner, metrics cards, 7-day streak visualization, "Best time to be online" bar chart, and Top Match Interests list; uses local makeStyles(theme) and router pushes for subscriptions.
Settings & Interests
app/(protected)/(tabs)/settings.tsx, app/(protected)/settings/interests.tsx, app/(protected)/settings/personaldetails.tsx
Updates settings menu hrefs (personalDetails, interests) and adds subscription entry; adds Interests selection screen (3–12 bounds, skeletons, overlay) and new PersonalDetails editor with avatar picker, controlled form fields, birthday formatting, and Save navigation.
Auth route header management
app/(auth)/register/addProfilePicture.tsx, app/(auth)/register/gender.tsx
Adds Stack.Screen with headerShown: false around existing auth screens to manage headers without changing visible behavior.
Theme & Tokens
lib/theme/theme.ts
Expands color tokens for screens, stats, and plans; adjusts dark theme accent value.
New Data/Content
lib/favorites/tips.ts
Adds typed tip data: TIPS list and TIP_CONTENT map with free/premium tip sections and icons.
Small layout/imports/cleanup
app/(protected)/(tabs)/_layout.tsx, app/(protected)/_layout.tsx, components/ServerStatusSheet.tsx, hooks/usePushNotifications.ts
Minor import reordering, removed unused imports, changed expo-notifications import style, and adjusted tab bar padding for non-iOS platforms.
Routing layout for Favorites folder
app/(protected)/favorites/_layout.tsx
Adds default export FavoritesLayout to hide headers for nested favorites routes.
Dependencies & config
package.json, .claude/settings.local.json, .gitignore
Adds expo-modules-core and react-native-keyboard-aware-scroll-view dependencies; adds local Claude permissions config; expands .gitignore for claude-* patterns.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~55 minutes

Possibly related PRs

Suggested labels

Feature

Suggested reviewers

  • Jamie-Poeffel
  • GRuoss
  • LuisAll12

Poem

🐰🌷
I hopped through screens both bright and new,
Cards and tips and charts in view,
A picture picked, a streak aligned,
Categories, colors, all combined —
Hooray! This rabbit says, "Nice work, crew!"

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feature/favorites' is vague and generic, using non-descriptive terms that don't clearly convey the specific changes made in the changeset. Replace the generic title with a more specific summary of the main changes, such as 'Add favorites screen with date ideas carousel and tips' or 'Implement favorites feature with UI components and theme colors'.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/favorites

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 467ac86 and d41e05b.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (12)
  • app/(onboarding)/index.tsx
  • app/(protected)/(tabs)/_layout.tsx
  • app/(protected)/(tabs)/favorites.tsx
  • app/(protected)/(tabs)/settings.tsx
  • app/(protected)/(tabs)/stats.tsx
  • app/(protected)/analytics/premium.tsx
  • app/(protected)/settings/personaldetails.tsx
  • components/favorites/CategoryCard.tsx
  • components/favorites/DateIdeaCard.tsx
  • components/favorites/TipRow.tsx
  • lib/theme/theme.ts
  • package.json

Comment thread app/(protected)/(tabs)/_layout.tsx
Comment thread app/(protected)/(tabs)/favorites.tsx Outdated
Comment thread app/(protected)/(tabs)/favorites.tsx Outdated
Comment thread app/(protected)/(tabs)/stats.tsx Outdated
Comment thread app/(protected)/analytics/premium.tsx Outdated
Comment thread app/(protected)/settings/personaldetails.tsx Outdated
Comment thread components/favorites/CategoryCard.tsx Outdated
Comment thread components/favorites/DateIdeaCard.tsx
Comment thread components/favorites/DateIdeaCard.tsx
Comment thread components/favorites/TipRow.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (11)
app/(auth)/register/gender.tsx (1)

47-48: Redundant headerShown: false if parent layout already sets it.

The (auth)/_layout.tsx already configures screenOptions={{ headerShown: false }} for all screens under this layout. This Stack.Screen override 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 of StyleSheet.flatten on a plain object.

StyleSheet.flatten is 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 tip is 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: Use Theme type instead of any for type safety.

The makeStyles function parameter loses type safety with any. Import and use the Theme type 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 SkeletonSection component 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: Placeholder alert() 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-picker was 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 unused ideas prop to CategoryGridCard.

ideas={cat.ideas} is passed here, but as noted in CategoryCard.tsx, the CategoryGridCard component 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 typing theme parameter properly.

Same as in CategoryCard.tsx, using any loses type safety. Use the Theme type 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.get at module level won't update on orientation/resize.

width is captured once at module load. If the app supports rotation or runs on tablets with resizable windows, the card sizing will be stale. Consider using useWindowDimensions hook 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 typing theme parameter properly.

Using any for the theme parameter loses type safety. Import and use the Theme type 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: ideas prop declared but unused in CategoryGridCard.

The Props type includes ideas: DateIdea[], but CategoryGridCard (line 20) destructures only label, icon, and onPress. Either remove ideas from 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9ed4870 and 8187e94.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (14)
  • app/(auth)/register/addProfilePicture.tsx
  • app/(auth)/register/gender.tsx
  • app/(protected)/(tabs)/favorites.tsx
  • app/(protected)/(tabs)/settings.tsx
  • app/(protected)/_layout.tsx
  • app/(protected)/favorites/_layout.tsx
  • app/(protected)/favorites/allcategories.tsx
  • app/(protected)/favorites/tipdetail.tsx
  • app/(protected)/settings/interests.tsx
  • app/(protected)/settings/personaldetails.tsx
  • app/_layout.tsx
  • components/favorites/CategoryCard.tsx
  • components/favorites/TipSection.tsx
  • package.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

Comment thread app/_layout.tsx Outdated
Comment thread app/(protected)/_layout.tsx
Comment thread app/(protected)/favorites/_layout.tsx
Comment thread app/(protected)/settings/interests.tsx Outdated
Comment thread components/favorites/CategoryCard.tsx Outdated
@Kush-Srigiri Kush-Srigiri reopened this Apr 3, 2026

@Kush-Srigiri Kush-Srigiri left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

♻️ Duplicate comments (2)
app/(protected)/settings/interests.tsx (1)

32-33: ⚠️ Potential issue | 🟠 Major

Persist and hydrate interests before returning.

selected starts empty and onContinue only calls router.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 | 🟠 Major

Replace 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.text with 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 shared Theme.

any masks theme token mistakes in this screen. Since Theme is already exported from lib/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 styles iconWrap and premiumInner.

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: Type theme parameter with the exported Theme type.

makeStyles(theme: any) loses all safety on a palette you already control. Theme is exported from @/lib/theme/theme and is the literal return type of useTheme().theme, so typing it here would catch stale token references (e.g. the theme.white/theme.planPremium/cardBgDeep fields 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: scrollRef is assigned but never used.

The ref is attached to the horizontal ScrollView on line 153 but is never read (no imperative scrollTo, no tap-to-page-from-dots behavior). Either wire the dot row to call scrollRef.current?.scrollTo({ x: i * cardWidth, animated: true }) on tap to make the dots interactive, or drop the ref/useRef import.

🤖 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: Type makeStyles parameter with Theme.

Same note as DateIdeaCard: import Theme from @/lib/theme/theme and drop the any so theme.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

📥 Commits

Reviewing files that changed from the base of the PR and between 8187e94 and 61cda30.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (17)
  • .claude/settings.local.json
  • .gitignore
  • app/(auth)/register/addProfilePicture.tsx
  • app/(protected)/(tabs)/favorites.tsx
  • app/(protected)/(tabs)/settings.tsx
  • app/(protected)/(tabs)/stats.tsx
  • app/(protected)/_layout.tsx
  • app/(protected)/favorites/tipdetail.tsx
  • app/(protected)/settings/interests.tsx
  • app/(protected)/settings/personaldetails.tsx
  • components/ServerStatusSheet.tsx
  • components/favorites/CategoryCard.tsx
  • components/favorites/DateIdeaCard.tsx
  • components/favorites/TipRow.tsx
  • hooks/usePushNotifications.ts
  • lib/theme/theme.ts
  • package.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

Comment thread app/(protected)/(tabs)/favorites.tsx
Comment thread app/(protected)/(tabs)/stats.tsx Outdated
Comment thread app/(protected)/favorites/tipdetail.tsx Outdated
Comment thread app/(protected)/settings/interests.tsx
Comment thread components/favorites/CategoryCard.tsx Outdated
Comment thread components/favorites/CategoryCard.tsx Outdated
styles.blurOverlay,
{ backgroundColor: theme.background + "CC" },
]}
onPress={() => router.push("../(protected)/subscriptions")}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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 20

Repository: 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 20

Repository: 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 -20

Repository: 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 subscriptions

Repository: 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.tsx lines 79, 87: href="/subscriptions"
  • app/(protected)/favorites/tipdetail.tsx: <Link href="/subscriptions"

Fix these three locations:

  • components/favorites/CategoryCard.tsx line 74
  • app/(protected)/(tabs)/favorites.tsx line 298
  • app/(protected)/(tabs)/stats.tsx line 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.

Suggested change
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.

Comment thread hooks/usePushNotifications.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
app/(protected)/(tabs)/favorites.tsx (1)

148-148: ⚠️ Potential issue | 🟡 Minor

Inactive dot color still hardcoded to "#333".

This was raised previously and remains unresolved: "#333" is nearly invisible against the dark rootBg (#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: Type makeStyles with Theme instead of any.

The Theme type is already exported from lib/theme/theme.ts and consumed by useTheme(). Using any here silently drops autocomplete and would hide typos like theme.matchColour that 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 for IconComp.

The default <Check size={14} color="#3b3a3b" /> is never rendered: when isInactive is true, line 124 gates it out, and every other branch reassigns IconComp. 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 the TIP_CONTENT key type.

Record<string, TipData> allows any string lookup to type-check, which loses compile-time safety when tipdetail.tsx indexes with a search param. Consider a literal union keyed off TIPS[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

📥 Commits

Reviewing files that changed from the base of the PR and between 61cda30 and b0c7c71.

📒 Files selected for processing (5)
  • app/(protected)/(tabs)/favorites.tsx
  • app/(protected)/(tabs)/stats.tsx
  • app/(protected)/favorites/tipdetail.tsx
  • components/favorites/CategoryCard.tsx
  • lib/favorites/tips.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/(protected)/favorites/tipdetail.tsx
  • components/favorites/CategoryCard.tsx

Comment thread app/(protected)/(tabs)/favorites.tsx Outdated
Comment thread app/(protected)/(tabs)/stats.tsx Outdated
Comment thread app/(protected)/(tabs)/stats.tsx

@Jamie-Poeffel Jamie-Poeffel left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needs to be fixed before merge

<BackWrapper>
<Text style={[gs.h1, { marginTop: 35 }]}>{t("title")}</Text>
<>
<Stack.Screen options={{ headerShown: false }} />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Stack.Screen options={{ headerShown: false }} />

style={[styles.card, getCardStyle("male")]}
onPress={() => setSelected("male")}
<>
<Stack.Screen options={{ headerShown: false }} />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Stack.Screen options={{ headerShown: false }} />


return (
<>
<Stack.Screen options={{ headerShown: false }} />

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<Stack.Screen options={{ headerShown: false }} />

Comment thread .gitignore
@Jamie-Poeffel
Jamie-Poeffel self-requested a review April 22, 2026 19:32
@Jamie-Poeffel
Jamie-Poeffel merged commit d94f315 into dev Apr 22, 2026
2 checks passed
@Jamie-Poeffel
Jamie-Poeffel deleted the feature/favorites branch April 22, 2026 19:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

widgetDown widgetUp Analytics NavigateToPlans DatingInfo

3 participants