Skip to content

feat(home): add global wallet navigation and branding#2227

Open
webguru-hypha wants to merge 88 commits into
mainfrom
home-screen-main-pr-2225
Open

feat(home): add global wallet navigation and branding#2227
webguru-hypha wants to merge 88 commits into
mainfrom
home-screen-main-pr-2225

Conversation

@webguru-hypha

@webguru-hypha webguru-hypha commented May 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a global My Wallet entry and dedicated wallet page in the top navigation
  • render the root ecosystem logo / home branding through a connected top bar
  • keep the home navigation aligned with the updated menu structure

Test plan

  • pnpm run format:fix
  • pnpm --filter web check-types

Made with Cursor

Summary by CodeRabbit

  • New Features
    • Added a new “My Wallet” page and linked it from the navigation menu on both mobile and desktop views (with localized labeling when available).
    • Implemented a tabbed “My Wallet” experience with three tabs: Wallet, Transactions, and Rewards to view wallet assets, transaction history, and pending rewards.
    • The wallet UI responds to sign-in status, showing a loading state while user information is fetched and prompting to sign in when needed.

@coderabbitai

coderabbitai Bot commented May 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Too many files!

This PR contains 169 files, which is 19 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: cc2d6149-9d37-4a16-96eb-0ccf057a4b24

📥 Commits

