Skip to content

Feat/escrow detail route placeholder#87

Open
Obiajulu-gif wants to merge 1 commit intosafetrustcr:mainfrom
Obiajulu-gif:feat/escrow-detail-route-placeholder
Open

Feat/escrow detail route placeholder#87
Obiajulu-gif wants to merge 1 commit intosafetrustcr:mainfrom
Obiajulu-gif:feat/escrow-detail-route-placeholder

Conversation

@Obiajulu-gif
Copy link
Copy Markdown
Contributor

@Obiajulu-gif Obiajulu-gif commented Mar 28, 2026

This pull request sets up the initial structure and UI stubs for the SafeTrust web application using Next.js. It introduces placeholder pages and components for the apartment booking and escrow management flows, applies consistent styling, and configures the project for development. The changes are organized into project setup, layout and global styles, and feature-specific UI stubs.

Project setup and configuration:

  • Adds a new package.json for the web app with Next.js, React, TypeScript, and related dependencies, along with basic scripts for development and production.
  • Introduces a next.config.mjs file that configures Next.js to ignore ESLint and TypeScript errors during builds to streamline initial development.

Layout and global styles:

  • Implements a RootLayout in layout.tsx that wraps all pages and imports a new globals.css stylesheet for consistent base styling. [1] [2]
  • Defines responsive CSS rules for sidebar and suggestions components, and sets up base typography and color scheme.

Feature-specific UI stubs:

These changes provide a scaffold for further development, with clear TODOs indicating where real data and components will be integrated as the project progresses.

Closes #72

Summary by CodeRabbit

Release Notes

  • New Features
    • Added apartment detail pages with property gallery, monthly pricing display, room counts, amenities, owner information, full apartment descriptions, and booking links.
    • Added escrow detail pages featuring invoice number display, payment status tracking (paid/blocked/released), notes section, and a step-by-step progress indicator for escrow transaction management.

Copilot AI review requested due to automatic review settings March 28, 2026 19:42
@drips-wave
Copy link
Copy Markdown

drips-wave bot commented Mar 28, 2026

@Obiajulu-gif Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

This pull request introduces an escrow detail page route handler with status-driven view stubs for three escrow states (paid, blocked, released), an apartment detail page with static content, and two accompanying escrow components (InvoiceHeader and ProcessStepper) for rendering invoice information and process tracking.

Changes

Cohort / File(s) Summary
Escrow Detail Route & Stub Views
apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx
New dynamic page component that maps query parameter status to a ViewConfig, renders an InvoiceHeader, conditionally displays one of three inline stub sections (PaidStubView, BlockedStubView, ReleasedStubView), and includes a Notes textarea and ProcessStepper in a two-column layout.
Escrow Components
apps/web/src/components/escrow/InvoiceHeader.tsx, apps/web/src/components/escrow/ProcessStepper.tsx
InvoiceHeader renders invoice metadata with a status-driven badge (paid/blocked/released); ProcessStepper displays a vertical step tracker with active/completed/pending state indicators based on a currentStep prop (1–4).
Apartment Detail Page
apps/web/src/app/hotel/[id]/page.tsx
New page component rendering a static apartment detail layout with hardcoded placeholder data, including image gallery, metadata rows, suggestion cards, and a "BOOK" link—all sourced from a STUB_APARTMENT constant with no data fetching.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

  • Feat/dashboard route placeholder #86 — Both PRs add or modify the apartment detail page route (apps/web/src/app/hotel/[id]/page.tsx), creating a direct code-level overlap at the same file path.

Suggested reviewers

  • sotoJ24

Poem

