feat(FN-1888): add mobile-ready MailboxView with agents load and styles

- Load agents on mount for compose from any MailboxView tab
- Add .mailbox-view base styles for full-page layout
- Add .mailbox-view mobile overrides with safe-area-inset handling
- Add MailboxView test coverage for compose from inbox with agents
This commit is contained in:
Fusion
2026-04-16 05:56:17 -07:00
committed by gsxdsm
parent 7e05e8962f
commit fdaf1cacfe
3 changed files with 132 additions and 0 deletions

View File

@@ -220,6 +220,11 @@ export function MailboxView({
refreshUnreadCount();
}, [refreshUnreadCount]);
// Load agents on mount so they're available for compose from any tab (not just agents tab)
useEffect(() => {
loadAgents();
}, [loadAgents]);
// ── Actions ───────────────────────────────────────────────────────────
const handleOpenMessage = useCallback(async (message: Message) => {

View File

@@ -445,4 +445,38 @@ describe("MailboxView", () => {
expect(onUnreadCountChange).toHaveBeenCalledWith(5);
});
});
it("shows MessageComposer with agents when clicking compose FAB from inbox tab", async () => {
mockFetchInbox.mockResolvedValue({
messages: [],
unreadCount: 0,
});
render(<MailboxView {...defaultProps} />);
// Verify compose FAB is visible in inbox tab
await waitFor(() => {
expect(screen.getByTestId("mailbox-compose-fab")).toBeDefined();
});
// Click compose FAB
await act(async () => {
fireEvent.click(screen.getByTestId("mailbox-compose-fab"));
});
// Verify MessageComposer is shown
await waitFor(() => {
expect(screen.getByTestId("message-composer")).toBeDefined();
});
// Verify agents are available (not "No agents available")
// The select should have agents as options, not just the placeholder
const recipientSelect = screen.getByTestId("message-composer-recipient");
expect(recipientSelect).toBeDefined();
// Should have agents option, not just "No agents available" placeholder
expect(screen.queryByText("No agents available")).toBeNull();
// Should show the mock agents
expect(screen.getByText("Test Agent 1")).toBeDefined();
expect(screen.getByText("Test Agent 2")).toBeDefined();
});
});

View File

@@ -26819,6 +26819,28 @@ html .column.drag-over * {
width: 80%;
}
/* ── Mailbox View (full-page) ──────────────────────────────────────── */
.mailbox-view {
display: flex;
flex-direction: column;
height: 100%;
overflow: hidden;
}
.mailbox-view .mailbox-header {
padding: var(--space-lg) 20px;
border-bottom: 1px solid var(--border);
background: var(--surface);
}
.mailbox-view .mailbox-content {
flex: 1;
overflow-y: auto;
padding: 20px;
max-height: none;
}
/* ── Mailbox — Mobile (≤ 768px) ───────────────────────────────────── */
@media (max-width: 768px) {
@@ -26891,6 +26913,77 @@ html .column.drag-over * {
.mailbox-modal .mailbox-empty {
padding: 32px 12px;
}
/* Mailbox View (full-page) mobile overrides */
.mailbox-view .mailbox-header {
flex-wrap: wrap;
gap: 8px;
}
.mailbox-view .mailbox-title {
flex-shrink: 0;
}
.mailbox-view .mailbox-header-actions {
flex-wrap: wrap;
gap: 6px;
}
.mailbox-view .mailbox-tabs {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
}
.mailbox-view .mailbox-tabs::-webkit-scrollbar {
display: none;
}
.mailbox-view .mailbox-tab {
flex-shrink: 0;
padding: 8px 12px;
font-size: 0.8rem;
}
.mailbox-view .mailbox-content {
padding: var(--space-md);
max-height: none;
}
.mailbox-view .mailbox-message-detail-header {
flex-direction: column;
align-items: flex-start;
}
.mailbox-view .mailbox-message-detail-actions {
flex-wrap: wrap;
}
.mailbox-view .mailbox-message-participants {
flex-direction: column;
gap: 8px;
}
.mailbox-view .mailbox-conversation-msg {
padding: 6px 10px;
}
.mailbox-view .mailbox-agent-select {
max-width: 100%;
}
.mailbox-view .mailbox-agents {
min-height: 200px;
}
.mailbox-view .mailbox-compose-fab {
bottom: calc(16px + var(--mobile-nav-height, 44px) + env(safe-area-inset-bottom, 0px));
right: 16px;
}
.mailbox-view .mailbox-empty {
padding: 32px 12px;
}
}
/* ── Message Composer ──────────────────────────────────────────────── */