Reviewing files that changed from the base of the PR and between 18e2300 and 02c6a1c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (169)
  • apps/web/src/app/[lang]/dho/[id]/@aside/[tab]/edit-scheduled-item/[itemId]/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/[tab]/edit-signal/[signalSlug]/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/[tab]/new-scheduled-item/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/[tab]/space-configuration/space-configuration-client.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/calendar/default.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/calendar/edit-scheduled-item/[itemId]/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/calendar/new-scheduled-item/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/@aside/calendar/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/@tab/calendar/constants.ts
  • apps/web/src/app/[lang]/dho/[id]/@tab/calendar/default.tsx
  • apps/web/src/app/[lang]/dho/[id]/@tab/calendar/page.tsx
  • apps/web/src/app/[lang]/dho/[id]/_components/navigation-tabs.tsx
  • apps/web/src/app/api/v1/ops/scheduled-items/dispatch-reminders/route.ts
  • apps/web/src/app/api/v1/spaces/[spaceSlug]/coherences/[slug]/task/route.ts
  • apps/web/src/app/api/v1/spaces/[spaceSlug]/scheduled-items/[itemId]/route.ts
  • apps/web/src/app/api/v1/spaces/[spaceSlug]/scheduled-items/route.ts
  • apps/web/src/app/api/v1/spaces/[spaceSlug]/signal-workflow/route.ts
  • apps/web/src/app/api/v1/spaces/configuration/route.ts
  • apps/web/src/app/api/v1/spaces/record/route.ts
  • apps/web/src/components/connected-scheduled-item-form.tsx
  • apps/web/src/lib/dho-calendar-paths.ts
  • apps/web/src/utils/parse-bearer-token.ts
  • packages/chat-server/src/tools/space-screen-navigation.ts
  • packages/core/package.json
  • packages/core/src/client.ts
  • packages/core/src/coherence/__tests__/sanitize-signal-workflow.test.ts
  • packages/core/src/coherence/client/hooks/__tests__/merge-pending-coherence-task-patches.test.ts
  • packages/core/src/coherence/client/hooks/index.ts
  • packages/core/src/coherence/client/hooks/useFindCoherences.ts
  • packages/core/src/coherence/client/hooks/usePatchCoherenceTask.web2.rsc.ts
  • packages/core/src/coherence/client/hooks/useSignalWorkflow.web2.rsc.ts
  • packages/core/src/coherence/client/hooks/useUpdateSignalWorkflow.web2.rsc.ts
  • packages/core/src/coherence/client/index.ts
  • packages/core/src/coherence/server/actions.ts
  • packages/core/src/coherence/server/assert-coherence-space-panel-auth.ts
  • packages/core/src/coherence/server/index.ts
  • packages/core/src/coherence/server/mutations.ts
  • packages/core/src/coherence/server/queries.ts
  • packages/core/src/coherence/server/resolve-coherence-task-patch-context.ts
  • packages/core/src/coherence/server/signal-workflow.ts
  • packages/core/src/coherence/server/web3/get-all-coherences.ts
  • packages/core/src/coherence/server/web3/normalize-coherence.ts
  • packages/core/src/coherence/signal-workflow.ts
  • packages/core/src/coherence/types.ts
  • packages/core/src/coherence/validation.ts
  • packages/core/src/common/pagination.ts
  • packages/core/src/matrix/client/hooks/index.ts
  • packages/core/src/matrix/client/hooks/use-matrix-user-ids-by-person-ids.ts
  • packages/core/src/matrix/server/actions.ts
  • packages/core/src/matrix/server/queries.ts
  • packages/core/src/people/client/hooks/useJwt.ts
  • packages/core/src/schedule/__tests__/calendar-events.test.ts
  • packages/core/src/schedule/__tests__/meeting-url.test.ts
  • packages/core/src/schedule/__tests__/merge-update.test.ts
  • packages/core/src/schedule/__tests__/recurrence.test.ts
  • packages/core/src/schedule/calendar-events.ts
  • packages/core/src/schedule/client/hooks/useScheduledItems.web2.rsc.ts
  • packages/core/src/schedule/client/index.ts
  • packages/core/src/schedule/index.ts
  • packages/core/src/schedule/matrix-link.ts
  • packages/core/src/schedule/meeting-url.ts
  • packages/core/src/schedule/parse-scheduled-item-id.ts
  • packages/core/src/schedule/recurrence-presets.ts
  • packages/core/src/schedule/recurrence.ts
  • packages/core/src/schedule/schedule-from-signal.ts
  • packages/core/src/schedule/scheduled-item-colors.ts
  • packages/core/src/schedule/scheduled-item-types.ts
  • packages/core/src/schedule/server/actions.ts
  • packages/core/src/schedule/server/app-origin.ts
  • packages/core/src/schedule/server/assert-coherence-in-space.ts
  • packages/core/src/schedule/server/index.ts
  • packages/core/src/schedule/server/invitation-dispatch.ts
  • packages/core/src/schedule/server/matrix-link.ts
  • packages/core/src/schedule/server/merge-scheduled-item-update.ts
  • packages/core/src/schedule/server/mutations.ts
  • packages/core/src/schedule/server/queries.ts
  • packages/core/src/schedule/server/recipients.ts
  • packages/core/src/schedule/types.ts
  • packages/core/src/schedule/validation.ts
  • packages/core/src/server.ts
  • packages/core/src/space/client/hooks/index.ts
  • packages/core/src/space/client/hooks/useSpaceMutations.web2.rsc.ts
  • packages/epics/package.json
  • packages/epics/src/coherence/components/coherence-block.tsx
  • packages/epics/src/coherence/components/create-signal-form.tsx
  • packages/epics/src/coherence/components/index.ts
  • packages/epics/src/coherence/components/signal-board-view.tsx
  • packages/epics/src/coherence/components/signal-card-actions.tsx
  • packages/epics/src/coherence/components/signal-card.tsx
  • packages/epics/src/coherence/components/signal-creator-meta.tsx
  • packages/epics/src/coherence/components/signal-drop-placeholder.tsx
  • packages/epics/src/coherence/components/signal-grid.tsx
  • packages/epics/src/coherence/components/signal-linked-calendar-events.tsx
  • packages/epics/src/coherence/components/signal-list-view.tsx
  • packages/epics/src/coherence/components/signal-section.tsx
  • packages/epics/src/coherence/components/signal-swimlane-view.tsx
  • packages/epics/src/coherence/components/signal-tag-badges.tsx
  • packages/epics/src/coherence/components/signal-task-card.tsx
  • packages/epics/src/coherence/components/signal-team-member-picker.tsx
  • packages/epics/src/coherence/components/signal-view-controls.tsx
  • packages/epics/src/coherence/components/signal-workflow-settings.tsx
  • packages/epics/src/coherence/hooks/use-can-manage-signal.ts
  • packages/epics/src/coherence/hooks/use-can-update-signal-tasks.ts
  • packages/epics/src/coherence/hooks/use-signal-creator-meta.ts
  • packages/epics/src/coherence/index.ts
  • packages/epics/src/coherence/lib/__tests__/signal-view-mode.test.ts
  • packages/epics/src/coherence/lib/signal-view-mode.ts
  • packages/epics/src/coherence/lib/signal-workflow-configuration-return.ts
  • packages/epics/src/coherence/utils/signal-dnd-utils.ts
  • packages/epics/src/coherence/utils/signal-due-date.ts
  • packages/epics/src/coherence/utils/signal-priority-styles.ts
  • packages/epics/src/coherence/utils/signal-tag-badge-styles.ts
  • packages/epics/src/coherence/utils/signal-team-access.ts
  • packages/epics/src/common/ai-left-panel.tsx
  • packages/epics/src/common/aside-overlay-close.ts
  • packages/epics/src/common/button-close.tsx
  • packages/epics/src/common/get-dho-space-context-path.spec.ts
  • packages/epics/src/common/get-dho-space-context-path.ts
  • packages/epics/src/common/human-chat-panel/build-space-roster-mention-candidates.ts
  • packages/epics/src/common/human-chat-panel/human-chat-panel-loader.tsx
  • packages/epics/src/common/human-chat-panel/human-chat-panel-members.tsx
  • packages/epics/src/common/human-chat-panel/index.ts
  • packages/epics/src/common/human-right-panel.tsx
  • packages/epics/src/common/space-accent-loader.tsx
  • packages/epics/src/index.ts
  • packages/epics/src/notifications/components/notification-centre-form.tsx
  • packages/epics/src/notifications/hooks/validation.ts
  • packages/epics/src/schedule/components/full-calendar-widget.tsx
  • packages/epics/src/schedule/components/scheduled-item-event-sheet.tsx
  • packages/epics/src/schedule/components/scheduled-item-form-dialog.tsx
  • packages/epics/src/schedule/components/scheduled-item-meeting-actions.tsx
  • packages/epics/src/schedule/components/space-calendar.css
  • packages/epics/src/schedule/components/space-calendar.tsx
  • packages/epics/src/schedule/index.ts
  • packages/epics/src/schedule/utils/__tests__/calendar-view-mode.test.ts
  • packages/epics/src/schedule/utils/all-day-event-range.ts
  • packages/epics/src/schedule/utils/calendar-view-config.ts
  • packages/epics/src/schedule/utils/calendar-view-mode.ts
  • packages/epics/src/schedule/utils/fullcalendar-locale.ts
  • packages/epics/src/schedule/utils/scheduled-item-type-icon.ts
  • packages/epics/src/spaces/components/create-space-form.tsx
  • packages/epics/src/spaces/hooks/index.ts
  • packages/epics/src/spaces/hooks/use-space-members-and-delegates.ts
  • packages/i18n/src/messages/de.json
  • packages/i18n/src/messages/en.json
  • packages/i18n/src/messages/es.json
  • packages/i18n/src/messages/fr.json
  • packages/i18n/src/messages/pt.json
  • packages/notifications/src/actions/dispatch-scheduled-item-invitation.ts
  • packages/notifications/src/actions/notify-scheduled-item-invitation.ts
  • packages/notifications/src/actions/notify-scheduled-item-reminder.ts
  • packages/notifications/src/constants/tags.ts
  • packages/notifications/src/hooks/use-notifications.ts
  • packages/notifications/src/server.ts
  • packages/storage-postgres/migrations/0054_space_scheduled_items.sql
  • packages/storage-postgres/migrations/0055_scheduled_item_recurrence_reminders.sql
  • packages/storage-postgres/migrations/0056_scheduled_item_type_channel_checks.sql
  • packages/storage-postgres/migrations/0057_scheduled_item_booking_type.sql
  • packages/storage-postgres/migrations/0058_scheduled_item_integrity_checks.sql
  • packages/storage-postgres/migrations/0059_signal_task_fields.sql
  • packages/storage-postgres/migrations/0060_scheduled_item_four_types.sql
  • packages/storage-postgres/migrations/0061_schedule_schema_optimize.sql
  • packages/storage-postgres/migrations/0062_scheduled_item_invitations.sql
  • packages/storage-postgres/migrations/0063_reminder_dispatch_date_fields.sql
  • packages/storage-postgres/migrations/meta/_journal.json
  • packages/storage-postgres/src/schema/coherence.ts
  • packages/storage-postgres/src/schema/index.ts
  • packages/storage-postgres/src/schema/space-scheduled-item.ts
  • packages/storage-postgres/src/schema/space.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR adds a new locale-aware My Wallet route with a tabbed wallet interface and wires the page into the app navigation for mobile and desktop menus.

