Skip to content

feat: housing creation flow#319

Merged
aahiltn merged 1 commit intomainfrom
housing-creation-flow
Apr 16, 2026
Merged

feat: housing creation flow#319
aahiltn merged 1 commit intomainfrom
housing-creation-flow

Conversation

@afnantuffaha
Copy link
Copy Markdown
Contributor

@afnantuffaha afnantuffaha commented Apr 16, 2026

Description

This PR implements the housing creation flow using the abstracted activity entry sheet, manual sheet, and activity card. This supports both autofill and manual housing creation.

How has this been tested?

Checklist

  • I have self-reviewed my code for readability, maintainability, performance, and added comments/documentation where necessary.
  • New and existing tests pass locally with my changes.
  • I have followed the project's coding standards and best practices.
  • New "Housing" tab in trip details with dedicated listing, sorting, pagination, and comments.
  • Housing creation supports two flows: autofill (URL parsing) and manual entry (price picker, date range, location selection).
  • Housing activities are separated from general activities (filtered out) and displayed via a new HousingCard with estimated price and location info.
  • Entry UX: an entry sheet wraps URL parsing and funnels parsed data into a manual sheet for review before creation.

Features

  • Housing creation flow (autofill + manual) with URL parsing, prefill, and create-mutation.
  • HousingTabContent: list, infinite scroll, newest/oldest sorting, empty state, comment integration.
  • AddHousingEntrySheet and AddHousingManualSheet components with imperative handles.
  • HousingCard component for housing activity display.

Improvements

  • Activities list hook supports category-based filtering (query key includes optional category).
  • Activities tab excludes housing items at display time.
  • Autofill button visual states clarified; entry sheet now has an explicit close affordance.
  • Edit link BottomSheet snap point increased for improved UX.

Infra

  • New navigation: trips/[id]/housing/ stack with index, [id], and creation routes; auth gate in layout.
  • Housing creation payload hardcodes category_names: ["housing"] for correct categorization.

Sequence (flow)

User -> Housing Tab -> Add button -> AddHousingEntrySheet
AddHousingEntrySheet -> parseActivityLink -> (autofill success) -> open AddHousingManualSheet (prefilled)
AddHousingManualSheet -> user edits -> useCreateActivity.mutateAsync -> API create -> HousingTabContent prepends new item

Author contribution