🐰 Escrow paths now shimmer bright,
Status flows from left to right,
Paid, blocked, released—three views in one,
Stepper marches, progress is done!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: introducing the escrow detail route placeholder with status-driven stub views.
Linked Issues check ✅ Passed All coding requirements from issue #72 are met: escrow detail route created, status-driven views implemented, ProcessStepper and InvoiceHeader integrated, and dev hint included.
Out of Scope Changes check ✅ Passed Changes to apartment detail page and supporting components are directly related to the overall PR objectives of scaffolding apartment booking and escrow flows.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Scaffolds the SafeTrust apps/web Next.js application with placeholder routes and UI for the apartment detail and escrow detail “waterfall” flow (Issue #72), plus monorepo build/workspace configuration.

Changes:

  • Adds pnpm workspace + Turborepo build wiring (root package.json, turbo.json, scripts/build.mjs, lockfile).
  • Introduces a Next.js app skeleton (Root layout, globals, home page, dashboard placeholders).
  • Implements placeholder hotel detail and escrow detail routes, including shared escrow UI components (InvoiceHeader, ProcessStepper).

Reviewed changes

Copilot reviewed 16 out of 20 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
turbo.json Adds Turborepo build task outputs for Next.js.
scripts/build.mjs Adds a cross-platform build wrapper invoking pnpm --filter @safetrust/web build.
pnpm-workspace.yaml Declares apps/* as workspace packages.
pnpm-lock.yaml Locks dependency graph for the new workspace/web app.
package.json Adds root package metadata + build script entrypoint.
.gitignore Ignores node_modules, turbo cache, and Next build output dirs.
apps/web/package.json Defines the @safetrust/web Next.js app dependencies and scripts.
apps/web/next.config.mjs Configures Next.js build behavior (currently ignores TS/ESLint errors).
apps/web/tsconfig.json Sets TS config + @/* path alias for the web app.
apps/web/next-env.d.ts Next.js TypeScript environment declarations.
apps/web/src/app/layout.tsx Root layout applying global styles and metadata.
apps/web/src/app/globals.css Base styling + responsive display helpers for placeholder sidebars.
apps/web/src/app/page.tsx Home page linking to the hotel detail placeholder.
apps/web/src/app/dashboard/layout.tsx Dashboard layout with a stub sidebar.
apps/web/src/app/dashboard/page.tsx Dashboard placeholder sections (quick actions/overview/table).
apps/web/src/app/hotel/[id]/page.tsx Apartment detail placeholder with “BOOK” CTA into escrow flow.
apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx Escrow detail placeholder route with status-driven stub views.
apps/web/src/components/escrow/InvoiceHeader.tsx Shared invoice/status header component for escrow views.
apps/web/src/components/escrow/ProcessStepper.tsx Shared “Process” stepper component for escrow flow status.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +2 to +7
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

Disabling ESLint and TypeScript errors during next build makes CI/production builds succeed even when there are lint/type errors (and can mask real runtime issues). Consider removing these flags or gating them behind a dev-only env var so builds fail in CI.

Suggested change
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
const allowBuildErrors = process.env.ALLOW_BUILD_ERRORS === 'true';
const nextConfig = {
eslint: {
ignoreDuringBuilds: allowBuildErrors,
},
typescript: {
ignoreBuildErrors: allowBuildErrors,

Copilot uses AI. Check for mistakes.
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.

.

Comment on lines +90 to +99
function getStubView(status: string | undefined): ViewConfig {
switch (status) {
case 'blocked':
return { label: 'blocked', step: 3, title: 'Payment batch - Escrow Status' };
case 'released':
return { label: 'released', step: 4, title: 'Deposit / Escrow Released' };
case 'paid':
default:
return { label: 'paid', step: 2, title: 'Payment batch January 2025' };
}
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

The header comment says unknown/missing status should redirect to /hotel/[id]/escrow/create, but getStubView currently falls back to paid for any unrecognized status. If the intended behavior is a redirect for invalid values, validate searchParams.status and call redirect(...) when it's not one of the supported stub statuses.

Copilot uses AI. Check for mistakes.
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.

.

PDF
</button>
</div>
<textarea style={styles.input} placeholder="Justification..." />
Copy link

Copilot AI Mar 28, 2026

Choose a reason for hiding this comment

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

This <textarea> relies on a placeholder only; it should have an associated <label> (or at least aria-label/aria-labelledby) so screen readers can identify the field even when the placeholder disappears.

Copilot uses AI. Check for mistakes.
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.

.

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: 6

🧹 Nitpick comments (6)
apps/web/src/components/escrow/InvoiceHeader.tsx (1)

34-39: Use a neutral timestamp prop name for all escrow states.

paidAt is reused for blocked/released states where the value represents a generic status update time. Renaming to updatedAt will make integration clearer when real data is wired.

Small naming cleanup
 export function InvoiceHeader({
   invoiceNumber,
-  paidAt,
+  updatedAt,
   status,
 }: {
   invoiceNumber: string;
-  paidAt: string;
+  updatedAt: string;
   status: InvoiceStatus;
 }) {
@@
-          <p style={{ margin: '0.25rem 0 0', fontWeight: 600 }}>{paidAt}</p>
+          <p style={{ margin: '0.25rem 0 0', fontWeight: 600 }}>{updatedAt}</p>

Also applies to: 87-88

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

In `@apps/web/src/components/escrow/InvoiceHeader.tsx` around lines 34 - 39, The
prop name paidAt on the InvoiceHeader component should be renamed to updatedAt
to reflect a neutral status timestamp; update the prop type annotation in the
InvoiceHeader parameter list (replace paidAt: string with updatedAt: string),
update every internal usage of paidAt within InvoiceHeader (e.g., where you
render the timestamp around lines 87-88), and update any places that pass the
prop into InvoiceHeader to use updatedAt instead of paidAt so all escrow states
(paid/blocked/released) receive a consistently named timestamp prop.
apps/web/src/app/globals.css (1)

14-17: Restore clearer global link affordance.

Line 14-17 removes default link underlines globally, which can make inline links harder to distinguish from body text. Prefer preserving underlines (or adding a stronger explicit link treatment).

Suggested CSS adjustment
 a {
   color: inherit;
-  text-decoration: none;
+  text-decoration: underline;
+  text-underline-offset: 0.12em;
+}
+
+a:hover {
+  text-decoration-thickness: 2px;
+}
+
+a:focus-visible {
+  outline: 2px solid `#2563eb`;
+  outline-offset: 2px;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/globals.css` around lines 14 - 17, The global anchor rule
currently removes underlines (selector "a"), which reduces link affordance;
update the "a" CSS rule to preserve or reintroduce a clear link treatment by
removing text-decoration: none and either restoring the default underline or
explicitly adding text-decoration: underline (optionally combined with a
distinct link color such as a --link-color variable) so inline links remain
visually distinguishable from body text.
package.json (1)

5-7: Add root quality-gate scripts alongside build.

Keeping only build at root makes it easier for lint/type issues to slip through during scaffold iterations. Consider adding lint and typecheck scripts for CI and local verification.

Suggested script additions
   "scripts": {
-    "build": "node scripts/build.mjs"
+    "build": "node scripts/build.mjs",
+    "lint": "pnpm --filter `@safetrust/web` lint",
+    "typecheck": "pnpm --filter `@safetrust/web` typecheck"
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` around lines 5 - 7, The package.json currently exposes only the
"build" script, which allows linting/type errors to be missed; add root-level
quality-gate scripts next to "build" such as "lint" (to run ESLint across the
repo) and "typecheck" (to run TypeScript's checker/tsc --noEmit or your monorepo
typecheck command), and update CI/local docs to invoke these scripts; look for
the "scripts" object and add "lint" and "typecheck" entries so maintainers can
run npm run lint and npm run typecheck alongside npm run build.
scripts/build.mjs (1)

4-10: Build entrypoint bypasses the Turbo task graph.

The script invokes the package build directly via spawnSync, so the task dependencies and outputs defined in turbo.json are not exercised from the root build command.

Consider routing the build through turbo run build to leverage the established task orchestration:

Suggested refactor
 const result =
   process.platform === 'win32'
-    ? spawnSync('cmd.exe', ['/c', 'pnpm', '--filter', '@safetrust/web', 'build'], {
+    ? spawnSync('cmd.exe', ['/c', 'pnpm', 'exec', 'turbo', 'run', 'build', '--filter=@safetrust/web'], {
         stdio: 'inherit',
       })
-    : spawnSync('pnpm', ['--filter', '@safetrust/web', 'build'], {
+    : spawnSync('pnpm', ['exec', 'turbo', 'run', 'build', '--filter=@safetrust/web'], {
         stdio: 'inherit',
       });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/build.mjs` around lines 4 - 10, The script currently bypasses Turbo
by calling spawnSync with pnpm to build `@safetrust/web` (see process.platform and
spawnSync invocations); replace those direct pnpm build calls with a spawnSync
invocation that runs the root orchestration command (e.g., "pnpm turbo run
build" or "turbo run build") so Turbo's task graph and caching defined in
turbo.json are used; update both the Windows branch (cmd.exe ['/c', ...]) and
the non-Windows branch (spawnSync('pnpm', [...])) to invoke the turbo run build
command instead of the package-level build target.
apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx (1)

203-209: Add explicit labels for textareas (don’t rely on placeholders).

These fields are not programmatically labeled, which hurts accessibility. Add <label htmlFor> + id for each textarea.

Proposed fix
-        <textarea style={styles.input} placeholder="Justification..." />
+        <label htmlFor="escrow-justification">Justification</label>
+        <textarea id="escrow-justification" style={styles.input} placeholder="Justification..." />
@@
-          <textarea style={{ ...styles.input, minHeight: '5rem' }} placeholder="Claims..." />
+          <label htmlFor="escrow-claims">Claims</label>
+          <textarea id="escrow-claims" style={{ ...styles.input, minHeight: '5rem' }} placeholder="Claims..." />
@@
-            <textarea style={styles.input} placeholder="Notes..." />
+            <label htmlFor="escrow-notes">Notes</label>
+            <textarea id="escrow-notes" style={styles.input} placeholder="Notes..." />

Also applies to: 223-224, 280-281

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

In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx around lines 203 -
209, The textarea elements (e.g., the Escrow Justification textarea and the
other textareas referenced at lines 223-224 and 280-281) lack programmatic
labels; add a <label htmlFor="..."> with a matching id on each textarea (for
example id="escrow-justification") so the textarea elements have explicit labels
tied via htmlFor/id, or alternatively provide an aria-label if a visible label
isn't desired; update the JSX around the textarea in the EscrowJustification
block and the other two textarea locations to include these ids and label
elements to satisfy accessibility requirements.
apps/web/src/app/hotel/[id]/page.tsx (1)

37-43: Avoid inline display: none for responsive suggestions panel.

The inline display makes visibility depend on CSS override precedence. Move display control fully to stylesheet/class to keep responsive behavior predictable.

Proposed fix
   aside: {
     width: '18rem',
     borderRight: '1px solid `#fed7aa`',
     padding: '1rem',
     flexShrink: 0,
-    display: 'none',
   } satisfies CSSProperties,

Also applies to: 109-109

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

In `@apps/web/src/app/hotel/`[id]/page.tsx around lines 37 - 43, The inline style
object "aside" currently sets display: 'none' which causes precedence issues;
remove the display property from the inline "aside" styles and instead add a CSS
class (e.g., responsive-aside) that controls visibility via media queries (show
on large screens, hide on small screens) and apply that class to the aside
element where the "aside" style object is used; do the same change for the other
occurrence referenced (around the second "aside" usage at the later location) so
responsive visibility is managed entirely in the stylesheet rather than inline
styles.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/next.config.mjs`:
- Around line 3-8: The build config currently disables ESLint and TypeScript
build-time checks via the next.config.mjs keys eslint.ignoreDuringBuilds and
typescript.ignoreBuildErrors; revert those to enable build-time enforcement
(remove the ignores or set them to false) and add explicit lint and typecheck
scripts to package.json (e.g., "lint" and "typecheck") plus a CI workflow step
that runs those scripts so lint/type errors fail PRs; ensure any temporary
failures are fixed or gated behind feature branches rather than permanently
disabling eslint.ignoreDuringBuilds or typescript.ignoreBuildErrors.

In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx:
- Line 115: Replace the personal-looking stub contact data used in the UI (e.g.,
the InfoPair with value "John_s@gmail.com" and the other occurrences noted) with
non-identifying fixture emails such as "tenant@example.com" or
"owner@example.com"; locate the InfoPair usages in the escrow page component
(references: InfoPair and the escrow page component functions/JSX) and update
the value props at the three occurrences to use safe fixture addresses instead
of realistic personal emails.
- Around line 90-100: Update getStubView to use the canonical mapping and
redirect on invalid/absent status: map 'funded' -> the existing 'paid' result
(label 'paid', step 2, title 'Payment batch January 2025'), 'active' -> the
existing 'blocked' result (label 'blocked', step 3, title 'Payment batch -
Escrow Status'), and 'completed' -> the existing 'released' result (label
'released', step 4, title 'Deposit / Escrow Released'); for the default case, do
not return 'paid'—instead trigger a redirect to /hotel/[id]/escrow/create (or
throw/return a sentinel that the caller handling page.tsx uses to perform the
redirect). Ensure the switch in getStubView covers these exact status strings
and that the redirect path is used when status is invalid or undefined.

In `@apps/web/src/app/hotel/`[id]/page.tsx:
- Around line 21-25: The owner fixture currently contains real personal contact
data; update the stub in the owner object (owner.name, owner.email, owner.phone)
to use clearly anonymized placeholder values (e.g. a generic name or "Owner
Name", an obviously fake email like owner@example.com, and a non-personal dummy
phone like +1-555-0100) so no PII is present in the page.tsx fixture returned by
the component or data loader.
- Line 132: The suggestions list contains a hardcoded price string ("$4.000") in
the <p> element; replace it with the same currency formatting used elsewhere
(e.g., call Number(suggestion.price).toLocaleString(locale, { style: 'currency',
currency: 'USD' }) or reuse the app's currency formatter) so values render
consistently; update the JSX that renders the price (the <p style={{ margin: 0,
color: '#ea580c', fontWeight: 600 }}> element) to use the formatted value
instead of the literal "$4.000".

In `@scripts/build.mjs`:
- Line 16: The current exit uses process.exit(result.status ?? 0) which treats
signal-terminated children (where spawnSync sets result.status to null and
result.signal to e.g. "SIGTERM") as success; update the script that handles the
spawnSync result to check result.signal and exit with a non-zero code (e.g., 1)
when result.signal is set, otherwise use result.status (or 0 fallback). Locate
the spawnSync invocation and the exit call (process.exit(result.status ?? 0))
and change the logic to: if (result.signal) exit non-zero; else exit with
result.status ?? 0.

---

Nitpick comments:
In `@apps/web/src/app/globals.css`:
- Around line 14-17: The global anchor rule currently removes underlines
(selector "a"), which reduces link affordance; update the "a" CSS rule to
preserve or reintroduce a clear link treatment by removing text-decoration: none
and either restoring the default underline or explicitly adding text-decoration:
underline (optionally combined with a distinct link color such as a --link-color
variable) so inline links remain visually distinguishable from body text.

In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx:
- Around line 203-209: The textarea elements (e.g., the Escrow Justification
textarea and the other textareas referenced at lines 223-224 and 280-281) lack
programmatic labels; add a <label htmlFor="..."> with a matching id on each
textarea (for example id="escrow-justification") so the textarea elements have
explicit labels tied via htmlFor/id, or alternatively provide an aria-label if a
visible label isn't desired; update the JSX around the textarea in the
EscrowJustification block and the other two textarea locations to include these
ids and label elements to satisfy accessibility requirements.

In `@apps/web/src/app/hotel/`[id]/page.tsx:
- Around line 37-43: The inline style object "aside" currently sets display:
'none' which causes precedence issues; remove the display property from the
inline "aside" styles and instead add a CSS class (e.g., responsive-aside) that
controls visibility via media queries (show on large screens, hide on small
screens) and apply that class to the aside element where the "aside" style
object is used; do the same change for the other occurrence referenced (around
the second "aside" usage at the later location) so responsive visibility is
managed entirely in the stylesheet rather than inline styles.

In `@apps/web/src/components/escrow/InvoiceHeader.tsx`:
- Around line 34-39: The prop name paidAt on the InvoiceHeader component should
be renamed to updatedAt to reflect a neutral status timestamp; update the prop
type annotation in the InvoiceHeader parameter list (replace paidAt: string with
updatedAt: string), update every internal usage of paidAt within InvoiceHeader
(e.g., where you render the timestamp around lines 87-88), and update any places
that pass the prop into InvoiceHeader to use updatedAt instead of paidAt so all
escrow states (paid/blocked/released) receive a consistently named timestamp
prop.

In `@package.json`:
- Around line 5-7: The package.json currently exposes only the "build" script,
which allows linting/type errors to be missed; add root-level quality-gate
scripts next to "build" such as "lint" (to run ESLint across the repo) and
"typecheck" (to run TypeScript's checker/tsc --noEmit or your monorepo typecheck
command), and update CI/local docs to invoke these scripts; look for the
"scripts" object and add "lint" and "typecheck" entries so maintainers can run
npm run lint and npm run typecheck alongside npm run build.

In `@scripts/build.mjs`:
- Around line 4-10: The script currently bypasses Turbo by calling spawnSync
with pnpm to build `@safetrust/web` (see process.platform and spawnSync
invocations); replace those direct pnpm build calls with a spawnSync invocation
that runs the root orchestration command (e.g., "pnpm turbo run build" or "turbo
run build") so Turbo's task graph and caching defined in turbo.json are used;
update both the Windows branch (cmd.exe ['/c', ...]) and the non-Windows branch
(spawnSync('pnpm', [...])) to invoke the turbo run build command instead of the
package-level build target.
🪄 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: 6aa5a845-8e73-4ae1-9a29-26fa86e78def

📥 Commits

Reviewing files that changed from the base of the PR and between decc85f and dcbb680.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (19)
  • pnpm-workspace.yaml
  • .gitignore
  • apps/web/next-env.d.ts
  • apps/web/next.config.mjs
  • apps/web/package.json
  • apps/web/src/app/dashboard/layout.tsx
  • apps/web/src/app/dashboard/page.tsx
  • apps/web/src/app/globals.css
  • apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx
  • apps/web/src/app/hotel/[id]/page.tsx
  • apps/web/src/app/layout.tsx
  • apps/web/src/app/page.tsx
  • apps/web/src/components/escrow/InvoiceHeader.tsx
  • apps/web/src/components/escrow/ProcessStepper.tsx
  • apps/web/tsconfig.json
  • package.json
  • pnpm-workspace.yaml
  • scripts/build.mjs
  • turbo.json

Comment on lines +3 to +8
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 28, 2026

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
# Verify current guardrail state and whether alternative scripts exist.
rg -n '"lint"|"typecheck"|ignoreDuringBuilds|ignoreBuildErrors' \
  package.json apps/web/package.json apps/web/next.config.mjs -C2

Repository: safetrustcr/dApp-SafeTrust

Length of output: 406


🏁 Script executed:

cat apps/web/package.json

Repository: safetrustcr/dApp-SafeTrust

Length of output: 465


🏁 Script executed:

find . -name "package.json" -type f | head -5 | xargs cat

Repository: safetrustcr/dApp-SafeTrust

Length of output: 609


🏁 Script executed:

find .github/workflows -name "*.yml" -o -name "*.yaml" 2>/dev/null | head -3 | xargs cat

Repository: safetrustcr/dApp-SafeTrust

Length of output: 52


🏁 Script executed:

cat -n apps/web/tsconfig.json

Repository: safetrustcr/dApp-SafeTrust

Length of output: 888


Build is configured to ignore both lint and type errors.

Lines 4 and 7 disable core build-time safeguards while tsconfig.json enforces strict mode. No lint or typecheck scripts exist in package.json and no CI workflows are configured, leaving no alternative quality gates. Invalid code can be promoted to production undetected.

Suggested fix:

 const nextConfig = {
   eslint: {
-    ignoreDuringBuilds: true,
+    ignoreDuringBuilds: false,
   },
   typescript: {
-    ignoreBuildErrors: true,
+    ignoreBuildErrors: 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
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
eslint: {
ignoreDuringBuilds: false,
},
typescript: {
ignoreBuildErrors: false,
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/next.config.mjs` around lines 3 - 8, The build config currently
disables ESLint and TypeScript build-time checks via the next.config.mjs keys
eslint.ignoreDuringBuilds and typescript.ignoreBuildErrors; revert those to
enable build-time enforcement (remove the ignores or set them to false) and add
explicit lint and typecheck scripts to package.json (e.g., "lint" and
"typecheck") plus a CI workflow step that runs those scripts so lint/type errors
fail PRs; ensure any temporary failures are fixed or gated behind feature
branches rather than permanently disabling eslint.ignoreDuringBuilds or
typescript.ignoreBuildErrors.

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.

.

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.

@sotoJ24, understood! Just to leave a note for future reference: when the scaffolding is ready for production, re-enabling these checks (setting ignoreDuringBuilds: false and ignoreBuildErrors: false) alongside dedicated lint and typecheck scripts will help catch issues before they reach production. Happy to help when you're ready to make that change!

Comment on lines +90 to +100
function getStubView(status: string | undefined): ViewConfig {
switch (status) {
case 'blocked':
return { label: 'blocked', step: 3, title: 'Payment batch - Escrow Status' };
case 'released':
return { label: 'released', step: 4, title: 'Deposit / Escrow Released' };
case 'paid':
default:
return { label: 'paid', step: 2, title: 'Payment batch January 2025' };
}
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 28, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Implement canonical status mapping + redirect fallback (objective mismatch).

getStubView currently treats unknown/missing status as paid. The issue objective calls for mapping funded→paid, active→blocked, completed→released, and redirecting default/invalid states to /hotel/[id]/escrow/create.

Proposed fix
+import { redirect } from 'next/navigation';
 import { InvoiceHeader } from '@/components/escrow/InvoiceHeader';
 import { ProcessStepper } from '@/components/escrow/ProcessStepper';
 import type { CSSProperties } from 'react';

 type StubStatus = 'paid' | 'blocked' | 'released';
+type QueryStatus = StubStatus | 'funded' | 'active' | 'completed';

-function getStubView(status: string | undefined): ViewConfig {
+function getStubView(status: QueryStatus | undefined): ViewConfig | null {
   switch (status) {
+    case 'active':
     case 'blocked':
       return { label: 'blocked', step: 3, title: 'Payment batch - Escrow Status' };
+    case 'completed':
     case 'released':
       return { label: 'released', step: 4, title: 'Deposit / Escrow Released' };
+    case 'funded':
     case 'paid':
-    default:
       return { label: 'paid', step: 2, title: 'Payment batch January 2025' };
+    default:
+      return null;
   }
 }
@@
-  const view = getStubView(searchParams?.status);
+  const view = getStubView(searchParams?.status as QueryStatus | undefined);
+  if (!view) {
+    redirect(`/hotel/${params.id}/escrow/create`);
+  }

Also applies to: 246-246

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

In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx around lines 90 -
100, Update getStubView to use the canonical mapping and redirect on
invalid/absent status: map 'funded' -> the existing 'paid' result (label 'paid',
step 2, title 'Payment batch January 2025'), 'active' -> the existing 'blocked'
result (label 'blocked', step 3, title 'Payment batch - Escrow Status'), and
'completed' -> the existing 'released' result (label 'released', step 4, title
'Deposit / Escrow Released'); for the default case, do not return 'paid'—instead
trigger a redirect to /hotel/[id]/escrow/create (or throw/return a sentinel that
the caller handling page.tsx uses to perform the redirect). Ensure the switch in
getStubView covers these exact status strings and that the redirect path is used
when status is invalid or 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.

.

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.

@sotoJ24 — Noted! If you'd like to revisit the canonical status mapping and redirect fallback for getStubView in a follow-up PR, feel free to reference the proposed fix in this comment. No pressure to address it now.

😔

(\(\
( -.-)
o_(")(")

return (
<div style={{ display: 'grid', gap: '1.5rem' }}>
<div style={styles.splitGrid}>
<InfoPair label="Billed to" value="John_s@gmail.com" />
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 28, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace personal-looking stub contact data with safe fixture values.

Committing realistic emails in UI stubs is a privacy/compliance risk. Use non-identifying fixtures (e.g., tenant@example.com, owner@example.com) across placeholders.

Also applies to: 173-173, 181-181

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

In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx at line 115, Replace
the personal-looking stub contact data used in the UI (e.g., the InfoPair with
value "John_s@gmail.com" and the other occurrences noted) with non-identifying
fixture emails such as "tenant@example.com" or "owner@example.com"; locate the
InfoPair usages in the escrow page component (references: InfoPair and the
escrow page component functions/JSX) and update the value props at the three
occurrences to use safe fixture addresses instead of realistic personal emails.

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.

.

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.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check current state of the escrow page for email stub values
rg -n "gmail\|example\.com\|@" apps/web/src/app/hotel/

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Check if the file exists and look for email values
fd "page.tsx" apps/web/src/app/hotel --exec cat {}

Length of output: 15388


@sotoJ24, the personal-looking emails are still present in the current code. Here are all four occurrences that need updating:

File Location Current value Suggested value
escrow/[escrowId]/page.tsx PaidStubView – "Billed to" John_s@gmail.com tenant@example.com
escrow/[escrowId]/page.tsx BlockedStubView – Tenant Email John_s@gmail.com tenant@example.com
escrow/[escrowId]/page.tsx BlockedStubView – Owner Email albertoCasas100@gmail.com owner@example.com
hotel/[id]/page.tsx STUB_APARTMENT.owner.email albertoCasas100@gmail.com owner@example.com

Would you like me to plan the code changes to swap these out for safe fixture values?

Comment on lines +21 to +25
owner: {
name: 'Alberto Casas',
email: 'albertoCasas100@gmail.com',
phone: '+506 64852179',
},
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 28, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Use anonymized fixture contacts in stubs.

owner.email/owner.phone should use clearly fake, non-personal fixtures to avoid accidental PII leakage in shipped placeholder content.

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

In `@apps/web/src/app/hotel/`[id]/page.tsx around lines 21 - 25, The owner fixture
currently contains real personal contact data; update the stub in the owner
object (owner.name, owner.email, owner.phone) to use clearly anonymized
placeholder values (e.g. a generic name or "Owner Name", an obviously fake email
like owner@example.com, and a non-personal dummy phone like +1-555-0100) so no
PII is present in the page.tsx fixture returned by the component or data loader.

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.

.

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.

@sotoJ24, here's the fix to replace the real-looking contact data with clearly anonymized placeholder values:

  • Replace owner.name, owner.email, and owner.phone in STUB_APARTMENT with generic, obviously fake values

Failed to handle agent chat message. Please try again.

<p style={{ margin: '0.25rem 0', color: '#78716c' }}>
329 Calle santos, San José
</p>
<p style={{ margin: 0, color: '#ea580c', fontWeight: 600 }}>$4.000</p>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot Mar 28, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use consistent currency formatting in suggestions list.

$4.000 is inconsistent with the rest of the page (toLocaleString pattern). Standardize formatting to avoid locale/UX confusion.

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

In `@apps/web/src/app/hotel/`[id]/page.tsx at line 132, The suggestions list
contains a hardcoded price string ("$4.000") in the <p> element; replace it with
the same currency formatting used elsewhere (e.g., call
Number(suggestion.price).toLocaleString(locale, { style: 'currency', currency:
'USD' }) or reuse the app's currency formatter) so values render consistently;
update the JSX that renders the price (the <p style={{ margin: 0, color:
'#ea580c', fontWeight: 600 }}> element) to use the formatted value instead of
the literal "$4.000".

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.

.

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.

@sotoJ24, thanks for the reply! Could you clarify — have you addressed the currency formatting inconsistency, or would you like help implementing the fix? If needed, here's a quick drop-in replacement for the hardcoded $4.000:

<p style={{ margin: 0, color: '#ea580c', fontWeight: 600 }}>
  {new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(4000)}
</p>

Or, if the suggestion cards are eventually driven by real data, you could extract a small helper:

const formatCurrency = (amount: number, locale = 'en-US') =>
  new Intl.NumberFormat(locale, { style: 'currency', currency: 'USD' }).format(amount);

and use it as {formatCurrency(suggestion.price)} in the JSX. This would keep all price displays consistent across the page.

Copy link
Copy Markdown
Contributor

@sotoJ24 sotoJ24 left a comment

Choose a reason for hiding this comment

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

Hello Dear @Obiajulu-gif, could you please make the changes request by coderabbit

@sotoJ24
Copy link
Copy Markdown
Contributor

sotoJ24 commented Mar 30, 2026

Hello Dear @Obiajulu-gif, could you please make the changes request by coderabbit

Also please solve the conflicts of the branch

@Obiajulu-gif
Copy link
Copy Markdown
Contributor Author

@sotoJ24 i have fix the error

Comment on lines +90 to +99
function getStubView(status: string | undefined): ViewConfig {
switch (status) {
case 'blocked':
return { label: 'blocked', step: 3, title: 'Payment batch - Escrow Status' };
case 'released':
return { label: 'released', step: 4, title: 'Deposit / Escrow Released' };
case 'paid':
default:
return { label: 'paid', step: 2, title: 'Payment batch January 2025' };
}
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.

.

Comment on lines +90 to +100
function getStubView(status: string | undefined): ViewConfig {
switch (status) {
case 'blocked':
return { label: 'blocked', step: 3, title: 'Payment batch - Escrow Status' };
case 'released':
return { label: 'released', step: 4, title: 'Deposit / Escrow Released' };
case 'paid':
default:
return { label: 'paid', step: 2, title: 'Payment batch January 2025' };
}
}
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.

.

return (
<div style={{ display: 'grid', gap: '1.5rem' }}>
<div style={styles.splitGrid}>
<InfoPair label="Billed to" value="John_s@gmail.com" />
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.

.

PDF
</button>
</div>
<textarea style={styles.input} placeholder="Justification..." />
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.

.

Comment on lines +21 to +25
owner: {
name: 'Alberto Casas',
email: 'albertoCasas100@gmail.com',
phone: '+506 64852179',
},
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.

.

<p style={{ margin: '0.25rem 0', color: '#78716c' }}>
329 Calle santos, San José
</p>
<p style={{ margin: 0, color: '#ea580c', fontWeight: 600 }}>$4.000</p>
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.

.

Comment on lines +2 to +7
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
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.

.

Comment on lines +3 to +8
eslint: {
ignoreDuringBuilds: true,
},
typescript: {
ignoreBuildErrors: true,
},
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.

.

@Obiajulu-gif Obiajulu-gif force-pushed the feat/escrow-detail-route-placeholder branch from b1240c3 to bd24d6b Compare April 1, 2026 11:59
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx:
- Line 118: The stub currency string passed to InfoPair is incorrect: "IDR -
Dollar" mixes the ISO code for Indonesian Rupiah with "Dollar"; update the stub
to a consistent code/name pair (for example "IDR - Indonesian Rupiah" or "USD -
Dollar") where InfoPair is rendered so the label/value pair is accurate; locate
the usage in page.tsx where InfoPair is invoked for Currency and replace the
value string 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: 0102339a-e616-44b6-9a8e-5761ac46769f

📥 Commits

Reviewing files that changed from the base of the PR and between dcbb680 and bd24d6b.

📒 Files selected for processing (4)
  • apps/web/src/app/hotel/[id]/escrow/[escrowId]/page.tsx
  • apps/web/src/app/hotel/[id]/page.tsx
  • apps/web/src/components/escrow/InvoiceHeader.tsx
  • apps/web/src/components/escrow/ProcessStepper.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/web/src/components/escrow/InvoiceHeader.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/web/src/components/escrow/ProcessStepper.tsx

<InfoPair label="Billed to" value="John_s@gmail.com" />
<InfoPair label="Invoice Number" value="INV4257-09-012" />
<InfoPair label="Billing details" value="John Smith" />
<InfoPair label="Currency" value="IDR - Dollar" />
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

Currency code inconsistency in stub data.

IDR is the ISO code for Indonesian Rupiah, not Dollar (which would be USD). While this is stub data, it could cause confusion if used as a template.

💡 Proposed fix
-        <InfoPair label="Currency" value="IDR - Dollar" />
+        <InfoPair label="Currency" value="USD - US Dollar" />
📝 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
<InfoPair label="Currency" value="IDR - Dollar" />
<InfoPair label="Currency" value="USD - US Dollar" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/hotel/`[id]/escrow/[escrowId]/page.tsx at line 118, The stub
currency string passed to InfoPair is incorrect: "IDR - Dollar" mixes the ISO
code for Indonesian Rupiah with "Dollar"; update the stub to a consistent
code/name pair (for example "IDR - Indonesian Rupiah" or "USD - Dollar") where
InfoPair is rendered so the label/value pair is accurate; locate the usage in
page.tsx where InfoPair is invoked for Currency and replace the value string
accordingly.

Copy link
Copy Markdown
Contributor

@sotoJ24 sotoJ24 left a comment

Choose a reason for hiding this comment

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

Dear @Obiajulu-gif, please fix your pull request so we can merge it

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.

📌feat: scaffold apps/web/src/app/hotel/[id]/escrow/[escrowId]/ waterfall route placeholder

3 participants