Skip to content

fix(web): use real discovery data and owner-aware store pages#350

Merged
onerandomdevv merged 2 commits into
devfrom
fix/web-real-discovery-owner-store-pages
Jun 2, 2026
Merged

fix(web): use real discovery data and owner-aware store pages#350
onerandomdevv merged 2 commits into
devfrom
fix/web-real-discovery-owner-store-pages

Conversation

@onerandomdevv
Copy link
Copy Markdown
Collaborator

@onerandomdevv onerandomdevv commented Jun 2, 2026

What does this PR do?

This PR removes hardcoded discovery/sidebar data from the public store surfaces and wires the web app to real backend feed/search endpoints. It adds the public /search page, updates store directory/detail/feed links to use canonical /stores/:handle routes, and makes the public store page owner-aware so store owners see edit/add/dashboard actions while public viewers continue to see the public Follow action.

Type of change

  • New feature
  • Bug fix
  • Refactor / cleanup
  • Database migration included
  • Chore / maintenance
  • Documentation

Area affected

  • Backend
  • Web
  • WhatsApp
  • Shared package
  • Database / Prisma
  • GitHub / CI / infrastructure

How to test this

  1. Visit /stores and confirm it loads from GET /feed/stores?limit=24 or shows a clean empty/error state.
  2. Visit /stores/test-handle and confirm it renders public store data or a clean unavailable/not-found state; store owners should see Edit profile, Add product, and Dashboard instead of Follow.
  3. Visit /search and /search?q=test and confirm results come from GET /search?q=...&type=all&limit=12 with no fake stores/products.
  4. Check the right panel and feed cards for canonical /stores/:handle links and no generated /@handle links.

Expected result: public discovery surfaces use backend data, hardcoded trending hashtags are removed, store handles display without a visible @ prefix in touched surfaces, and owner-specific actions appear only when the current viewer owns the public store.

Pre-commit checklist

  • Backend lint/type/build pass when backend is affected
  • Web lint/type/build pass when web is affected
  • Shared package build passes when shared is affected
  • No console.log left in production code
  • No secrets or .env files committed
  • No new any types added
  • No non-MVP legacy features reintroduced
  • All money values are BigInt kobo, never float
  • Paystack webhook changes verify HMAC before processing
  • Database migrations are Prisma migrations, not db push
  • Database migrations are backward-compatible or risk is documented

Screenshots

N/A. UI behavior changed but no local browser smoke was run in this split worktree.

Notes for reviewer

Backend endpoints used: GET /feed/stores?limit=24, GET /feed/stores?limit=3, GET /feed/explore?limit=12, and GET /search?q=...&type=all&limit=12. Product detail links were already canonical and QuickBuySheet already matches the current /checkout/[productId]?code=... contract, so they were intentionally left unchanged. The owner-aware public store page only uses the public store payload for rendering public store data; private owner-store data such as bank details, internal address, Paystack recipient data, and internal verification fields are not exposed.

Validation:

  • pnpm.cmd run lint: passed, with existing warning in src/app/(store)/store/settings/StoreSettingsClient.tsx about a missing load dependency.
  • npx.cmd tsc --noEmit: passed.
  • pnpm.cmd run build: passed, with the same existing store settings hook warning.

Summary by CodeRabbit

  • New Features

    • Added public search page to discover stores and products with query support
    • Right panel now displays recommended stores and trending hashtags
    • Store pages show owner-specific management options for store owners
  • Improvements

    • Standardized store handle display format across the app
    • Simplified store header buttons and removed unnecessary actions

@codesandbox
Copy link
Copy Markdown

codesandbox Bot commented Jun 2, 2026

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

Warning

Review limit reached

@onerandomdevv, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 4 minutes and 14 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 49d9c90b-4b02-46f3-9c5c-6ebd63298f21

📥 Commits

Reviewing files that changed from the base of the PR and between 7ee4cbd and 9237178.

📒 Files selected for processing (6)
  • .github/workflows/neon_workflow.yml
  • apps/web/src/app/(public)/search/page.tsx
  • apps/web/src/app/(public)/stores/[handle]/StorePageClient.tsx
  • apps/web/src/app/(public)/stores/page.tsx
  • apps/web/src/components/feed/FeedCard.tsx
  • apps/web/src/components/layout/RightPanel.tsx
📝 Walkthrough

Walkthrough

This PR introduces public search functionality for stores and products, standardizes handle display across discovery surfaces, adds ownership-based branching on store detail pages, and transforms the right sidebar from static content to a dynamic API-driven discovery panel with search integration.

Changes

Public Discovery & Store Management Features