File Added Removed
frontend/api/activities/custom/useActivitiesList.ts 20 10
frontend/app/(app)/trips/[id]/_layout.tsx 9 0
frontend/app/(app)/trips/[id]/activities/[id]/index.tsx 1 1
frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx 8 5
frontend/app/(app)/trips/[id]/housing/_layout.tsx 53 0
frontend/app/(app)/trips/[id]/housing/components/add-housing-entry-sheet.tsx 37 0
frontend/app/(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx 328 0
frontend/app/(app)/trips/[id]/housing/components/housing-card.tsx 38 0
frontend/app/(app)/trips/[id]/housing/components/housing-tab-content.tsx 293 0
frontend/app/(app)/trips/[id]/index.tsx 7 4
frontend/app/(app)/trips/[id]/components/add-item-entry-sheet.tsx 20 3
Total 814 23

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 16, 2026

Warning

Rate limit exceeded

@afnantuffaha has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 25 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 17 minutes and 25 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e61920c4-33da-4580-a585-8aae35db506a

📥 Commits

Reviewing files that changed from the base of the PR and between 43b94cd and 7bd76fc.

⛔ Files ignored due to path filters (1)
  • frontend/assets/images/house.png is excluded by !**/*.png
📒 Files selected for processing (11)
  • frontend/api/activities/custom/useActivitiesList.ts
  • frontend/app/(app)/trips/[id]/_layout.tsx
  • frontend/app/(app)/trips/[id]/activities/[id]/index.tsx
  • frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx
  • frontend/app/(app)/trips/[id]/components/add-item-entry-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/_layout.tsx
  • frontend/app/(app)/trips/[id]/housing/components/add-housing-entry-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/components/housing-card.tsx
  • frontend/app/(app)/trips/[id]/housing/components/housing-tab-content.tsx
  • frontend/app/(app)/trips/[id]/index.tsx
📝 Walkthrough

Walkthrough

Adds housing as a new activity category: extends the activities hook to accept an optional category, filters housing out of the main activities list, and introduces housing routes and UI (entry sheet, manual form, card, tab content) with navigation and authentication handling.

Changes

Cohort / File(s) Summary
Activities hook
frontend/api/activities/custom/useActivitiesList.ts
Hook now accepts options?: UseActivitiesListOptions with category?: string; activitiesQueryKey includes category; useInfiniteQuery key/fn and cache updates include category; returned shape removes refetch.
Activities UI tweaks
frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx, frontend/app/(app)/trips/[id]/activities/[id]/index.tsx
Filters out activities with category_names containing "housing" for sorting; background color tokens changed from gray25gray50; bottom sheet snap point adjusted 230→300.
Trips layout
frontend/app/(app)/trips/[id]/_layout.tsx
Adds a housing child route to the trips layout with header/gesture config.
Housing stack layout
frontend/app/(app)/trips/[id]/housing/_layout.tsx
New default-exported Layout enforcing auth redirect and defining a Stack with screens: index, [id], creation and shared header options.
Housing components
frontend/app/(app)/trips/[id]/housing/components/add-housing-entry-sheet.tsx, .../add-housing-manual-sheet.tsx, .../housing-card.tsx, .../housing-tab-content.tsx
Added AddHousingEntrySheet (link entry wrapper), AddHousingManualSheet (manual form with price/date/location and create flow), HousingCard (rendering), and HousingTabContent (list, sorting, comments, sheet control, imperative handle).
Trip index integration
frontend/app/(app)/trips/[id]/index.tsx
Imports and renders HousingTabContent when activeTab === "housing" and updates empty-state gating.
Shared entry sheet UI
frontend/app/(app)/trips/[id]/components/add-item-entry-sheet.tsx
Adjusted autofill button loading/disabled style precedence and added a top-right close Pressable with styles.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as HousingTabContent
    participant Entry as AddHousingEntrySheet
    participant Manual as AddHousingManualSheet
    participant API as Activity API
    participant Store as QueryClient/List

    User->>UI: Open housing tab
    UI->>API: Fetch housing activities (category="housing")
    API-->>UI: Return list
    UI->>Store: Render list

    User->>UI: Tap "Add a housing option"
    UI->>Entry: Open entry sheet

    User->>Entry: Paste link
    Entry->>API: parseActivityLink(tripID, url)
    API-->>Entry: Parsed data
    Entry->>Manual: Open manual sheet with prefill

    User->>Manual: Fill form (price, dates, location) and save
    Manual->>API: createActivity(tripID, payload with category_names:["housing"])
    API-->>Manual: Created activity
    Manual->>UI: onSaved callback (new activity)
    UI->>Store: Prepend activity to list / update query cache
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • aahiltn
  • in-mai-space

Poem

A new tab hosts rooms to find,
Links parsed, forms saved, and lists aligned.
Sheets open, create calls return,
Housing entries live and learn,
Trips gain places for the road ahead.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective: implementing a housing creation flow with new components, screens, and integration into the activities system.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ 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 housing-creation-flow

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx (1)

236-239: ⚠️ Potential issue | 🟡 Minor

Count displays total activities, not filtered count.

The header shows activities.length but the list renders sortedActivities which excludes housing. If any housing items exist, users will see a higher count than the actual number of visible items.

Proposed fix
             <Text variant="bodyDefault" color="gray500">
-              {activities.length}{" "}
-              {activities.length === 1 ? "option" : "options"} added
+              {sortedActivities.length}{" "}
+              {sortedActivities.length === 1 ? "option" : "options"} added
             </Text>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/activities/components/activities-tab-content.tsx
around lines 236 - 239, The header currently shows the total activities count
using activities.length while the rendered list uses sortedActivities (which
excludes housing), causing a mismatch; update the displayed count to reflect the
visible/filtered items by using sortedActivities.length (or compute a
visibleCount variable derived from sortedActivities) in the Text component,
ensuring the pluralization logic (activities.length === 1 ? "option" :
"options") also uses that same visible count.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/app/`(app)/trips/[id]/activities/components/activities-tab-content.tsx:
- Around line 116-122: Indentation for the useMemo block is inconsistent; adjust
the formatting of the sortedActivities useMemo so its body and return lines
follow the same indentation style as the rest of the file (match surrounding
2-space or 4-space convention). Locate the sortedActivities constant and the
useMemo callback (references: sortedActivities, useMemo, nonHousing, activities,
sortOrder) and reformat the callback opening, inner lines (filter, if, return)
and closing brace to use the file's standard indentation level so the block
visually aligns with neighboring code.

In `@frontend/app/`(app)/trips/[id]/housing/_layout.tsx:
- Around line 22-39: The Stack.Screen entries for the "index" and "[id]" routes
include redundant options (headerTitle and headerTransparent) that have no
effect when headerShown is false; edit the options objects for the Stack.Screen
components named "index" and "[id]" to remove headerTitle and headerTransparent,
leaving headerShown: false and gestureEnabled as-is so the screen configurations
are minimal and correct.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx:
- Around line 298-327: The styles object contains hard-coded spacing and
typography numbers; update the StyleSheet (symbols: styles, formRows, formRow,
formRowInput, formRowInputEmpty, formRowInputFilled, formRowPlaceholder,
formRowValue) to use centralized design-system tokens instead of literals (e.g.,
replace 16, 8, 20, 0 and any fontFamily/fontSize values with your design
system's spacing and typography tokens like spacing.* and typography.* or
FontSizes/LineHeights constants), import those token constants and apply them in
each style entry so spacing, fontSize, lineHeight and padding use the shared
tokens rather than magic numbers.
- Around line 115-117: The catch block that currently only calls
setLocationName(prediction.description ?? null) leaves stale coordinates if a
prior selection set locationLat/locationLng; update the catch to also clear
those coordinates by calling setLocationLat(null) and setLocationLng(null)
alongside setLocationName so lat/lng cannot be submitted for a failed
place-details lookup (locate the catch in add-housing-manual-sheet.tsx where
setLocationName is called).
- Around line 138-139: The code currently formats calendar dates using
dateRange.start.toISOString().split("T")[0] and
dateRange.end.toISOString().split("T")[0], which converts to UTC and can shift
the local calendar day; update the serialization to build YYYY-MM-DD from the
local date parts instead (use dateRange.start.getFullYear(), getMonth()+1,
getDate() and similarly for dateRange.end), zero-pad month/day to two digits or
add a small helper like formatLocalDate(Date) and use that for the start and end
fields so the API receives the local calendar date.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-card.tsx:
- Around line 26-27: The thumbnailUrl and proposedBy props are mapped to
incorrect fields on the housing object; update the JSX where
thumbnailUrl={housing.thumbnail_url ?? undefined} and
proposedBy={housing.proposed_by ?? undefined} to use housing.media_url for
thumbnailUrl and housing.proposer_name for proposedBy (preserving the ??
undefined fallback) so the card shows the correct media and display name.
- Line 33: housing.comment_previews is typed as ModelsCommenterPreview[] (which
lacks created_at) but EntityCard expects CommentPreview[] and reads
commentPreviews[0]?.created_at; fix by aligning types or transforming the data
before passing. Two options: 1) update
ModelsActivityAPIResponse.comment_previews (and ModelsCommenterPreview) to
include created_at where the API actually provides it; or 2) map
housing.comment_previews to a CommentPreview shape before passing to EntityCard
(e.g., copy fields and add created_at: preview.created_at ?? undefined or a
parsed timestamp) so EntityCard receives CommentPreview[]; reference symbols:
housing.comment_previews, ModelsCommenterPreview,
ModelsActivityAPIResponse.comment_previews, CommentPreview, EntityCard,
formatCommentTimeLabel.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-tab-content.tsx:
- Line 79: The variable toast returned from useToast is declared but never used;
remove the unused call and related import: delete the line "const toast =
useToast();" in the HousingTabContent component (and remove the useToast import
if it exists at the top of the file) so no unused variable or import remains.

---

Outside diff comments:
In
`@frontend/app/`(app)/trips/[id]/activities/components/activities-tab-content.tsx:
- Around line 236-239: The header currently shows the total activities count
using activities.length while the rendered list uses sortedActivities (which
excludes housing), causing a mismatch; update the displayed count to reflect the
visible/filtered items by using sortedActivities.length (or compute a
visibleCount variable derived from sortedActivities) in the Text component,
ensuring the pluralization logic (activities.length === 1 ? "option" :
"options") also uses that same visible count.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fe83eefa-0987-4f91-8935-3e0c82237c20

📥 Commits

Reviewing files that changed from the base of the PR and between 6f1ed67 and f98c211.

⛔ Files ignored due to path filters (1)
  • frontend/assets/images/house.png is excluded by !**/*.png
📒 Files selected for processing (10)
  • frontend/api/activities/custom/useActivitiesList.ts
  • frontend/app/(app)/trips/[id]/_layout.tsx
  • frontend/app/(app)/trips/[id]/activities/[id]/index.tsx
  • frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx
  • frontend/app/(app)/trips/[id]/housing/_layout.tsx
  • frontend/app/(app)/trips/[id]/housing/components/add-housing-entry-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/components/housing-card.tsx
  • frontend/app/(app)/trips/[id]/housing/components/housing-tab-content.tsx
  • frontend/app/(app)/trips/[id]/index.tsx

Comment thread frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx Outdated
Comment on lines +22 to +39
<Stack.Screen
name="index"
options={{
headerShown: false,
headerTitle: "",
headerTransparent: true,
gestureEnabled: false,
}}
/>
<Stack.Screen
name="[id]"
options={{
headerShown: false,
headerTitle: "",
headerTransparent: true,
gestureEnabled: false,
}}
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Redundant options when headerShown: false.

For the index and [id] screens, headerTitle and headerTransparent are set but have no effect when headerShown: false. This is not a bug, just unnecessary configuration.

Optional cleanup
       <Stack.Screen
         name="index"
         options={{
           headerShown: false,
-          headerTitle: "",
-          headerTransparent: true,
           gestureEnabled: false,
         }}
       />
       <Stack.Screen
         name="[id]"
         options={{
           headerShown: false,
-          headerTitle: "",
-          headerTransparent: true,
           gestureEnabled: false,
         }}
       />
📝 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
<Stack.Screen
name="index"
options={{
headerShown: false,
headerTitle: "",
headerTransparent: true,
gestureEnabled: false,
}}
/>
<Stack.Screen
name="[id]"
options={{
headerShown: false,
headerTitle: "",
headerTransparent: true,
gestureEnabled: false,
}}
/>
<Stack.Screen
name="index"
options={{
headerShown: false,
gestureEnabled: false,
}}
/>
<Stack.Screen
name="[id]"
options={{
headerShown: false,
gestureEnabled: false,
}}
/>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/_layout.tsx around lines 22 - 39, The
Stack.Screen entries for the "index" and "[id]" routes include redundant options
(headerTitle and headerTransparent) that have no effect when headerShown is
false; edit the options objects for the Stack.Screen components named "index"
and "[id]" to remove headerTitle and headerTransparent, leaving headerShown:
false and gestureEnabled as-is so the screen configurations are minimal and
correct.

Comment on lines +115 to +117
} catch {
setLocationName(prediction.description ?? null);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Clear stale coordinates when place-details lookup fails

On Line 115-117, fallback only updates locationName. If a previous selection set locationLat/locationLng, those stale coordinates remain and can be submitted with a different name.

Proposed fix
       } catch {
         setLocationName(prediction.description ?? null);
+        setLocationLat(null);
+        setLocationLng(null);
       }