Changes

My Wallet Feature

Layer / File(s) Summary
My Wallet page route
apps/web/src/app/[lang]/my-wallet/page.tsx
Async page component that awaits locale params from Next.js dynamic routing, extracts lang, and renders a Container with "My Wallet" heading and MyWalletTabs component.
MyWalletTabs component implementation
apps/web/src/components/my-wallet-tabs.tsx
Client component with three tab panels for Wallet, Transactions, and Rewards. Uses useAuthentication and useMe hooks to verify user sign-in status and fetch person data. Renders sign-in prompts or loading states, then displays UserAssetsSection, UserTransactionsSection, and PendingRewardsSection with computed basePath derived from lang and person.slug.
Navigation menu wiring and translations
apps/web/src/app/layout.tsx
Adds navMyWalletLabel initialized from Navigation translations, then inserts myWallet nav item linking to /${locale}/my-wallet in both mobile and desktop ConnectedButtonProfile navItems arrays.

Estimated code review effort: 2 (Simple) | ~12 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MyWalletTabs
  participant useAuthentication
  participant useMe
  participant TabSections
  User->>MyWalletTabs: render(lang)
  MyWalletTabs->>useAuthentication: check if signed in
  MyWalletTabs->>useMe: fetch person data
  alt Not authenticated or missing slug
    MyWalletTabs-->>User: show sign-in prompt
  else Loading
    MyWalletTabs-->>User: show Loading...
  else Loaded and authenticated
    MyWalletTabs->>TabSections: render UserAssetsSection, UserTransactionsSection, PendingRewardsSection
    TabSections-->>User: render tabs with wallet content
  end
Loading

Possibly related PRs

  • hypha-dao/hypha-web#1067: Shares the same tabbed wallet section pattern with UserAssetsSection and UserTransactionsSection.
  • hypha-dao/hypha-web#2068: Adjusts header/menu composition in apps/web/src/app/layout.tsx, which overlaps with the navigation changes here.
  • hypha-dao/hypha-web#697: Updates wallet-related navigation entries, similar to the new myWallet menu item in this PR.

Suggested reviewers: evgenibir, sergey3bv

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title is conventional, but the scope 'home' does not reference an affected package or app as required. Use a package/app scope such as 'web' and keep the description aligned, e.g. 'feat(web): add global wallet navigation and branding'.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch home-screen-main-pr-2225

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.

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

