Develop#2
Conversation
Builds out the home screen to display a user's balance, upcoming subscriptions, and a list of all subscriptions. This release introduces interactive subscription cards with expandable details for a comprehensive overview. New components: - `ListHeading`: Reusable title with a "View All" action. - `SubscriptionCard`: Displays individual subscription details, with expand/collapse functionality. - `UpcomingSubscriptionCard`: Compact view for imminent subscriptions. Also includes new utility functions for date and status formatting, and updates `global.css` with styles for the new components.
📝 WalkthroughWalkthroughThis PR adds a subscriptions dashboard home screen, new subscription card components, shared formatting utilities and data constants, plus font loading with splash-screen gating and a safe-area update for the subscription details screen. ChangesHome Dashboard and Subscription Components
Estimated code review effort: 3 (Moderate) | ~30 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant HomeScreen
participant UpcomingSubscriptionCard
participant SubscriptionCard
participant formatCurrency
User->>HomeScreen: open home tab
HomeScreen->>UpcomingSubscriptionCard: render upcoming list
UpcomingSubscriptionCard->>formatCurrency: format price
HomeScreen->>SubscriptionCard: render subscriptions
User->>SubscriptionCard: tap card
SubscriptionCard->>HomeScreen: update expandedSubscriptionId
HomeScreen->>SubscriptionCard: re-render expanded card
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
app.json (1)
41-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRedundant native font registration.
This
expo-fontplugin config embeds native fonts under family names derived from filenames (e.g.PlusJakartaSans-Bold), separate from theuseFontskeys (sans-bold, etc.) actually used by the app's styles inapp/_layout.tsx/global.css. Since typography relies exclusively on theuseFonts-loaded names, this native registration appears unused. Confirm this is intentional (e.g. for a future native-only usage) or drop it to avoid maintaining two separate font registration mechanisms.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@app.json` around lines 41 - 54, The expo-font plugin in app.json is redundantly registering native fonts that are not used by the app’s typography, since styles in app/_layout.tsx and global.css rely on the names loaded via useFonts instead. Either remove this native font registration from the expo-font config or, if it is meant for future native-only usage, make sure the app actually references those native family names consistently. Use the expo-font plugin block and the useFonts setup in app/_layout.tsx as the places to align.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/_layout.tsx`:
- Around line 2-23: Keep the splash screen from auto-hiding until font loading
is fully resolved in RootLayout. In app/_layout.tsx, add the
SplashScreen.preventAutoHideAsync call at module scope, then update the
RootLayout/useFonts flow so both the loaded and error states are handled before
calling SplashScreen.hideAsync. Make sure the useFonts hook result is checked
for failure and that the component does not get stuck returning null when font
loading fails.
In `@components/SubscriptionCard.tsx`:
- Around line 46-49: The subscription price display is inflating the amount by
multiplying it by 50 before formatting. Update the rendering in SubscriptionCard
so the amount passed to formatCurrency is the actual price value, unless there
is a documented smaller-unit conversion elsewhere in the component or its props.
Check the price display block and any related pricing calculation to keep the
displayed subscription cost consistent.
In `@components/UpcomingSubscriptionCard.tsx`:
- Around line 5-16: The UpcomingSubscriptionCard price rendering is using a
hard-coded multiplier instead of the subscription’s actual currency. Update
UpcomingSubscriptionCard so the displayed amount uses the existing currency prop
from UpcomingSubscriptionCardProps and pass that through to formatCurrency,
removing the fixed price * 50 conversion. Check the UpcomingSubscriptionCard
component and its formatCurrency call to ensure the value and currency stay
aligned for all subscriptions.
In `@lib/utils/currency.ts`:
- Around line 13-15: The fallback in the currency formatting logic always
hardcodes the peso symbol, so unsupported currencies are mislabeled. Update the
`formatCurrency` fallback in `currency.ts` to use the requested currency
code/symbol from the function input instead of always returning `₱`, and keep
the existing `Intl.NumberFormat` path unchanged for supported currencies.
---
Nitpick comments:
In `@app.json`:
- Around line 41-54: The expo-font plugin in app.json is redundantly registering
native fonts that are not used by the app’s typography, since styles in
app/_layout.tsx and global.css rely on the names loaded via useFonts instead.
Either remove this native font registration from the expo-font config or, if it
is meant for future native-only usage, make sure the app actually references
those native family names consistently. Use the expo-font plugin block and the
useFonts setup in app/_layout.tsx as the places to align.
🪄 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 Plus
Run ID: 8cbd17b8-67f9-45d2-b4df-d51d50decdb6
⛔ Files ignored due to path filters (2)
assets/images/avatar.pngis excluded by!**/*.pngpackage-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (15)
app.jsonapp/(tabs)/index.tsxapp/(tabs)/subscriptions/[id].tsxapp/_layout.tsxcomponents/ListHeading.tsxcomponents/SubscriptionCard.tsxcomponents/UpcomingSubscriptionCard.tsxconstants/data.tsconstants/images.tsglobal.csslib/utils/currency.tslib/utils/date.tslib/utils/status.tspackage.jsontype.d.ts
| } catch { | ||
| return `₱${value.toFixed(2)}`; | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Fallback ignores the requested currency.
If Intl.NumberFormat throws (e.g., invalid/unsupported currency code), the catch block always renders ₱, even for non-PHP currencies like USD — silently mislabeling the amount's currency.
💡 Proposed fix
} catch {
- return `₱${value.toFixed(2)}`;
+ const symbol = currency === "PHP" ? "₱" : `${currency} `;
+ return `${symbol}${value.toFixed(2)}`;
}📝 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.
| } catch { | |
| return `₱${value.toFixed(2)}`; | |
| } | |
| } catch { | |
| const symbol = currency === "PHP" ? "₱" : `${currency} `; | |
| return `${symbol}${value.toFixed(2)}`; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@lib/utils/currency.ts` around lines 13 - 15, The fallback in the currency
formatting logic always hardcodes the peso symbol, so unsupported currencies are
mislabeled. Update the `formatCurrency` fallback in `currency.ts` to use the
requested currency code/symbol from the function input instead of always
returning `₱`, and keep the existing `Intl.NumberFormat` path unchanged for
supported currencies.
There was a problem hiding this comment.
Pull request overview
Adds the new subscriptions-focused home/dashboard UI (upcoming + all subscriptions), along with supporting utilities (date/status/currency formatting), shared type definitions, and custom font loading/splash handling to polish the app experience.
Changes:
- Introduces reusable subscription UI components (subscription cards, upcoming cards, list heading) and wires them into the home tab.
- Adds formatting utilities and the
dayjsdependency to standardize date/status/currency display. - Adds custom font loading via
expo-fontand updates styling/theme assets.
Reviewed changes
Copilot reviewed 14 out of 17 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| type.d.ts | Adds global app types for tabs, subscriptions, and component props. |
| package.json | Adds dayjs dependency. |
| package-lock.json | Locks dayjs dependency. |
| lib/utils/status.ts | Adds status label formatter. |
| lib/utils/date.ts | Adds subscription date formatter using dayjs. |
| lib/utils/currency.ts | Adds currency formatting helper. |
| global.css | Re-indents/refines theme + component class definitions and sizing. |
| constants/images.ts | Centralizes image imports/exports. |
| constants/data.ts | Adds mock home/subscription data and types the tabs array. |
| components/UpcomingSubscriptionCard.tsx | New upcoming subscription card UI. |
| components/SubscriptionCard.tsx | New expandable subscription card UI. |
| components/ListHeading.tsx | New reusable list header with optional “View All”. |
| app/(tabs)/subscriptions/[id].tsx | Updates subscription details screen to use safe area. |
| app/(tabs)/index.tsx | Replaces placeholder home screen with the new dashboard layout and lists. |
| app/_layout.tsx | Adds font loading + splash screen gating for a polished startup. |
| app.json | Configures expo-font plugin with bundled fonts. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…xchange - Rewrite formatCurrency to accept a source currency and convert to PHP using real-time exchange rates via Frankfurter API with static fallback - Expose initCurrencyRates() for pre-fetching rates on app startup - Remove hardcoded 50x multiplier from SubscriptionCard - Wire currency prop into UpcomingSubscriptionCard so prices convert correctly instead of defaulting to PHP
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
lib/utils/currency.ts (1)
17-21: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winHarden the remote rate fetch.
fetchRateshas nores.okcheck and no timeout. A non-2xx response (e.g., 5xx) will parse into a body without.rates, silently cachingundefined, and a hung connection will keep the promise pending indefinitely. Add a status check and an abort-based timeout soinitCurrencyRatesreliably falls back toSTATIC_RATES.♻️ Proposed hardening
-async function fetchRates(): Promise<Record<string, number>> { - const res = await fetch(`${API_URL}?from=PHP`); - const data = await res.json(); - return data.rates as Record<string, number>; -} +async function fetchRates(): Promise<Record<string, number>> { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 5000); + try { + const res = await fetch(`${API_URL}?from=PHP`, { signal: controller.signal }); + if (!res.ok) { + throw new Error(`Frankfurter request failed: ${res.status}`); + } + const data = await res.json(); + return data.rates as Record<string, number>; + } finally { + clearTimeout(timeout); + } +}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/utils/currency.ts` around lines 17 - 21, Harden fetchRates by checking res.ok before parsing and by adding an AbortController-based timeout to the remote request; if the response is non-2xx, times out, or the payload lacks rates, make fetchRates fail so initCurrencyRates can fall back to STATIC_RATES instead of caching an undefined result. Use the existing fetchRates and initCurrencyRates flow to keep the fallback behavior reliable.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@components/UpcomingSubscriptionCard.tsx`:
- Line 19: The pluralization in UpcomingSubscriptionCard is incorrect for a
zero-day renewal because the current daysLeft check falls back to the singular
form for 0. Update the rendering logic around daysLeft so it uses the singular
label only when daysLeft is exactly 1, and uses the plural label for 0 and all
other values.
In `@lib/utils/currency.ts`:
- Around line 32-38: The getRate function in currency.ts currently falls back to
STATIC_RATES when the cache is stale, but it never triggers a refresh path, so
live rates stop updating. Update getRate to detect stale cache and kick off a
non-blocking refresh by reusing initCurrencyRates while still returning the
current cached or static value immediately. Keep the refresh logic isolated so
the existing cachedRates and lastFetched behavior remains intact, and ensure
subsequent calls pick up the updated rates once the background refresh
completes.
---
Nitpick comments:
In `@lib/utils/currency.ts`:
- Around line 17-21: Harden fetchRates by checking res.ok before parsing and by
adding an AbortController-based timeout to the remote request; if the response
is non-2xx, times out, or the payload lacks rates, make fetchRates fail so
initCurrencyRates can fall back to STATIC_RATES instead of caching an undefined
result. Use the existing fetchRates and initCurrencyRates flow to keep the
fallback behavior reliable.
🪄 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 Plus
Run ID: 6a229841-c4c8-4dbf-a1ea-3db8faaf7237
📒 Files selected for processing (3)
components/SubscriptionCard.tsxcomponents/UpcomingSubscriptionCard.tsxlib/utils/currency.ts
Summary by CodeRabbit