📝 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
} catch {
setLocationName(prediction.description ?? null);
}
} catch {
setLocationName(prediction.description ?? null);
setLocationLat(null);
setLocationLng(null);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
around lines 115 - 117, The catch block that currently only calls
setLocationName(prediction.description ?? null) leaves stale coordinates if a
prior selection set locationLat/locationLng; update the catch to also clear
those coordinates by calling setLocationLat(null) and setLocationLng(null)
alongside setLocationName so lat/lng cannot be submitted for a failed
place-details lookup (locate the catch in add-housing-manual-sheet.tsx where
setLocationName is called).

Comment on lines +138 to +139
start: dateRange.start.toISOString().split("T")[0]!,
end: dateRange.end.toISOString().split("T")[0]!,
Copy link
Copy Markdown
Contributor

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:

# Find and examine the file
find . -type f -name "add-housing-manual-sheet.tsx" | head -5

Repository: GenerateNU/toggo

Length of output: 139


🏁 Script executed:

# Verify the JavaScript Date.toISOString() behavior with a simple test
node << 'EOF'
// Test the toISOString behavior
const testDate = new Date("2024-01-15T00:00:00");
console.log("Test date object:", testDate);
console.log("toISOString():", testDate.toISOString());
console.log("split result:", testDate.toISOString().split("T")[0]);
console.log("getFullYear():", testDate.getFullYear());
console.log("getMonth():", testDate.getMonth() + 1);
console.log("getDate():", testDate.getDate());

// Test with timezone-aware scenario
const d = new Date();
console.log("\nCurrent date object:", d);
console.log("toISOString() result:", d.toISOString());
console.log("Local date methods - Y/M/D:", d.getFullYear(), d.getMonth() + 1, d.getDate());
EOF

Repository: GenerateNU/toggo

Length of output: 347


🏁 Script executed:

# Read the file around lines 138-139 to confirm the code
sed -n '130,150p' ./frontend/app/\(app\)/trips/\[id\]/housing/components/add-housing-manual-sheet.tsx

Repository: GenerateNU/toggo

Length of output: 630


🏁 Script executed:

# Let's examine more context around the dateRange to understand how it's being used
sed -n '100,160p' ./frontend/app/\(app\)/trips/\[id\]/housing/components/add-housing-manual-sheet.tsx

Repository: GenerateNU/toggo

Length of output: 1837


🏁 Script executed:

# Check the Date type and where dateRange comes from
grep -n "dateRange" ./frontend/app/\(app\)/trips/\[id\]/housing/components/add-housing-manual-sheet.tsx | head -20

Repository: GenerateNU/toggo

Length of output: 421


🏁 Script executed:

# Check the DateRange type definition
rg "type DateRange|interface DateRange" --type ts --type tsx -A 5

Repository: GenerateNU/toggo

Length of output: 87


🏁 Script executed:

# Look at the top of the file to see imports and type definitions
head -70 ./frontend/app/\(app\)/trips/\[id\]/housing/components/add-housing-manual-sheet.tsx

Repository: GenerateNU/toggo

Length of output: 2585


🏁 Script executed:

# Check the types to understand what dates format is expected by the API
rg "dates" ./frontend/app/\(app\)/trips/\[id\]/housing/components/add-housing-manual-sheet.tsx -B 2 -A 2 | grep -A 5 -B 5 "dates"

Repository: GenerateNU/toggo

Length of output: 524


🏁 Script executed:

# Check the API types to see what format dates should be in
find . -type f -name "*.gen.ts" -o -name "types.ts" | xargs grep -l "ActivityAPI\|ParsedActivityData" | head -3

Repository: GenerateNU/toggo

Length of output: 190


🏁 Script executed:

# Check the schema to understand the dates field format
rg "dates" ./frontend/types/schema.gen.ts -B 3 -A 3 | head -40

Repository: GenerateNU/toggo

Length of output: 926


🏁 Script executed:

# Look at the activity-related types
rg "Activity.*API\|ParsedActivity" ./frontend/types/schema.gen.ts -A 10 | head -60

Repository: GenerateNU/toggo

Length of output: 42


🏁 Script executed:

# Find the modelsDateRangeSchema definition
rg "modelsDateRangeSchema" ./frontend/types/schema.gen.ts -B 2 -A 5 | head -20

Repository: GenerateNU/toggo

Length of output: 735


🏁 Script executed:

# Search for DateRange interface/type definition
rg "DateRange" ./frontend/design-system -B 2 -A 5 | head -40

Repository: GenerateNU/toggo

Length of output: 3018


🏁 Script executed:

# Let's verify the timezone issue more thoroughly with a practical example
node << 'EOF'
// Simulate the timezone issue
const testCases = [
  { tz: "UTC+8", offset: 8 },
  { tz: "UTC-5", offset: -5 },
  { tz: "UTC+0", offset: 0 }
];

// Create a date representing midnight on Jan 15
const baseDate = new Date(2024, 0, 15, 0, 0, 0, 0);

console.log("Original date object (Jan 15 midnight):");
console.log("toISOString():", baseDate.toISOString());
console.log("split result:", baseDate.toISOString().split("T")[0]);
console.log("Using local methods - getFullYear/Month/Date:", 
  baseDate.getFullYear(), 
  (baseDate.getMonth() + 1).toString().padStart(2, '0'), 
  baseDate.getDate().toString().padStart(2, '0'));

console.log("\n--- The Issue ---");
console.log("In UTC+8 timezone, Jan 15 midnight local is Jan 14 at 4 PM UTC");
console.log("In UTC-5 timezone, Jan 15 midnight local is Jan 15 at 5 AM UTC");
console.log("\nToISO always returns UTC. If in UTC+X (east), previous day in UTC.");
console.log("The proposed fix correctly uses getDate() which gives local date.\n");

// Verify the proposed fix format
const toLocalISODate = (d) => {
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
};

console.log("Proposed fix result:", toLocalISODate(baseDate));
EOF

Repository: GenerateNU/toggo

Length of output: 533


🏁 Script executed:

# Search for other uses of toISOString() in the codebase that might have the same issue
rg "toISOString\(\)" ./frontend --type ts --type jsx -B 2 -A 2 | head -80

Repository: GenerateNU/toggo

Length of output: 87


🏁 Script executed:

# Check if there are other timezone-related date issues in the codebase
rg "toISOString" ./frontend -l | head -20

Repository: GenerateNU/toggo

Length of output: 766


🏁 Script executed:

# Check if other files use toISOString().split("T")[0] pattern
rg 'toISOString\(\)\.split\("T"\)\[0\]' ./frontend

Repository: GenerateNU/toggo

Length of output: 901


🏁 Script executed:

# Look at the edit-dates file to see if it has the same pattern
rg "toISOString" ./frontend/app/\(app\)/trips/\[id\]/settings/edit-dates.tsx -B 3 -A 3

Repository: GenerateNU/toggo

Length of output: 552


Use local date methods instead of toISOString() for calendar dates

Lines 138-139 extract calendar dates using toISOString().split("T")[0], which converts the local Date to UTC first. This causes the saved date to shift by one day in some timezones (e.g., UTC+8 would save Jan 14 instead of Jan 15). The API expects the local calendar date in YYYY-MM-DD format. Use getFullYear(), getMonth(), and getDate() to extract the local date instead.

Proposed fix
+      const toLocalISODate = (d: Date) => {
+        const y = d.getFullYear();
+        const m = String(d.getMonth() + 1).padStart(2, "0");
+        const day = String(d.getDate()).padStart(2, "0");
+        return `${y}-${m}-${day}`;
+      };
+
       const dates =
         dateRange.start && dateRange.end
           ? [
               {
-                start: dateRange.start.toISOString().split("T")[0]!,
-                end: dateRange.end.toISOString().split("T")[0]!,
+                start: toLocalISODate(dateRange.start),
+                end: toLocalISODate(dateRange.end),
               },
             ]
           : undefined;
📝 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
start: dateRange.start.toISOString().split("T")[0]!,
end: dateRange.end.toISOString().split("T")[0]!,
const toLocalISODate = (d: Date) => {
const y = d.getFullYear();
const m = String(d.getMonth() + 1).padStart(2, "0");
const day = String(d.getDate()).padStart(2, "0");
return `${y}-${m}-${day}`;
};
const dates =
dateRange.start && dateRange.end
? [
{
start: toLocalISODate(dateRange.start),
end: toLocalISODate(dateRange.end),
},
]
: undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
around lines 138 - 139, The code currently formats calendar dates using
dateRange.start.toISOString().split("T")[0] and
dateRange.end.toISOString().split("T")[0], which converts to UTC and can shift
the local calendar day; update the serialization to build YYYY-MM-DD from the
local date parts instead (use dateRange.start.getFullYear(), getMonth()+1,
getDate() and similarly for dateRange.end), zero-pad month/day to two digits or
add a small helper like formatLocalDate(Date) and use that for the start and end
fields so the API receives the local calendar date.

Comment on lines +298 to +327
const styles = StyleSheet.create({
formRows: {
gap: 16,
},
formRow: {
flexDirection: "row",
alignItems: "center",
gap: 8,
},
formRowPlaceholder: {
color: ColorPalette.blue500,
flex: 1,
},
formRowValue: {
color: ColorPalette.gray700,
flex: 1,
},
formRowInput: {
flex: 1,
fontFamily: FontFamily.semiBold,
fontSize: 16,
lineHeight: 20,
paddingVertical: 0,
},
formRowInputEmpty: {
color: ColorPalette.blue500,
},
formRowInputFilled: {
color: ColorPalette.gray700,
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Replace style magic numbers with design-system tokens

Line 298-327 hard-codes spacing and typography numbers (16, 8, 20, 0). Move these to centralized design-system tokens to keep consistency and avoid drift.

As per coding guidelines, React/Expo UI must use a centralized design system; avoid hard-coded color values, magic spacing numbers, and duplicated style definitions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
around lines 298 - 327, The styles object contains hard-coded spacing and
typography numbers; update the StyleSheet (symbols: styles, formRows, formRow,
formRowInput, formRowInputEmpty, formRowInputFilled, formRowPlaceholder,
formRowValue) to use centralized design-system tokens instead of literals (e.g.,
replace 16, 8, 20, 0 and any fontFamily/fontSize values with your design
system's spacing and typography tokens like spacing.* and typography.* or
FontSizes/LineHeights constants), import those token constants and apply them in
each style entry so spacing, fontSize, lineHeight and padding use the shared
tokens rather than magic numbers.

Comment on lines +26 to +27
thumbnailUrl={housing.thumbnail_url ?? undefined}
proposedBy={housing.proposed_by ?? undefined}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Incorrect field mappings for thumbnailUrl and proposedBy.

ModelsActivityAPIResponse includes fields like media_url, proposed_by, proposer_name, and proposer_picture_url. The type does not define a thumbnail_url field. Additionally, proposed_by is the user ID, not the display name.

  • thumbnailUrl should use housing.media_url
  • proposedBy should use housing.proposer_name
Proposed fix
-      thumbnailUrl={housing.thumbnail_url ?? undefined}
-      proposedBy={housing.proposed_by ?? undefined}
+      thumbnailUrl={housing.media_url ?? undefined}
+      proposedBy={housing.proposer_name ?? undefined}
📝 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
thumbnailUrl={housing.thumbnail_url ?? undefined}
proposedBy={housing.proposed_by ?? undefined}
thumbnailUrl={housing.media_url ?? undefined}
proposedBy={housing.proposer_name ?? undefined}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-card.tsx around
lines 26 - 27, The thumbnailUrl and proposedBy props are mapped to incorrect
fields on the housing object; update the JSX where
thumbnailUrl={housing.thumbnail_url ?? undefined} and
proposedBy={housing.proposed_by ?? undefined} to use housing.media_url for
thumbnailUrl and housing.proposer_name for proposedBy (preserving the ??
undefined fallback) so the card shows the correct media and display name.

priceLabel={priceLabel}
actionButton={null}
commentCount={housing.comment_count ?? 0}
commentPreviews={housing.comment_previews ?? []}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if EntityCard handles missing created_at gracefully
rg -nA5 'formatCommentTimeLabel' frontend/app/\(app\)/trips/\[id\]/components/entity-card.tsx

Repository: GenerateNU/toggo

Length of output: 453


🏁 Script executed:

# Find the definition of ModelsCommenterPreview or CommentPreview
rg -n 'ModelsCommenterPreview|interface CommentPreview|type CommentPreview' --type ts --type tsx

Repository: GenerateNU/toggo

Length of output: 87


🏁 Script executed:

# Check the housing-card.tsx file around line 33 to see the actual prop
cat -n frontend/app/\(app\)/trips/\[id\]/housing/components/housing-card.tsx | head -50

Repository: GenerateNU/toggo

Length of output: 1451


🏁 Script executed:

# Check the EntityCard component's prop types
rg -nB5 -A15 'interface.*Props|type.*Props' frontend/app/\(app\)/trips/\[id\]/components/entity-card.tsx | head -50

Repository: GenerateNU/toggo

Length of output: 641


🏁 Script executed:

# Find ModelsActivityAPIResponse definition
rg -n 'ModelsActivityAPIResponse' --type ts | grep -i 'interface\|type'

Repository: GenerateNU/toggo

Length of output: 2569


🏁 Script executed:

# Look for the types.gen file
fd 'types.gen' -t f

Repository: GenerateNU/toggo

Length of output: 87


🏁 Script executed:

# Check if there's a ModelsCommenterPreview type
rg -n 'ModelsCommenterPreview' --type ts

Repository: GenerateNU/toggo

Length of output: 705


🏁 Script executed:

# Check ModelsCommenterPreview definition in types.gen.ts
sed -n '101,120p' frontend/types/types.gen.ts

Repository: GenerateNU/toggo

Length of output: 408


🏁 Script executed:

# Also verify the CommentPreview type definition in entity-card.tsx
sed -n '10,20p' frontend/app/\(app\)/trips/\[id\]/components/entity-card.tsx

Repository: GenerateNU/toggo

Length of output: 318


Type mismatch: housing.comment_previews is ModelsCommenterPreview[] but EntityCard expects CommentPreview[].

ModelsCommenterPreview does not include the created_at field, while EntityCard attempts to access commentPreviews[0]?.created_at. The code uses a type assertion to work around this mismatch, and formatCommentTimeLabel gracefully returns an empty string for missing timestamps, so it won't crash—but comment timestamps will not display.

Align the types by either updating ModelsActivityAPIResponse.comment_previews to include created_at, or transform the data before passing to EntityCard.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-card.tsx at line
33, housing.comment_previews is typed as ModelsCommenterPreview[] (which lacks
created_at) but EntityCard expects CommentPreview[] and reads
commentPreviews[0]?.created_at; fix by aligning types or transforming the data
before passing. Two options: 1) update
ModelsActivityAPIResponse.comment_previews (and ModelsCommenterPreview) to
include created_at where the API actually provides it; or 2) map
housing.comment_previews to a CommentPreview shape before passing to EntityCard
(e.g., copy fields and add created_at: preview.created_at ?? undefined or a
parsed timestamp) so EntityCard receives CommentPreview[]; reference symbols:
housing.comment_previews, ModelsCommenterPreview,
ModelsActivityAPIResponse.comment_previews, CommentPreview, EntityCard,
formatCommentTimeLabel.

>(({ tripID }, ref) => {
const entrySheetRef = useRef<AddHousingEntrySheetHandle>(null);
const manualSheetRef = useRef<AddHousingManualSheetHandle>(null);
const toast = useToast();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Unused variable: toast is declared but never used.

The useToast hook is called but the result is never used in this component.

Remove unused import and variable
   Box,
   Button,
   EmptyState,
   SkeletonRect,
   Text,
-  useToast,
 } from "@/design-system";
   const entrySheetRef = useRef<AddHousingEntrySheetHandle>(null);
   const manualSheetRef = useRef<AddHousingManualSheetHandle>(null);
-  const toast = useToast();
📝 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
const toast = useToast();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-tab-content.tsx at
line 79, The variable toast returned from useToast is declared but never used;
remove the unused call and related import: delete the line "const toast =
useToast();" in the HousingTabContent component (and remove the useToast import
if it exists at the top of the file) so no unused variable or import remains.


return (
<>
<AddItemManualSheet
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not sure if this is the exact component, but can we add the x icon ( or something like that) to the sheet on the top right?

Image

@in-mai-space in-mai-space linked an issue Apr 16, 2026 that may be closed by this pull request
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx (1)

220-238: ⚠️ Potential issue | 🟠 Major

Activity count does not match displayed list.

Line 220 checks activities.length === 0 for the empty state, and lines 237-238 display activities.length as the count. However, the FlatList at line 252 renders sortedActivities, which excludes housing. If a trip has only housing activities, the list appears empty but the count is non-zero and no empty state is shown.

Use sortedActivities.length for both the empty state check and the displayed count.

Proposed fix
-      ) : activities.length === 0 ? (
+      ) : sortedActivities.length === 0 ? (
         <Box alignItems="center" justifyContent="center" paddingVertical="xl">
           <EmptyState
             title="No activities yet"
             description="Tap + to add the first one!"
           />
         </Box>
       ) : (
         <>
           {/* Header row: count + sort toggle */}
           <Box
             flexDirection="row"
             justifyContent="space-between"
             alignItems="center"
             style={styles.headerRow}
           >
             <Text variant="bodyDefault" color="gray500">
-              {activities.length}{" "}
-              {activities.length === 1 ? "option" : "options"} added
+              {sortedActivities.length}{" "}
+              {sortedActivities.length === 1 ? "option" : "options"} added
             </Text>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/activities/components/activities-tab-content.tsx
around lines 220 - 238, The UI uses activities.length for the empty-state check
and the header count while the list actually renders sortedActivities (which
excludes housing), causing a mismatch; replace usages of activities.length in
the empty-state conditional and the header Text that shows the count with
sortedActivities.length so the EmptyState, count display in the header (the Text
inside the headerRow) and the FlatList (which renders sortedActivities) are
consistent; update the conditional that currently reads activities.length === 0
and the displayed count expression to use sortedActivities.length instead.
frontend/api/activities/custom/useActivitiesList.ts (1)

88-95: ⚠️ Potential issue | 🔴 Critical

Breaking change: refetch removed from hook return.

The refetch function is no longer returned from useActivitiesList, but frontend/app/(app)/trips/[id]/activities/index.tsx destructures and calls it (lines 43, 56). This will cause a runtime error during activity creation.

Either restore refetch in the return object or remove it from all callers.

Proposed fix to restore refetch
   const {
     data,
     isLoading,
     isFetchingNextPage,
     fetchNextPage,
     hasNextPage,
     isError,
+    refetch,
   } = useInfiniteQuery({
     // ...
   });

   return {
     activities,
     isLoading,
     isError,
     isLoadingMore: isFetchingNextPage,
     fetchMore,
     prependActivity,
+    refetch,
   };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/api/activities/custom/useActivitiesList.ts` around lines 88 - 95,
The hook useActivitiesList no longer returns the refetch function but callers
(e.g., the component that destructures useActivitiesList and calls refetch)
still expect it; restore compatibility by adding refetch to the hook's returned
object and map it to the refetch function produced by your query (the refetch
from useInfiniteQuery / the internal refetch variable), i.e., include "refetch"
alongside activities, isLoading, isError, isLoadingMore, fetchMore,
prependActivity so existing callers keep working.
♻️ Duplicate comments (5)
frontend/app/(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx (3)

134-142: ⚠️ Potential issue | 🟠 Major

Timezone drift when formatting dates.

Lines 138-139 use toISOString().split("T")[0] which converts to UTC first. In timezones east of UTC, this shifts the date back by one day. Use local date methods instead.

Proposed fix
+      const toLocalISODate = (d: Date) => {
+        const y = d.getFullYear();
+        const m = String(d.getMonth() + 1).padStart(2, "0");
+        const day = String(d.getDate()).padStart(2, "0");
+        return `${y}-${m}-${day}`;
+      };
+
       const dates =
         dateRange.start && dateRange.end
           ? [
               {
-                start: dateRange.start.toISOString().split("T")[0]!,
-                end: dateRange.end.toISOString().split("T")[0]!,
+                start: toLocalISODate(dateRange.start),
+                end: toLocalISODate(dateRange.end),
               },
             ]
           : undefined;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
around lines 134 - 142, The date formatting for the dates array uses
toISOString().split("T")[0] which converts the Date to UTC and causes timezone
drift; update the logic in the dates construction (where dateRange.start and
dateRange.end are used) to format using local date components (e.g.,
getFullYear(), getMonth()+1, getDate()) or a locale-safe formatter so the
produced "YYYY-MM-DD" reflects the local date instead of converting to UTC.
Ensure both dateRange.start and dateRange.end are handled the same way and
preserve the existing array shape when assigning to the dates constant.

298-327: 🛠️ Refactor suggestion | 🟠 Major

Replace magic numbers with design-system tokens.

Lines 300, 305, 318-320 use hardcoded spacing and typography values (16, 8, 20, 0) instead of centralized design-system tokens. As per coding guidelines, avoid hard-coded magic spacing numbers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
around lines 298 - 327, Replace the hardcoded numeric values in the StyleSheet
with design-system tokens: change gap: 16 in styles.formRows to the appropriate
spacing token (e.g., Spacing.md), gap: 8 in styles.formRow to the smaller
spacing token (e.g., Spacing.sm), lineHeight: 20 in styles.formRowInput to the
corresponding typography token (e.g., Typography.lineHeightBase) and
paddingVertical: 0 to the design token for vertical padding (e.g., Spacing.none
or Padding.none); update styles.formRowInputEmpty/formRowInputFilled only if
they rely on explicit numeric values—use existing ColorPalette and FontFamily
tokens already imported. Ensure you import or reference the correct token names
used across the codebase and replace each numeric literal in the
formRows/formRow/formRowInput blocks accordingly.

115-117: ⚠️ Potential issue | 🟠 Major

Stale coordinates not cleared on place-details failure.

When getPlaceDetailsCustom fails, only locationName is updated. If a previous selection set locationLat/locationLng, those stale coordinates remain and can be submitted with a mismatched name.

Proposed fix
       } catch {
         setLocationName(prediction.description ?? null);
+        setLocationLat(null);
+        setLocationLng(null);
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
around lines 115 - 117, The catch block after calling getPlaceDetailsCustom only
sets setLocationName(prediction.description ?? null) and leaves any previously
set coordinates (locationLat/locationLng) intact; update the failure path in
add-housing-manual-sheet.tsx so that when getPlaceDetailsCustom fails you also
clear the stale coordinates by calling the corresponding setters (e.g.,
setLocationLat(null) and setLocationLng(null) or the app's equivalent) alongside
updating locationName to avoid submitting mismatched name/coords.
frontend/app/(app)/trips/[id]/housing/_layout.tsx (1)

22-39: 🧹 Nitpick | 🔵 Trivial

Redundant options when header is hidden.

For the index and [id] screens, headerTitle and headerTransparent have no effect when headerShown: false. This adds unnecessary configuration.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/_layout.tsx around lines 22 - 39, The
screen option objects for the Stack.Screen entries named "index" and "[id]"
include redundant properties: when headerShown is false, headerTitle and
headerTransparent are ignored; remove headerTitle and headerTransparent from the
options for both Stack.Screen declarations and keep only the required options
(e.g., headerShown: false and gestureEnabled: false) to simplify the config and
avoid clutter.
frontend/app/(app)/trips/[id]/housing/components/housing-card.tsx (1)

25-28: ⚠️ Potential issue | 🟠 Major

Map the card props from the display fields, not the backend ids.

proposedBy={housing.proposed_by} passes the proposer id into a UI label, and thumbnailUrl={housing.thumbnail_url} does not use the activity media field. This will show the wrong proposer text and can drop the housing image. Use housing.proposer_name and housing.media_url here instead.

Proposed fix
-      thumbnailUrl={housing.thumbnail_url ?? undefined}
-      proposedBy={housing.proposed_by ?? undefined}
+      thumbnailUrl={housing.media_url ?? undefined}
+      proposedBy={housing.proposer_name ?? undefined}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-card.tsx around
lines 25 - 28, The EntityCard prop mappings are using backend IDs and the wrong
media field; update the props in housing-card.tsx so thumbnailUrl uses
housing.media_url (not housing.thumbnail_url) and proposedBy uses
housing.proposer_name (not housing.proposed_by), keeping proposerPictureUrl as
housing.proposer_picture_url if that contains the image; adjust the EntityCard
prop assignments (thumbnailUrl, proposedBy, proposerPictureUrl) to those display
fields to ensure correct label and image rendering.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/app/`(app)/trips/[id]/components/add-item-entry-sheet.tsx:
- Around line 203-205: The close button (Pressable using onClose and
styles.closeButton with the X icon) currently bypasses the bottom sheet's
disableClose behavior; update the render so the close control is hidden or
disabled when isAutofilling is true—e.g., conditionally render nothing or a
non-interactive element instead of the Pressable when isAutofilling, or pass
disabled prop and adjust hitSlop/opacity—but do not call onClose while
isAutofilling; ensure references are to Pressable, onClose, isAutofilling, and
the disableClose prop on the bottom sheet.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-tab-content.tsx:
- Around line 107-114: The housing tab currently collapses query failures into
the empty state; update the HousingTabContent component to surface a dedicated
error UI instead of falling through to "No housing options yet": read the error
flag/obj returned by useActivitiesList (in addition to isLoading/isLoadingMore
and housingOptions) and render the app's ErrorState component with a
user-friendly message and a retry handler that calls fetchMore (or refetch) and
does not show raw API error text; only if there is no error and the list is
empty should you render the EmptyState branch (also update the same logic around
the other empty-state branch referenced near the existing empty handling).

---

Outside diff comments:
In `@frontend/api/activities/custom/useActivitiesList.ts`:
- Around line 88-95: The hook useActivitiesList no longer returns the refetch
function but callers (e.g., the component that destructures useActivitiesList
and calls refetch) still expect it; restore compatibility by adding refetch to
the hook's returned object and map it to the refetch function produced by your
query (the refetch from useInfiniteQuery / the internal refetch variable), i.e.,
include "refetch" alongside activities, isLoading, isError, isLoadingMore,
fetchMore, prependActivity so existing callers keep working.

In
`@frontend/app/`(app)/trips/[id]/activities/components/activities-tab-content.tsx:
- Around line 220-238: The UI uses activities.length for the empty-state check
and the header count while the list actually renders sortedActivities (which
excludes housing), causing a mismatch; replace usages of activities.length in
the empty-state conditional and the header Text that shows the count with
sortedActivities.length so the EmptyState, count display in the header (the Text
inside the headerRow) and the FlatList (which renders sortedActivities) are
consistent; update the conditional that currently reads activities.length === 0
and the displayed count expression to use sortedActivities.length instead.

---

Duplicate comments:
In `@frontend/app/`(app)/trips/[id]/housing/_layout.tsx:
- Around line 22-39: The screen option objects for the Stack.Screen entries
named "index" and "[id]" include redundant properties: when headerShown is
false, headerTitle and headerTransparent are ignored; remove headerTitle and
headerTransparent from the options for both Stack.Screen declarations and keep
only the required options (e.g., headerShown: false and gestureEnabled: false)
to simplify the config and avoid clutter.

In
`@frontend/app/`(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx:
- Around line 134-142: The date formatting for the dates array uses
toISOString().split("T")[0] which converts the Date to UTC and causes timezone
drift; update the logic in the dates construction (where dateRange.start and
dateRange.end are used) to format using local date components (e.g.,
getFullYear(), getMonth()+1, getDate()) or a locale-safe formatter so the
produced "YYYY-MM-DD" reflects the local date instead of converting to UTC.
Ensure both dateRange.start and dateRange.end are handled the same way and
preserve the existing array shape when assigning to the dates constant.
- Around line 298-327: Replace the hardcoded numeric values in the StyleSheet
with design-system tokens: change gap: 16 in styles.formRows to the appropriate
spacing token (e.g., Spacing.md), gap: 8 in styles.formRow to the smaller
spacing token (e.g., Spacing.sm), lineHeight: 20 in styles.formRowInput to the
corresponding typography token (e.g., Typography.lineHeightBase) and
paddingVertical: 0 to the design token for vertical padding (e.g., Spacing.none
or Padding.none); update styles.formRowInputEmpty/formRowInputFilled only if
they rely on explicit numeric values—use existing ColorPalette and FontFamily
tokens already imported. Ensure you import or reference the correct token names
used across the codebase and replace each numeric literal in the
formRows/formRow/formRowInput blocks accordingly.
- Around line 115-117: The catch block after calling getPlaceDetailsCustom only
sets setLocationName(prediction.description ?? null) and leaves any previously
set coordinates (locationLat/locationLng) intact; update the failure path in
add-housing-manual-sheet.tsx so that when getPlaceDetailsCustom fails you also
clear the stale coordinates by calling the corresponding setters (e.g.,
setLocationLat(null) and setLocationLng(null) or the app's equivalent) alongside
updating locationName to avoid submitting mismatched name/coords.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-card.tsx:
- Around line 25-28: The EntityCard prop mappings are using backend IDs and the
wrong media field; update the props in housing-card.tsx so thumbnailUrl uses
housing.media_url (not housing.thumbnail_url) and proposedBy uses
housing.proposer_name (not housing.proposed_by), keeping proposerPictureUrl as
housing.proposer_picture_url if that contains the image; adjust the EntityCard
prop assignments (thumbnailUrl, proposedBy, proposerPictureUrl) to those display
fields to ensure correct label and image rendering.
🪄 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: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7b0960a3-ae1b-4a8b-b555-9bcfbeba2695

📥 Commits

Reviewing files that changed from the base of the PR and between f98c211 and 43b94cd.

⛔ Files ignored due to path filters (1)
  • frontend/assets/images/house.png is excluded by !**/*.png
📒 Files selected for processing (11)
  • frontend/api/activities/custom/useActivitiesList.ts
  • frontend/app/(app)/trips/[id]/_layout.tsx
  • frontend/app/(app)/trips/[id]/activities/[id]/index.tsx
  • frontend/app/(app)/trips/[id]/activities/components/activities-tab-content.tsx
  • frontend/app/(app)/trips/[id]/components/add-item-entry-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/_layout.tsx
  • frontend/app/(app)/trips/[id]/housing/components/add-housing-entry-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/components/add-housing-manual-sheet.tsx
  • frontend/app/(app)/trips/[id]/housing/components/housing-card.tsx
  • frontend/app/(app)/trips/[id]/housing/components/housing-tab-content.tsx
  • frontend/app/(app)/trips/[id]/index.tsx

Comment on lines +203 to +205
<Pressable onPress={onClose} hitSlop={12} style={styles.closeButton}>
<X size={20} color={ColorPalette.gray950} />
</Pressable>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Close button bypasses autofill lock.

The close button calls onClose directly, but the bottom sheet has disableClose={isAutofilling} to prevent dismissal during autofill. This button circumvents that protection and allows the user to dismiss the sheet while autofill is in progress.

Disable the close button or hide it when isAutofilling is true.

Proposed fix
-        <Pressable onPress={onClose} hitSlop={12} style={styles.closeButton}>
+        <Pressable
+          onPress={onClose}
+          hitSlop={12}
+          style={styles.closeButton}
+          disabled={isAutofilling}
+        >
-          <X size={20} color={ColorPalette.gray950} />
+          <X size={20} color={isAutofilling ? ColorPalette.gray300 : ColorPalette.gray950} />
         </Pressable>
📝 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
<Pressable onPress={onClose} hitSlop={12} style={styles.closeButton}>
<X size={20} color={ColorPalette.gray950} />
</Pressable>
<Pressable
onPress={onClose}
hitSlop={12}
style={styles.closeButton}
disabled={isAutofilling}
>
<X size={20} color={isAutofilling ? ColorPalette.gray300 : ColorPalette.gray950} />
</Pressable>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/components/add-item-entry-sheet.tsx around
lines 203 - 205, The close button (Pressable using onClose and
styles.closeButton with the X icon) currently bypasses the bottom sheet's
disableClose behavior; update the render so the close control is hidden or
disabled when isAutofilling is true—e.g., conditionally render nothing or a
non-interactive element instead of the Pressable when isAutofilling, or pass
disabled prop and adjust hitSlop/opacity—but do not call onClose while
isAutofilling; ensure references are to Pressable, onClose, isAutofilling, and
the disableClose prop on the bottom sheet.

Comment on lines +107 to +114
const {
activities: housingOptions,
isLoading,
isLoadingMore,
fetchMore,
prependActivity: prependHousing,
} = useActivitiesList(tripID, { category: "housing" });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Do not collapse fetch failures into the empty state.

This screen only distinguishes loading from empty. If the housing query fails, users can fall through to “No housing options yet,” which is misleading for a network or backend error. Render a dedicated error state with retry handling before the empty state branch.

As per coding guidelines "React/Expo UI error handling must not expose raw API errors; use UI states (LoadingState, ErrorState, EmptyState); errors shown to users must be clear and user-friendly".

Also applies to: 180-190

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/`(app)/trips/[id]/housing/components/housing-tab-content.tsx
around lines 107 - 114, The housing tab currently collapses query failures into
the empty state; update the HousingTabContent component to surface a dedicated
error UI instead of falling through to "No housing options yet": read the error
flag/obj returned by useActivitiesList (in addition to isLoading/isLoadingMore
and housingOptions) and render the app's ErrorState component with a
user-friendly message and a retry handler that calls fetchMore (or refetch) and
does not show raw API error text; only if there is no error and the list is
empty should you render the EmptyState branch (also update the same logic around
the other empty-state branch referenced near the existing empty handling).

@afnantuffaha afnantuffaha force-pushed the housing-creation-flow branch from 0d2b129 to 11c6cfe Compare April 16, 2026 17:18
@afnantuffaha afnantuffaha force-pushed the housing-creation-flow branch from 4888af9 to 7bd76fc Compare April 16, 2026 17:20
@aahiltn aahiltn self-requested a review April 16, 2026 17:31
Copy link
Copy Markdown
Contributor

@aahiltn aahiltn left a comment

Choose a reason for hiding this comment

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

SHIP

@aahiltn aahiltn merged commit abb6a5d into main Apr 16, 2026
9 checks passed
@aahiltn aahiltn deleted the housing-creation-flow branch April 16, 2026 17:32
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.

[FE]: Housing Tab

3 participants