🤖 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/`[lang]/my-wallet/page.tsx:
- Around line 9-19: The page heading is hardcoded; import getTranslations from
"next-intl/server" at the top, call it inside MyWalletPage with the locale from
props.params (e.g., const t = getTranslations(lang)), and replace the hardcoded
<h1> text with a translated key like t('myWallet.title'); keep
MyWalletTabs(lang={lang}) as-is and ensure the translation key exists in the
my-wallet namespace/messages.

In `@apps/web/src/app/layout.tsx`:
- Around line 179-182: The tNav('myWallet') call references a missing
translation key; add a "myWallet" entry under the "Navigation" namespace in each
locale file so tNav can resolve it: update packages/i18n/src/messages/en.json,
de.json, es.json, fr.json and pt.json to include "Navigation": { "myWallet":
"<appropriate translated string>" } (use the English text in en.json and correct
translations in the other files) so the navigation label renders correctly in
Layout (tNav usage).

In `@apps/web/src/components/connected-menu-top.tsx`:
- Around line 172-186: The MenuTop consumer is passing logoNode but MenuTopProps
and MenuTop implementation don't accept or render it, which causes no logo when
useReplacementLogoNode is true; update the MenuTop API by adding logoNode?:
ReactNode to the MenuTopProps type and modify the MenuTop component (the MenuTop
function/JSX) to conditionally render the provided logoNode in place of the
default <Logo> when logoNode exists (respecting existing logoHref / hrefTarget
behavior), ensuring prop names (logoNode, logoHref, hrefTarget) are used
consistently and exported in the MenuTop signature so the custom ecosystem logo
supplied by connected-menu-top.tsx will render.
- Around line 55-92: The two useSWR calls (for activeSpace and
organisationSpaces) duplicate the same inline fetch logic; extract a shared
generic fetcher function (e.g., apiJsonNoCacheFetcher<T>(url: string,
contextLabel?: string): Promise<T | null | T[]>) that sets Accept header, uses
cache: 'no-store', checks response.ok, logs a contextual warning (use the
contextLabel like '[ConnectedMenuTop] activeSpace' / '[ConnectedMenuTop]
organisationSpaces'), and returns the parsed JSON cast to T (or a safe default
like null or [] as appropriate). Replace the inline async fetchers in the useSWR
for activeSpace and organisationSpaces with calls to this shared fetcher,
preserving the return type casts and the same null/empty-array fallback
behavior.
- Around line 8-12: The import is failing because getRootSpace is not exported
from `@hypha-platform/epics`; remove getRootSpace from the named import (leave
getDhoSpaceSlugFromPathname and isSafeImageUrl) and either (a) add a local
utility function getRootSpace inside connected-menu-top.tsx with the same
behavior used by this component, or (b) import getRootSpace from the correct
module that actually exports it if one exists; then update all usages of
getRootSpace in this file to reference the new local helper or the corrected
import and run the build to verify the error is resolved.

In `@apps/web/src/components/my-wallet-tabs.tsx`:
- Around line 18-33: Replace all hardcoded user-facing strings in the
MyWalletTabs component with next-intl translation lookups using the provided
lang prop; specifically, import and call the translator (e.g., useTranslations
or intl) in MyWalletTabs and replace "Loading..." with t('loading') (or an
equivalent key), "Sign in to view your wallet." with t('signInToViewWallet'),
and the tab labels "Wallet", "Transactions", "Rewards" with t('tabs.wallet'),
t('tabs.transactions'), t('tabs.rewards') respectively; ensure keys are added to
the relevant locale files and keep the component's logic (isLoading,
isAuthenticated, person?.slug, activeTab, setActiveTab) unchanged while swapping
literal strings for t(...) calls.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 0b9a0e4f-2c85-43b3-9cb8-162810f79250

📥 Commits

Reviewing files that changed from the base of the PR and between 15be14f and 5fbab6f.

📒 Files selected for processing (4)
  • apps/web/src/app/[lang]/my-wallet/page.tsx
  • apps/web/src/app/layout.tsx
  • apps/web/src/components/connected-menu-top.tsx
  • apps/web/src/components/my-wallet-tabs.tsx

Comment on lines +9 to +19
export default async function MyWalletPage(props: PageProps) {
const { lang } = await props.params;

return (
<Container className="flex w-full flex-col gap-4 py-4">
<h1 className="text-7 font-semibold tracking-tight text-foreground">
My Wallet
</h1>
<MyWalletTabs lang={lang} />
</Container>
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Hardcoded "My Wallet" page heading — use getTranslations

The <h1> text is a hardcoded user-facing string. In a Server Component the fix uses getTranslations from next-intl/server.

✏️ Proposed fix
+import { getTranslations } from 'next-intl/server';
 import { Locale } from '@hypha-platform/i18n';
 import { Container } from '@hypha-platform/ui';
 import { MyWalletTabs } from '@web/components/my-wallet-tabs';
 
 type PageProps = {
   params: Promise<{ lang: Locale }>;
 };
 
 export default async function MyWalletPage(props: PageProps) {
   const { lang } = await props.params;
+  const t = await getTranslations('MyWallet');
 
   return (
     <Container className="flex w-full flex-col gap-4 py-4">
-      <h1 className="text-7 font-semibold tracking-tight text-foreground">
-        My Wallet
-      </h1>
+      <h1 className="text-7 font-semibold tracking-tight text-foreground">
+        {t('pageTitle')}
+      </h1>
       <MyWalletTabs lang={lang} />
     </Container>
   );
 }

As per coding guidelines: "next-intl integration for i18n (no hardcoded user-facing strings)".

📝 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
export default async function MyWalletPage(props: PageProps) {
const { lang } = await props.params;
return (
<Container className="flex w-full flex-col gap-4 py-4">
<h1 className="text-7 font-semibold tracking-tight text-foreground">
My Wallet
</h1>
<MyWalletTabs lang={lang} />
</Container>
);
import { getTranslations } from 'next-intl/server';
import { Locale } from '@hypha-platform/i18n';
import { Container } from '@hypha-platform/ui';
import { MyWalletTabs } from '@web/components/my-wallet-tabs';
type PageProps = {
params: Promise<{ lang: Locale }>;
};
export default async function MyWalletPage(props: PageProps) {
const { lang } = await props.params;
const t = await getTranslations('MyWallet');
return (
<Container className="flex w-full flex-col gap-4 py-4">
<h1 className="text-7 font-semibold tracking-tight text-foreground">
{t('pageTitle')}
</h1>
<MyWalletTabs lang={lang} />
</Container>
);
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/app/`[lang]/my-wallet/page.tsx around lines 9 - 19, The page
heading is hardcoded; import getTranslations from "next-intl/server" at the top,
call it inside MyWalletPage with the locale from props.params (e.g., const t =
getTranslations(lang)), and replace the hardcoded <h1> text with a translated
key like t('myWallet.title'); keep MyWalletTabs(lang={lang}) as-is and ensure
the translation key exists in the my-wallet namespace/messages.

Comment thread apps/web/src/app/layout.tsx Outdated
Comment on lines +179 to +182
{
label: tNav('myWallet'),
href: `/${locale}/my-wallet`,
},

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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for 'myWallet' key in all Navigation translation files
rg -n '"myWallet"' --type json

