Skip to content

Implemented changes in ServiceproDetail page and created Provider Statement Page - #106

Merged
Nihalpuse merged 5 commits into
mainfrom
nihal
Dec 19, 2025
Merged

Implemented changes in ServiceproDetail page and created Provider Statement Page#106
Nihalpuse merged 5 commits into
mainfrom
nihal

Conversation

@Nihalpuse

@Nihalpuse Nihalpuse commented Dec 19, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Provider Statement report in Dashboard Reports: date-range, category/subcategory, service pro and group filters, column visibility controls, and CSV download.
    • Service Pro detail: Reports navigation, “View Profile” control and new Send Connection / Archive / Delete modal workflows.
  • UI Improvements

    • Tenant requests and transactions revamped with grid layouts, avatars, centered badges, improved spacing, status indicators, and multi-select/checkbox support.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 19, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Adds a new ProviderStatement component and protected route (/dashboard/reports/statement); updates ServiceProsDetail with report navigation plus Send Connection / Archive / Delete modals; converts tenant UIs to grid layouts and adds multi-select behavior to tenant transactions.

Changes

Cohort / File(s) Summary
Route Registration
src/App.tsx
Registers new /dashboard/reports/statement protected route rendering ProviderStatement.
Provider Statement feature
src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx
New default-export React component implementing provider statement UI: breadcrumb/header, info banner, multi-criteria filters (date range, category/sub-category, service pro, groups), column-visibility modal, client-side filtering over mock data, dynamic grid table rendering, and CSV download with loading state.
Service Pro detail changes
src/pages/Dashboard/features/ServicePros/ServiceProsDetail.tsx
Adds modal states and UIs for Send Connection / Archive / Delete; conditional action menu (Send vs Remove Connection); reworked top detail card and Reports area with navigation to the new statement route; explicit guarded tab rendering.
Tenant requests UI update
src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx
Layout refactor to grid with avatar/name row, centered status badge, adjusted description styling, property badge centering, and relocated view button; container styling updated (background, padding, rounded).
Tenant transactions & selection
src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx
Replaced table with grid header/body; added multi-select state (select all / per-row), checkbox handlers, status variants including Pending with indicator, expanded per-row content (due date, category, property, contact avatar, totals), and updated event handling for checkboxes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Pay extra attention to:
    • ProviderStatement.tsx: dense interactive logic (cascading filters, column visibility/order, CSV generation, simulated loading).
    • ServiceProsDetail.tsx: modal lifecycle, conditional action/menu logic, and navigation wiring to the new route.
    • Tenant components: correctness of select-all / per-row selection and checkbox event propagation after table→grid refactor.
    • src/App.tsx: route protection imports and duplicate route occurrences noted in route tree.

Possibly related PRs

Poem

🐰 I hopped through routes and filters bright,

Columns hide, CSVs take flight,
Modals popped like crunchy treats,
Tenants and pros in tidy fleets,
A little hop, a dashboard delight.

Pre-merge checks and finishing touches

✅ 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 captures the two main changes: updates to ServiceProDetail page and creation of the new ProviderStatement page component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nihal

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (5)
src/pages/Dashboard/features/ServicePros/ServiceProsDetail.tsx (2)

8-9: Duplicate comment.

Line 8 and 9 have the same comment // Mock Data - keyed by Service Pro ID. Remove one of them.

🔎 Proposed fix
 // Mock Data - keyed by Service Pro ID
