feat(frontend): unify async state handling and complete page metadata - #1483
Merged
pope-h merged 4 commits intoJul 31, 2026
Merged
Conversation
Closes Shelterflex#1440, closes Shelterflex#1441. Async state handling (Shelterflex#1440) ---------------------------- Surfaces migrated from mock data to live APIs each grew their own loading, empty, and error treatment. Adds shared primitives in components/ui/data-state.tsx — LoadingState/LoadingAnnouncer, ErrorState, EmptyState, MoneyValue, plus StatCardSkeleton/ListRowSkeleton — and migrates the dashboards and every money-displaying surface onto them. MoneyValue is the load-bearing piece: a balance rendered from `?? 0` is indistinguishable from a real zero, so it renders a skeleton while loading and an explicit dash when the amount is unknown, and only ever formats a number it was actually given. Inspector earnings and admin analytics both rendered ₦0 on a failed fetch; they now dash out. Error states take a required onRetry and re-run the failed fetch instead of reloading the page. Empty states carry the action that would populate them. Loading is announced via a polite live region, skeletons are aria-hidden, and placeholders mirror the real content's dimensions. lib/__tests__/no-money-fallbacks.test.ts scans the source tree and fails if either a money-from-fallback or a reload-based retry reappears. Page metadata (Shelterflex#1441) --------------------- Only 10 of 84 routes had metadata, with no metadataBase, canonical URLs, or robots exclusions. Adds lib/seo.ts, site-wide defaults with a title template, and per-route metadata for the priority public routes. Property detail pages now build a per-listing title, a description from the listing's own copy, and an absolute OpenGraph image from its first photo, plus Residence JSON-LD carrying the rent as an Offer. The homepage, /properties, and /landlords were client components and so could not export metadata; each is now a server route file rendering a client component. Private and token-addressed routes are excluded by segment layout, with noarchive/nosnippet alongside noindex — for the rating-card routes the token is the only access control, so a cached copy or search snippet would outlive its revocation. app/robots.ts repeats the list at the crawler level. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@nonso7 is attempting to deploy a commit to the pope-h's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@nonso7 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! 🚀 |
…nc-states-and-page-metadata # Conflicts: # frontend/app/dashboard/tenant/page.tsx # frontend/app/dashboard/user/page.tsx
c016cbf resolved the same main-merge via the GitHub UI and produced two build-breaking defects that failed the Frontend (lint, build) job: app/dashboard/user/page.tsx Parsing error: Expected corresponding JSX closing tag for 'LoadingState' — the resolution kept both sides, duplicating the walletError branch and orphaning the tag. app/dashboard/tenant/page.tsx 'Loader2' is not defined — the resolution restored a <Loader2> usage whose import this branch had removed. Both merges share the same parents, so this keeps the resolution in 1c4f7f8 and discards nothing from main.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Async state handling (#1440)
Surfaces migrated from mock data to live APIs each grew their own loading, empty, and error treatment. Adds shared primitives in components/ui/data-state.tsx — LoadingState/LoadingAnnouncer, ErrorState, EmptyState, MoneyValue, plus StatCardSkeleton/ListRowSkeleton — and migrates the dashboards and every money-displaying surface onto them.
MoneyValue is the load-bearing piece: a balance rendered from
?? 0is indistinguishable from a real zero, so it renders a skeleton while loading and an explicit dash when the amount is unknown, and only ever formats a number it was actually given. Inspector earnings and admin analytics both rendered ₦0 on a failed fetch; they now dash out.Error states take a required onRetry and re-run the failed fetch instead of reloading the page. Empty states carry the action that would populate them. Loading is announced via a polite live region, skeletons are aria-hidden, and placeholders mirror the real content's dimensions.
lib/tests/no-money-fallbacks.test.ts scans the source tree and fails if either a money-from-fallback or a reload-based retry reappears.
Page metadata (#1441)
Only 10 of 84 routes had metadata, with no metadataBase, canonical URLs, or robots exclusions. Adds lib/seo.ts, site-wide defaults with a title template, and per-route metadata for the priority public routes.
Property detail pages now build a per-listing title, a description from the listing's own copy, and an absolute OpenGraph image from its first photo, plus Residence JSON-LD carrying the rent as an Offer. The homepage, /properties, and /landlords were client components and so could not export metadata; each is now a server route file rendering a client component.
Private and token-addressed routes are excluded by segment layout, with noarchive/nosnippet alongside noindex — for the rating-card routes the token is the only access control, so a cached copy or search snippet would outlive its revocation. app/robots.ts repeats the list at the crawler level.
Summary
Briefly describe the change. This section is required for CI PR validation.
If this is a contract upgrade, include:
Linked issue (recommended)
Example:
Closes #123Changes
This section is required for CI PR validation.
Contract Upgrade Details (if applicable)
This section is required for CI PR validation if this is a contract upgrade.
Network
New Contract
C...sha256:...G...[link to transaction explorer]Upgrade Governance
Verification Steps
How to test
This section is required for CI PR validation.
Security Considerations
This section is required for CI PR validation.
Screenshots (if UI)
Include before/after screenshots for any UI changes. For new features, show different states (loading, error, success). For responsive changes, include mobile/tablet/desktop views.
Checklist
This section is required for CI PR validation.
Closes #1440
Closes #1441