Repository: hypha-dao/hypha-web

Length of output: 45


🏁 Script executed:

# Find translation file locations
fd -e json -e ts -e tsx | grep -i -E '(i18n|intl|locale|translation|message|lang)' | head -20

Repository: hypha-dao/hypha-web

Length of output: 843


🏁 Script executed:

# Check the structure of navigation-related translations
fd -type f \( -name '*nav*' -o -name '*menu*' \) | grep -E '\.(json|ts|tsx)$'

Repository: hypha-dao/hypha-web

Length of output: 234


🏁 Script executed:

# Look for where tNav is defined and how translations are loaded
rg -n "tNav\s*=" --type typescript --type tsx -A 3

Repository: hypha-dao/hypha-web

Length of output: 98


🏁 Script executed:

# Check for any reference to 'myWallet' in the codebase (case-insensitive)
rg -i "myWallet" --type json --type typescript --type tsx -C 2

Repository: hypha-dao/hypha-web

Length of output: 98


🏁 Script executed:

# Search for myWallet in the translation JSON files
grep -r "myWallet" packages/i18n/src/messages/

Repository: hypha-dao/hypha-web

Length of output: 45


🏁 Script executed:

# Check the English translation file structure
cat packages/i18n/src/messages/en.json | head -100

Repository: hypha-dao/hypha-web

Length of output: 4253


🏁 Script executed:

# Check the navigation configuration
cat packages/i18n/src/navigation.ts

Repository: hypha-dao/hypha-web

Length of output: 258


🏁 Script executed:

# Check if myWallet appears anywhere in the en.json file
grep -i "wallet" packages/i18n/src/messages/en.json

Repository: hypha-dao/hypha-web

Length of output: 4175


🏁 Script executed:

# Get the complete Navigation section from en.json
jq '.Navigation' packages/i18n/src/messages/en.json

Repository: hypha-dao/hypha-web

Length of output: 640


🏁 Script executed:

# Check if myWallet is defined elsewhere in the codebase
rg -i "myWallet" --type json

Repository: hypha-dao/hypha-web

Length of output: 45


🏁 Script executed:

# Also check if the layout.tsx file actually exists and has the line we're checking
grep -n "myWallet" apps/web/src/app/layout.tsx

Repository: hypha-dao/hypha-web

Length of output: 126


Add myWallet translation key to the Navigation namespace in all translation files

The tNav('myWallet') call at line 180 references a translation key that doesn't exist in packages/i18n/src/messages/{en,de,es,fr,pt}.json. This will either throw an error or fall back to displaying the raw key string. Add the translation key to the Navigation section of all locale files.

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

In `@apps/web/src/app/layout.tsx` around lines 179 - 182, The tNav('myWallet')
call references a missing translation key; add a "myWallet" entry under the
"Navigation" namespace in each locale file so tNav can resolve it: update
packages/i18n/src/messages/en.json, de.json, es.json, fr.json and pt.json to
include "Navigation": { "myWallet": "<appropriate translated string>" } (use the
English text in en.json and correct translations in the other files) so the
navigation label renders correctly in Layout (tNav usage).