-// Mock Data - keyed by Service Pro ID
 const SERVICE_PRO_DETAILS: Record<number, any> = {

316-358: Modal accessibility improvements.

Consider adding:

  • role="dialog" and aria-modal="true" to modal containers
  • aria-labelledby pointing to the modal title
  • ESC key handler to close modals
  • Focus trap to keep focus within the modal

This applies to all three modals (Send Connection, Archive, Delete).

src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (3)

40-48: Filter dropdowns lack click-outside-to-close behavior.

Unlike the action menu in ServiceProsDetail.tsx which has a click-outside handler, these filter dropdowns only close when clicking the same filter button again. Consider adding a ref and click-outside listener for better UX.


189-199: Consider preventing all columns from being hidden.

Users can currently hide all columns, leaving an empty table. Consider requiring at least one visible column.

🔎 Proposed fix
 const toggleColumn = (columnId: ColumnId) => {
     setVisibleColumns(prev => {
         if (prev.includes(columnId)) {
+            // Prevent hiding the last column
+            if (prev.length === 1) return prev;
             return prev.filter(id => id !== columnId);
         } else {
             // Maintain order
             const newSet = new Set([...prev, columnId]);
             return ALL_COLUMNS.filter(col => newSet.has(col.id)).map(col => col.id);
         }
     });
 };

507-536: Column modal lacks accessibility attributes.

Add role="dialog", aria-modal="true", aria-labelledby, and consider ESC key handling for accessibility compliance.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4336b31 and 1bbefff.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • src/App.tsx (2 hunks)
  • src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (1 hunks)
  • src/pages/Dashboard/features/ServicePros/ServiceProsDetail.tsx (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (1)
src/pages/basewebsite/resources/sections/resourceIcons.tsx (1)
  • Check (426-433)
🔇 Additional comments (3)
src/pages/Dashboard/features/ServicePros/ServiceProsDetail.tsx (2)

384-390: Archive confirmation lacks actual archive logic.

The "Yes I'm Sure" button only closes the modal without performing the archive operation. Ensure backend integration is planned.


426-431: Delete confirmation lacks actual delete logic.

The Delete button only closes the modal. The warning message mentions removing from maintenance requests and deleting transactions, but no such logic exists.

src/App.tsx (1)

71-71: LGTM!

Import follows the existing pattern for dashboard feature components.

Comment thread src/App.tsx Outdated
Comment on lines +107 to +110
const parseDate = (dateStr: string) => {
if (!dateStr || dateStr === '-') return null;
return new Date(dateStr);
};

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

Date parsing may fail for display format.

new Date("01 Dec 2024") relies on browser-specific parsing. The mock data uses "DD MMM YYYY" format which may not parse consistently across browsers.

🔎 Proposed fix with explicit parsing
 const parseDate = (dateStr: string) => {
     if (!dateStr || dateStr === '-') return null;
-    return new Date(dateStr);
+    // Parse "DD MMM YYYY" format explicitly
+    const parts = dateStr.split(' ');
+    if (parts.length !== 3) return new Date(dateStr);
+    const months: Record<string, number> = {
+        'Jan': 0, 'Feb': 1, 'Mar': 2, 'Apr': 3, 'May': 4, 'Jun': 5,
+        'Jul': 6, 'Aug': 7, 'Sep': 8, 'Oct': 9, 'Nov': 10, 'Dec': 11
+    };
+    const day = parseInt(parts[0], 10);
+    const month = months[parts[1]];
+    const year = parseInt(parts[2], 10);
+    if (month === undefined || isNaN(day) || isNaN(year)) return new Date(dateStr);
+    return new Date(year, month, day);
 };

Comment thread src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx
Comment on lines +456 to +458
<div className="bg-white px-4 py-2 rounded-full text-sm font-medium text-gray-700 cursor-pointer hover:bg-gray-50">
Save Filters
</div>

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

"Save Filters" button has no functionality.

This button renders but has no onClick handler. Either implement filter persistence or remove until ready.

Comment on lines +475 to +479
{activeColumns.map(col => (
<div key={col.id} className={col.hasSort ? "flex items-center gap-1 cursor-pointer" : ""}>
{col.label}
{col.hasSort && <ChevronUp className="w-3 h-3" />}
</div>

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

Sort indicators shown but sorting not implemented.

Columns display ChevronUp sort icons when hasSort: true, but clicking them does nothing. Either implement sorting or remove the icons until ready.

Comment on lines +118 to +127
const [isSendConnectionModalOpen, setIsSendConnectionModalOpen] = useState(false);
const [isArchiveModalOpen, setIsArchiveModalOpen] = useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [isConnected, setIsConnected] = useState(false);
const actionMenuRef = useRef<HTMLDivElement>(null);

const handleSendConnection = () => {
setIsConnected(true);
setIsSendConnectionModalOpen(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.

⚠️ Potential issue | 🟡 Minor

Connection state is ephemeral and email input is unused.

  1. isConnected is local state that resets on page refresh - consider persisting to backend or context.
  2. handleSendConnection doesn't capture/use the email entered in the modal. The email input on lines 333-337 is uncontrolled.
🔎 Proposed fix for controlled email input
 const [isConnected, setIsConnected] = useState(false);
+const [connectionEmail, setConnectionEmail] = useState('');
 const actionMenuRef = useRef<HTMLDivElement>(null);

 const handleSendConnection = () => {
+    // TODO: Send connection request to backend with connectionEmail
+    console.log('Sending connection to:', connectionEmail);
     setIsConnected(true);
     setIsSendConnectionModalOpen(false);
+    setConnectionEmail('');
 };

And update the input:

 <input
     type="email"
     placeholder="Enter email address"
+    value={connectionEmail}
+    onChange={(e) => setConnectionEmail(e.target.value)}
     className="w-full px-4 py-3 rounded-lg border border-gray-200 focus:outline-none focus:border-[#3A6D6C]"
 />

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +255 to +258
{/* View Profile Button */}
<button className="w-full bg-[#C8C8C8] text-gray-800 py-2.5 rounded-full text-sm font-semibold hover:bg-[#b8b8b8] transition-colors shadow-inner">
View Profile
</button>

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

"View Profile" button has no click handler.

The button renders but doesn't navigate or perform any action. Consider adding an onClick handler or removing it until functionality is implemented.

🤖 Prompt for AI Agents
In src/pages/Dashboard/features/ServicePros/ServiceProsDetail.tsx around lines
255 to 258, the "View Profile" button is rendered without any onClick handler so
it performs no action; add an onClick prop that navigates to the pro's profile
(e.g., use react-router's useNavigate to push to `/pros/{id}` or call a provided
openProfile handler) or, if navigation isn't ready, disable/remove the button;
ensure you pass the correct pro id from props/state and keep the existing
styling.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

🧹 Nitpick comments (3)
src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx (1)

33-44: Consider consolidating status color utilities.

A similar getStatusColor pattern exists in src/pages/Dashboard/features/Units/utils.ts. While the status values differ, extracting a generic status-to-color mapper could improve maintainability and reduce duplication across the codebase.

💡 Suggested approach for a shared utility

Create a shared utility in a common location:

// utils/statusColors.ts
export const createStatusColorMapper = (colorMap: Record<string, string>) => {
  return (status: string, defaultColor = 'bg-gray-500') => {
    return colorMap[status.toLowerCase()] || defaultColor;
  };
};

Then use it in this component:

-const getStatusColor = (status: string) => {
-    switch (status.toLowerCase()) {
-        case 'normal':
-            return 'bg-[#7BD747]';
-        case 'urgent':
-            return 'bg-red-500';
-        case 'low':
-            return 'bg-yellow-500';
-        default:
-            return 'bg-gray-500';
-    }
-};
+const getStatusColor = createStatusColorMapper({
+    'normal': 'bg-[#7BD747]',
+    'urgent': 'bg-red-500',
+    'low': 'bg-yellow-500'
+});
src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (2)

58-69: Consider consolidating status color utilities.

Similar to TenantRequestsSection.tsx, this component defines its own getStatusColor function. Multiple components across the codebase follow this pattern (e.g., src/pages/Dashboard/features/Units/utils.ts). A shared utility with configurable color types (text vs. background) would improve maintainability.


119-122: Consider extracting status color logic.

Line 120 duplicates the status-to-color mapping already defined in getStatusColor. While the dot requires background colors and the text requires text colors, this duplication makes maintenance harder. Consider a helper that returns both values.

💡 Suggested approach
const getStatusColors = (status: string) => {
    const colorMap = {
        'Paid': { text: 'text-[#7BD747]', bg: 'bg-[#7BD747]' },
        'Void': { text: 'text-red-500', bg: 'bg-red-500' },
        'Pending': { text: 'text-orange-500', bg: 'bg-orange-500' }
    };
    return colorMap[status] || { text: 'text-gray-500', bg: 'bg-gray-500' };
};

// Usage:
const statusColors = getStatusColors(transaction.status);
<div className={`w-2 h-2 rounded-full ${statusColors.bg}`}></div>
<span className={`text-sm font-medium ${statusColors.text}`}>{transaction.status}</span>
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1bbefff and 86835c3.

📒 Files selected for processing (2)
  • src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx (2 hunks)
  • src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (2)
src/pages/Dashboard/features/Units/utils.ts (1)
  • getStatusColor (6-17)
src/pages/basewebsite/resources/sections/resourceIcons.tsx (1)
  • Check (426-433)
src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx (1)
src/pages/Dashboard/features/Units/utils.ts (1)
  • getStatusColor (6-17)
🔇 Additional comments (5)
src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx (2)

1-1: LGTM! Clean removal of unused import.

The removal of the unused User icon import is good housekeeping and keeps the dependencies minimal.


47-93: Well-structured UI refactoring.

The grid-based layout with responsive spacing and visual styling provides a clean, maintainable structure. The use of Tailwind utilities is appropriate, and the component styling aligns well with the broader dashboard design system mentioned in the PR objectives.

src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (3)

40-56: Well-implemented selection state management.

The multi-select functionality is correctly implemented with proper state management and toggle logic. The handlers appropriately manage both individual and bulk selection operations.


74-99: Well-structured table header with proper accessibility.

The header implementation with select-all functionality is well done. The conditional rendering of the Check icon and the guard condition transactions.length > 0 prevents showing a checked state on an empty list.

Note: The ChevronUp icons suggest sortable columns, but sorting logic is not yet implemented. This is acceptable if sorting is planned for a future iteration.


72-158: Excellent UI restructuring with consistent design patterns.

The grid-based layout successfully mirrors the ServicePro style mentioned in the comments. The implementation demonstrates good attention to detail with:

  • Consistent column definitions between header and body
  • Proper hover states and transitions
  • Clean separation of concerns with dedicated columns
  • Responsive design considerations

The integration of multi-select functionality fits naturally into the new layout.

Comment thread src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 0

♻️ Duplicate comments (3)
src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (3)

107-110: Date parsing may fail for display format.

The parseDate function still relies on new Date(dateStr) for parsing "DD MMM YYYY" format dates (e.g., "01 Dec 2024"), which may not parse consistently across browsers. Consider implementing explicit date parsing as suggested in the previous review.

Does the JavaScript Date constructor reliably parse "DD MMM YYYY" format across all major browsers?

469-471: "Save Filters" button has no functionality.

This button renders with hover effects but has no onClick handler. Either implement filter persistence or remove the button until the functionality is ready.


488-492: Sort indicators shown but sorting not implemented.

Columns display ChevronUp sort icons and cursor-pointer styling when hasSort: true, but clicking them does nothing. Either implement the sorting functionality or remove the visual indicators until ready.

🧹 Nitpick comments (1)
src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (1)

133-136: Consider extracting status dot color logic to avoid duplication.

Line 134 hardcodes the status-to-color mapping for the status indicator dot, while Line 135 reuses the getStatusColor function for text color. Consider creating a helper function for background colors or extending getStatusColor to support both use cases.

🔎 Proposed refactor
+const getStatusBgColor = (status: string) => {
+    switch (status) {
+        case 'Paid':
+            return 'bg-[#7BD747]';
+        case 'Void':
+            return 'bg-red-500';
+        case 'Pending':
+            return 'bg-orange-500';
+        default:
+            return 'bg-gray-500';
+    }
+};

 {/* Status Column */}
 <div className="flex items-center gap-2">
-    <div className={`w-2 h-2 rounded-full ${transaction.status === 'Paid' ? 'bg-[#7BD747]' : transaction.status === 'Pending' ? 'bg-orange-500' : 'bg-red-500'}`}></div>
+    <div className={`w-2 h-2 rounded-full ${getStatusBgColor(transaction.status)}`}></div>
     <span className={`text-sm font-medium ${getStatusColor(transaction.status)}`}>{transaction.status}</span>
 </div>
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 86835c3 and 14299c4.

📒 Files selected for processing (4)
  • src/App.tsx (12 hunks)
  • src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (1 hunks)
  • src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx (2 hunks)
  • src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/pages/Dashboard/features/Tenants/components/TenantRequestsSection.tsx
  • src/App.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (1)
src/pages/Dashboard/features/Units/utils.ts (1)
  • getStatusColor (6-17)
src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (1)
src/pages/basewebsite/resources/sections/resourceIcons.tsx (1)
  • Check (426-433)
🔇 Additional comments (2)
src/pages/Dashboard/features/Tenants/components/TenantTransactionsSection.tsx (1)

71-83: Excellent edge case handling in getInitials helper.

The implementation properly addresses all the edge cases mentioned in the previous review:

  • Returns '?' for empty or falsy names
  • Trims and filters whitespace correctly
  • Handles single-word names by returning the first two characters
  • Handles multi-word names by returning the first character of the first two words

This is a solid implementation that prevents the issues identified earlier.

src/pages/Dashboard/features/ServicePros/ProviderStatement.tsx (1)

148-200: CSV export issues have been properly addressed.

The implementation now correctly:

  1. Exports filteredStatements instead of all statements (Line 171)
  2. Properly escapes CSV fields using escapeCsvField to handle quotes, commas, and newlines (Lines 157-166)
  3. Revokes the object URL after download to prevent memory leaks (Line 196)

All concerns from the previous review have been resolved.

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.

1 participant