Layer / File(s) Summary
Handle Normalization & Public Store Routing
src/components/feed/FeedCard.tsx, src/app/(public)/stores/page.tsx, src/app/(public)/stores/[handle]/StorePageClient.tsx
Introduces formatVisibleHandle helper to normalize displayed handles by stripping @ characters and trimming whitespace. Updates store discovery cards and store detail pages to use getPublicStoreHref instead of hardcoded paths for consistent public store link generation.
Public Search Page & Results
src/app/(public)/search/page.tsx
New search page implements public search for stores and products. Fetches from NEXT_PUBLIC_API_URL with strict runtime validation/normalization. Renders StoreSearchCard and ProductSearchCard with conditional linking, logo/image fallbacks, and formatted pricing. Includes metadata, error states with retry links, and empty results UI.
Store Page Ownership Detection & Owner Actions
src/app/(public)/stores/[handle]/StorePageClient.tsx
Uses useOwnerStore and useOwnProfile hooks to detect whether the logged-in user owns the viewed store. Introduces OwnerStoreActions component with links to edit profile, add product, and store dashboard for owner-owned stores. Dynamically configures AppShell mode, navigation, and panel visibility based on ownership state.
Store Page Header & Empty State Simplification
src/app/(public)/stores/[handle]/StorePageClient.tsx
Removes "Message store" and "Subscribe to store updates" icon buttons, keeping only "View store information" button. Normalizes store handle display to strip @ characters. Changes "gists" tab empty state icon from MessageCircle to Info.
RightPanel Dynamic Discovery Panel
src/components/layout/RightPanel.tsx
Converts right sidebar from static markup to live discovery panel. Fetches recommended stores and trending hashtags on mount with concurrent API calls. Adds controlled search input with submit handler navigating to /search?q=.... Renders fetched stores/hashtags with normalized handles and link generation; shows placeholder cards while loading. Formats post counts using Intl.NumberFormat.

Sequence Diagrams

sequenceDiagram
  participant SearchPage
  participant API
  participant Validator
  participant UI
  SearchPage->>API: GET /search?q=query
  API-->>SearchPage: response with stores/products
  SearchPage->>Validator: validate and normalize response
  Validator-->>SearchPage: typed stores[] and products[]
  SearchPage->>UI: render StoreSearchCard/ProductSearchCard
  UI-->>SearchPage: linked cards with metadata
Loading
flowchart TD
  StorePageClient[StorePageClient loads]
  StorePageClient-->OwnerCheck{useOwnerStore checks<br/>ownership}
  OwnerCheck-->|is owner|OwnerConfig["AppShell mode=edit<br/>OwnerStoreActions<br/>profile fields shown"]
  OwnerCheck-->|not owner|GuestConfig["AppShell mode=view<br/>Follow button<br/>public store data"]
  OwnerConfig-->Render["Render store page"]
  GuestConfig-->Render
Loading
sequenceDiagram
  participant RightPanel
  participant APIFetch
  participant State
  participant Render
  RightPanel->>APIFetch: fetch stores + hashtags on mount
  APIFetch-->>State: update stores[] and hashtags[]
  State->>Render: render store cards with getPublicStoreHref
  State->>Render: render hashtag links to /search?q=hashtag
  Render-->>RightPanel: display discovery panel + search input
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • coded-devs/twizrr#308: Backend SearchModule adds the GET /search API endpoint that the new public search page consumes and validates.
  • coded-devs/twizrr#347: Introduces StoreShell owner-state gating and canonical store handle cleanup, directly aligned with this PR's ownership detection and handle normalization on store pages.
  • coded-devs/twizrr#346: Introduces lib/routes.ts with getPublicStoreHref routing helper that this PR adopts across search, stores, and discovery components.

Poem

🐰 A search for stores shines bright,
Discovery panels fetch with delight!
Owners now branch their own way,
Handles cleaned—no @ on display.
Public discovery blooms, hooray! 🌟

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.57% 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
Title check ✅ Passed The title clearly and concisely summarizes the main changes: replacing hardcoded discovery data with real backend data and making store pages owner-aware.
Description check ✅ Passed The description follows the template with all key sections completed: clear explanation of changes, correct type of change selected, affected area marked, detailed testing instructions, pre-commit checklist mostly completed, and notes for reviewer provided.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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 fix/web-real-discovery-owner-store-pages

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/app/`(public)/search/page.tsx:
- Around line 80-89: Remove the local formatPrice function and swap all its
usages to the shared utility formatKobo: delete the function named formatPrice
in page.tsx and replace any occurrences like
{formatPrice(product.retailPriceKobo)} with
{formatKobo(product.retailPriceKobo)}; ensure you import formatKobo from the
shared utils (apps/web/src/lib/utils.ts) at the top of the file if not already
imported and keep the existing fallback behavior provided by formatKobo.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8f6d3471-ac9e-4fbf-a736-b6575de15f1f

📥 Commits

Reviewing files that changed from the base of the PR and between de9e8d7 and 7ee4cbd.

📒 Files selected for processing (5)
  • apps/web/src/app/(public)/search/page.tsx
  • apps/web/src/app/(public)/stores/[handle]/StorePageClient.tsx
  • apps/web/src/app/(public)/stores/page.tsx
  • apps/web/src/components/feed/FeedCard.tsx
  • apps/web/src/components/layout/RightPanel.tsx

Comment thread apps/web/src/app/(public)/search/page.tsx Outdated
@onerandomdevv onerandomdevv force-pushed the fix/web-real-discovery-owner-store-pages branch from 7ee4cbd to 17abeda Compare June 2, 2026 05:59
@onerandomdevv onerandomdevv merged commit f107d5e into dev Jun 2, 2026
8 checks passed
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