feat(eoi): signed-EOI hero + send-signed-copy; fix search dropdown z-order

- EOI tab: when an EOI is already signed and none is in flight, lead with a
  SignedEoiCard (preview + download + send-to-client) instead of the big
  "Generate EOI" empty state; quiet "Generate new EOI" remains for re-issue
- history rows + hero gain a "Send to client" action — POST
  /api/v1/documents/[id]/send-signed-copy emails the deal's client the
  finalized signed PDF (sendSignedCopyToClient reuses sendSigningCompleted),
  guarded by a confirm
- topbar: header gets z-30 so the global search dropdown paints above page
  content (charts/tables were bleeding through — header + main are sibling
  normal-flow boxes, so the dropdown's own z-50 couldn't win cross-context).
  Stays below the z-50 modal tier.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 15:55:28 +02:00
parent 3b227fe9b2
commit d1f6d6a427
4 changed files with 251 additions and 7 deletions

View File

@@ -0,0 +1,21 @@
import { NextResponse } from 'next/server';
import { withAuth, withPermission } from '@/lib/api/helpers';
import { errorResponse } from '@/lib/errors';
import { sendSignedCopyToClient } from '@/lib/services/documents.service';
/**
* Manually (re)send the finalized signed PDF to the deal's client. Backs
* the "Send signed copy to client" affordance on the EOI tab + document
* detail. Same `documents.edit` gate as the reminder endpoint.
*/
export const POST = withAuth(
withPermission('documents', 'edit', async (_req, ctx, params) => {
try {
const result = await sendSignedCopyToClient(params.id!, ctx.portId);
return NextResponse.json({ data: result });
} catch (error) {
return errorResponse(error);
}
}),
);