Comment thread apps/web/src/components/connected-menu-top.tsx
Comment on lines +55 to +92
const { data: activeSpace, isLoading: isLoadingActiveSpace } =
useSWR<Space | null>(
activeSpaceSlug ? `/api/v1/spaces/${activeSpaceSlug}` : null,
async (url: string) => {
const response = await fetch(url, {
headers: { Accept: 'application/json' },
cache: 'no-store',
});
if (!response.ok) {
console.warn('[ConnectedMenuTop] spaces fetch failed', {
status: response.status,
url,
});
return null;
}
return (await response.json()) as Space;
},
);
const {
data: organisationSpaces = [],
isLoading: isLoadingOrganisationSpaces,
} = useSWR<Space[]>(
activeSpaceSlug ? `/api/v1/spaces/${activeSpaceSlug}/organisation` : null,
async (url: string) => {
const response = await fetch(url, {
headers: { Accept: 'application/json' },
cache: 'no-store',
});
if (!response.ok) {
console.warn('[ConnectedMenuTop] organisation spaces fetch failed', {
status: response.status,
url,
});
return [];
}
return (await response.json()) as Space[];
},
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Duplicate inline SWR fetchers — extract a shared helper

The two useSWR calls (Lines 55–72 and 73–92) share identical fetch logic: set Accept header, use cache: 'no-store', check response.ok, warn on failure, and cast the result. Extract a single generic fetcher to avoid divergence.

♻️ Proposed refactor
+async function jsonFetcher<T>(url: string, fallback: T): Promise<T> {
+  const response = await fetch(url, {
+    headers: { Accept: 'application/json' },
+    cache: 'no-store',
+  });
+  if (!response.ok) {
+    console.warn('[ConnectedMenuTop] fetch failed', { status: response.status, url });
+    return fallback;
+  }
+  return (await response.json()) as T;
+}
+
 const { data: activeSpace, isLoading: isLoadingActiveSpace } =
   useSWR<Space | null>(
     activeSpaceSlug ? `/api/v1/spaces/${activeSpaceSlug}` : null,
-    async (url: string) => {
-      const response = await fetch(url, {
-        headers: { Accept: 'application/json' },
-        cache: 'no-store',
-      });
-      if (!response.ok) {
-        console.warn('[ConnectedMenuTop] spaces fetch failed', {
-          status: response.status,
-          url,
-        });
-        return null;
-      }
-      return (await response.json()) as Space;
-    },
+    (url: string) => jsonFetcher<Space | null>(url, null),
   );

 const { data: organisationSpaces = [], isLoading: isLoadingOrganisationSpaces } =
   useSWR<Space[]>(
     activeSpaceSlug ? `/api/v1/spaces/${activeSpaceSlug}/organisation` : null,
-    async (url: string) => {
-      const response = await fetch(url, {
-        headers: { Accept: 'application/json' },
-        cache: 'no-store',
-      });
-      if (!response.ok) {
-        console.warn('[ConnectedMenuTop] organisation spaces fetch failed', {
-          status: response.status,
-          url,
-        });
-        return [];
-      }
-      return (await response.json()) as Space[];
-    },
+    (url: string) => jsonFetcher<Space[]>(url, []),
   );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/web/src/components/connected-menu-top.tsx` around lines 55 - 92, The two
useSWR calls (for activeSpace and organisationSpaces) duplicate the same inline
fetch logic; extract a shared generic fetcher function (e.g.,
apiJsonNoCacheFetcher<T>(url: string, contextLabel?: string): Promise<T | null |
T[]>) that sets Accept header, uses cache: 'no-store', checks response.ok, logs
a contextual warning (use the contextLabel like '[ConnectedMenuTop] activeSpace'
/ '[ConnectedMenuTop] organisationSpaces'), and returns the parsed JSON cast to
T (or a safe default like null or [] as appropriate). Replace the inline async
fetchers in the useSWR for activeSpace and organisationSpaces with calls to this
shared fetcher, preserving the return type casts and the same null/empty-array
fallback behavior.

Comment thread apps/web/src/components/connected-menu-top.tsx
Comment on lines +18 to +33
export function MyWalletTabs({ lang }: MyWalletTabsProps) {
const [activeTab, setActiveTab] = React.useState('wallet');
const { isAuthenticated } = useAuthentication();
const { person, isLoading } = useMe();

if (isLoading) {
return <div className="py-4 text-sm text-muted-foreground">Loading...</div>;
}

if (!isAuthenticated || !person?.slug) {
return (
<div className="py-4 text-sm text-muted-foreground">
Sign in to view your wallet.
</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 | 🟠 Major | ⚡ Quick win

Hardcoded user-facing strings — must use next-intl

Every visible string is hardcoded instead of going through next-intl. Per the apps/web/** coding guidelines, there must be no hardcoded user-facing strings.

Affected strings:

  • Line 24: "Loading..."
  • Line 30: "Sign in to view your wallet."
  • Lines 46, 49, 52: "Wallet", "Transactions", "Rewards"
✏️ Proposed fix
+import { useTranslations } from 'next-intl';
 
 export function MyWalletTabs({ lang }: MyWalletTabsProps) {
   const [activeTab, setActiveTab] = React.useState('wallet');
   const { isAuthenticated } = useAuthentication();
   const { person, isLoading } = useMe();
+  const t = useTranslations('MyWallet');
 
   if (isLoading) {
-    return <div className="py-4 text-sm text-muted-foreground">Loading...</div>;
+    return <div className="py-4 text-sm text-muted-foreground">{t('loading')}</div>;
   }
 
   if (!isAuthenticated || !person?.slug) {
     return (
       <div className="py-4 text-sm text-muted-foreground">
-        Sign in to view your wallet.
+        {t('signInPrompt')}
       </div>
     );
   }
   // ...
           <TabsTrigger value="wallet" variant="switch">
-            Wallet
+            {t('tabWallet')}
           </TabsTrigger>
           <TabsTrigger value="transactions" variant="switch">
-            Transactions
+            {t('tabTransactions')}
           </TabsTrigger>
           <TabsTrigger value="rewards" variant="switch">
-            Rewards
+            {t('tabRewards')}
           </TabsTrigger>

As per coding guidelines: "next-intl integration for i18n (no hardcoded user-facing strings)".

Also applies to: 43-54

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

In `@apps/web/src/components/my-wallet-tabs.tsx` around lines 18 - 33, Replace all
hardcoded user-facing strings in the MyWalletTabs component with next-intl
translation lookups using the provided lang prop; specifically, import and call
the translator (e.g., useTranslations or intl) in MyWalletTabs and replace
"Loading..." with t('loading') (or an equivalent key), "Sign in to view your
wallet." with t('signInToViewWallet'), and the tab labels "Wallet",
"Transactions", "Rewards" with t('tabs.wallet'), t('tabs.transactions'),
t('tabs.rewards') respectively; ensure keys are added to the relevant locale
files and keep the component's logic (isLoading, isAuthenticated, person?.slug,
activeTab, setActiveTab) unchanged while swapping literal strings for t(...)
calls.

webguru-hypha pushed a commit that referenced this pull request May 22, 2026
Replace the missing getRootSpace dependency with a local root-space resolver and restore MenuTop logoNode support so connected-menu-top compiles against current UI exports.

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

Caution

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

⚠️ Outside diff range comments (2)
apps/web/src/components/connected-menu-top.tsx (2)

154-158: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't gate the new connected branding behind aiChatEnabled.

This condition turns the new root-space logo path off on every space route whenever AI chat is disabled, so the branding added by this PR disappears in the default flag state. Either make this unconditional for space routes or introduce a dedicated branding flag instead of reusing the AI chat one. As per coding guidelines, "AI chat, Human chat, Coherence, and Space Memory are gated flags — off by default".

🤖 Prompt for 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.

In `@apps/web/src/components/connected-menu-top.tsx` around lines 154 - 158,
Summary: The connected branding is incorrectly gated by aiChatEnabled causing
the root-space logo to be hidden when AI chat is off. Fix: remove aiChatEnabled
from the gating logic so the new branding path is active on space routes
regardless of the AI chat flag—change suppressDefaultLogo to depend only on
isSpaceRoute and keep canRenderSpaceLogoNode using rootSpace,
isLoadingActiveSpace, and isLoadingOrganisationSpaces; alternatively if you
prefer a feature flag, introduce a dedicated enableConnectedBranding boolean and
use that instead of aiChatEnabled in suppressDefaultLogo.

187-189: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use rootTitle for the text fallback.

When a space has no custom logo image, this renders the same generic label for every DHO, so the branding context is lost exactly on the fallback path. Showing rootTitle first keeps the menu identifiable.

💡 Suggested fix
           <span className="relative truncate">
-            {tNavigation('ecosystemLogo')}
+            {rootTitle || tNavigation('ecosystemLogo')}
           </span>
🤖 Prompt for 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.

In `@apps/web/src/components/connected-menu-top.tsx` around lines 187 - 189,
Replace the generic fallback text so the menu shows the space branding: in the
component that renders the span (connected-menu-top, where
tNavigation('ecosystemLogo') is used), render rootTitle first and fall back to
tNavigation('ecosystemLogo') if rootTitle is falsy (e.g. use rootTitle ||
tNavigation('ecosystemLogo')). Update the span content accordingly so the UI
shows the specific rootTitle when no custom logo image exists.
🤖 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/components/connected-menu-top.tsx`:
- Around line 53-62: The helper currently walks up parents using current.parent
or organisationById.get(current.parentId) and then returns the last seen current
even when a parent lookup failed; change the traversal so that if current.parent
is falsy and current.parentId is a number but
organisationById.get(current.parentId) returns undefined (i.e., nextParent is
unresolved), the function returns null instead of falling back to the child;
update the traversal in the block that computes nextParent (the variables
current, nextParent, organisationById, parentId) to detect this incomplete chain
and return null, and adjust the function signature/consumer handling if
necessary to accept a nullable return.

---

Outside diff comments:
In `@apps/web/src/components/connected-menu-top.tsx`:
- Around line 154-158: Summary: The connected branding is incorrectly gated by
aiChatEnabled causing the root-space logo to be hidden when AI chat is off. Fix:
remove aiChatEnabled from the gating logic so the new branding path is active on
space routes regardless of the AI chat flag—change suppressDefaultLogo to depend
only on isSpaceRoute and keep canRenderSpaceLogoNode using rootSpace,
isLoadingActiveSpace, and isLoadingOrganisationSpaces; alternatively if you
prefer a feature flag, introduce a dedicated enableConnectedBranding boolean and
use that instead of aiChatEnabled in suppressDefaultLogo.
- Around line 187-189: Replace the generic fallback text so the menu shows the
space branding: in the component that renders the span (connected-menu-top,
where tNavigation('ecosystemLogo') is used), render rootTitle first and fall
back to tNavigation('ecosystemLogo') if rootTitle is falsy (e.g. use rootTitle
|| tNavigation('ecosystemLogo')). Update the span content accordingly so the UI
shows the specific rootTitle when no custom logo image exists.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 1366ae62-acb0-4f8f-b7e1-ec4c144c1fa6

📥 Commits

Reviewing files that changed from the base of the PR and between 5fbab6f and 0d78883.

📒 Files selected for processing (2)
  • apps/web/src/components/connected-menu-top.tsx
  • packages/ui/src/organisms/menu-top.tsx

Comment thread apps/web/src/components/connected-menu-top.tsx Outdated
@github-actions

github-actions Bot commented May 22, 2026

Copy link
Copy Markdown

🔗 Custom preview URL: https://pr-2227.preview-app.hypha.earth

Add the global wallet entry and root ecosystem branding in the top bar
so the home navigation reflects the new home-screen experience.
@webguru-hypha
webguru-hypha force-pushed the home-screen-main-pr-2225 branch from 22a37a2 to 53a5850 Compare May 27, 2026 17:19
Alex Prate and others added 23 commits May 27, 2026 19:28
Stack toolbar controls and action buttons on narrow viewports, use a
wallet-specific single-column token grid until 720px, and tighten
asset card text wrapping for small screens.

Co-authored-by: Cursor <cursoragent@cursor.com>
Rebase layout onto main's SwrProvider/LocalizedIntlProvider stack while
keeping My Wallet nav links. Use getDhoPathDefaultLanding in asset-card.

Co-authored-by: Cursor <cursoragent@cursor.com>
…Matrix call links

Introduces a full Calendar tab for spaces with FullCalendar UI, scheduled-item CRUD, RRULE recurrence, email/push reminders via OneSignal, and auto-generated Hypha call join links for Matrix-backed calls.

Co-authored-by: Cursor <cursoragent@cursor.com>
The reminder notifier imported core/server and was re-exported through
actions/index, which pulled server-only code into use-send-notifications.
Export it only from notifications/server instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
The calendar route and top tab strip were wired up, but the AI left panel
section nav was missing the Calendar item between Members and Treasury.

Co-authored-by: Cursor <cursoragent@cursor.com>
Harden auth on scheduled-item APIs and server actions, isolate reminder
dispatch failures, validate patches against persisted state, tighten reminder
queries, and improve calendar UX (locale, all-day handling, HTML escaping).

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Add Booking as a scheduled item type, snap times to 15-minute increments, and keep end in sync when start changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Match proposal form validation UX by placing errors under fields and focusing the first invalid input on submit.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move create/edit into ProposalOverlayShell aside routes so outside clicks no longer dismiss the form or discard entered data, matching Signals and proposal flows.

Co-authored-by: Cursor <cursoragent@cursor.com>
Address API pagination shape, validation edge cases, reminder dispatch idempotency, client/server boundaries, and calendar UX issues from PR review.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fix PaginatedResponse import path, Drizzle returning() usage, recurrence preset narrowing, and Prettier formatting.

Co-authored-by: Cursor <cursoragent@cursor.com>
Validate PATCH updates against the merged full record, expand recurrence
with local dtstart to preserve wall-clock times, and add calendar tab
path helper regression coverage.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expand recurring occurrences in the event timezone with floating DTSTART
and tzid, stop emitting UTC Z-suffixed rrule inputs to FullCalendar, and
fix weekly fallback weekday indexing for strict TypeScript.

Co-authored-by: Cursor <cursoragent@cursor.com>
Scroll validation errors within the overlay panel, show a sticky error
banner above Save, validate recurrence-until client-side, and surface
server error messages instead of failing silently.

Co-authored-by: Cursor <cursoragent@cursor.com>
Set datetime-local step to 300 seconds and snap start/end times to
five-minute increments (00, 05, 10, …, 55).

Co-authored-by: Cursor <cursoragent@cursor.com>
Extend coherences with task fields (status, board, due date, assignees) and
space-level workflow config, then replace tag-filter boards with Board,
Swimlane, and List views with drag-and-drop. Signal due dates overlay on
the calendar tab and scheduled items gain an optional coherence_id link.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use Drizzle returning() without column projection, add task field
defaults to create-signal form, guard nullable signal slugs, and run Prettier.

Co-authored-by: Cursor <cursoragent@cursor.com>
Address review feedback on signal task workflow, calendar linkage, and
scheduled-item APIs — including patch semantics, auth, pagination, and
reminder dispatch reliability.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove anchorDate/view useEffects that re-triggered gotoDate on every
datesSet callback. Drive calendar navigation imperatively from controls
and only sync state when the visible range actually changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Swimlane rows now show status columns (mini-Kanban) with drag-and-drop
for status and board. Add status, board category, and due date fields to
create/edit signal forms with i18n hints clarifying board vs type/tags.

Co-authored-by: Cursor <cursoragent@cursor.com>
The create form lives at @aside/[tab]/new-signal, not create-signal.

Co-authored-by: Cursor <cursoragent@cursor.com>
Alex Prate and others added 30 commits July 8, 2026 13:40
Link a configure cog beside the view switcher to space configuration for
status and board editing, and return to the signals tab on close or save
when opened from that entry point.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove the grid view hero image and use the same left priority color bar
as board and list cards for a consistent signal card layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
Persist board/swimlane/list/grid selection in the view query param so users can be linked directly to a specific signals layout, including when returning from workflow settings.

Co-authored-by: Cursor <cursoragent@cursor.com>
Allow flex children to shrink below long join URLs and stack meeting actions in compact mode so footer buttons and hints stay visible.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use inline SVG icons for call, event, meeting, and booking types in month, time grid, and agenda views so narrow cells no longer clip the old accent stripe.

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove uppercase styling so Month, Week, Day, and Agenda match the rest of the app.

Co-authored-by: Cursor <cursoragent@cursor.com>
Set the prev/today/next control group to h-10 so it matches the adjacent calendar icon without extra wrapper padding.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use solid grid lines with vertical day dividers, HH:mm slot labels, and clear Today badges across month, week, day, and agenda views.

Co-authored-by: Cursor <cursoragent@cursor.com>
Expand recurring items into concrete occurrences for the visible range so agenda lists weekly calls, sync month/week/day/agenda to the view query param, and remove the header subtitle.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep the workflow cog inline with view tabs, add horizontal scroll for
priority filters, and defer side-by-side layout until lg breakpoints.
Move task route DB lookups behind core/server and gate useJwt on
isAuthenticated so forms recover after sign-in.
Keep month view only until week/day/agenda are ready, strip view query
params, and remove the redundant double border around the calendar card.
Align task PATCH auth with panel delegates, fetch fresh JWTs per update,
and harden optimistic overlays so stale refetches cannot revert moves.

Co-authored-by: Cursor <cursoragent@cursor.com>
Grid cards already open chat on click, so hide the redundant footer action.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Update the local SWR cache only after task moves and avoid unmounting
the board during background revalidation.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Align signal edit/delete auth with panel interaction instead of author-only
or Matrix signal-team membership checks.

Co-authored-by: Cursor <cursoragent@cursor.com>
Allow creators through panel auth, validate workflow fields only when they
change, pass assigneeIds into edit, and surface validation errors in the form.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the edit-form delete action with soft archive so signals stay recoverable and match the grid card archive behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
…nd cards

Show Unarchive in the edit form and card header when a signal is archived, and remove the redundant grid footer unarchive button.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve Matrix IDs server-side by person id so the public members API can
stay free of Privy subs, then use the full space roster for team management
and @ mentions instead of joined-room members only.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace Matrix room joiners with on-chain members plus validated delegates
for Signal Team management, @ mentions, and the chat Members tab.

Co-authored-by: Cursor <cursoragent@cursor.com>
Surface loading/error states for Matrix ID lookup, list every on-chain member and delegate in manage UI (not just Matrix-linked rows), and remove the unbounded module-level person-id cache.

Co-authored-by: Cursor <cursoragent@cursor.com>
Clear signal/msg URL params and bump the deep-link epoch before leaving coherence mode so the back arrow returns to space chat on the first click.

Co-authored-by: Cursor <cursoragent@cursor.com>
Include on-chain membership in delegate SWR cache keys, reuse personRosterDisplayLabel for sorting, and surface aggregated fetch errors to roster consumers.

Co-authored-by: Cursor <cursoragent@cursor.com>
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