fix(uat): batch — timeline overshoot, name-sync, reset-password, dashboard cleanup, queue/seed hygiene + alpha UAT findings doc
UAT findings landed across the last few Playwright + React Grab passes; single grouped commit so the index doesn't fragment into 30 one-liners. User & auth: - `user-settings`: name now updates the avatar + topbar menu after save (was reading stale session). - `me/password-reset`: 3 bugs (token validation, error response shape, redirect chain). - Admin user permission-overrides route honours the same envelope as the rest of the admin surface. Dashboard: - Removed obsolete `revenue-breakdown-chart` + `dashboard-widgets-card` (replaced by the customisable widget grid). - Strip `revenue_breakdown` from analytics route + use-analytics + service + integration test so nothing renders an empty card. - Activity log timeline overshoot fix (`interest-timeline` + `entity-activity-feed`). - Tightened tiles: active-deals, berth-heat-widget, pipeline-value, kpi-tile. - `dev-mode-banner`: derive dismissed state synchronously instead of via an effect (set-state-in-effect lint rule). Forms & lists (assorted polish): - client / company / yacht / interest / reminder forms — validation + empty-state copy + tab transitions. - companies/yachts list tweaks; berth recommender panel; qualification checklist; supplemental info request button. Infra & misc: - Queue workers (ai / email / notifications) — log shape + per-job timeout consistency. - Auth / brochures / users schema small adjustments; seeds reflect permissions matrix changes. - Scan shell + scanner manifest + AI admin page small fixes. - `next.config.transpilePackages` adds `echarts`/`zrender`/`echarts-for-react` (recommended config from echarts-for-react inside Next). Docs: - `docs/superpowers/audits/alpha-uat-master.md` — single rolling cross-cutting UAT findings doc (per CLAUDE.md convention). - `docs/BACKLOG.md`: dashboard stats cards (§I) + activity-log normalization (§J). - 2026-05-18 audit log updated with this batch. - `CLAUDE.md` — small manual UAT scaffold notes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -77,14 +77,40 @@ function buildAuth() {
|
||||
// through the shared SMTP infra so EMAIL_REDIRECT_TO honours it
|
||||
// in dev.
|
||||
sendResetPassword: async ({ user, url }) => {
|
||||
const { sendEmail } = await import('@/lib/email');
|
||||
const subject = 'Reset your Port Nimara CRM password';
|
||||
const html = `
|
||||
<p>Hi ${user.name || 'there'},</p>
|
||||
<p>You requested a password reset for your Port Nimara CRM account.</p>
|
||||
<p><a href="${url}">Click here to set a new password</a> — the link expires in 1 hour.</p>
|
||||
<p>If you didn't request this, you can safely ignore this email.</p>
|
||||
`;
|
||||
const [{ sendEmail }, { renderShell, safeUrl }, { resolveAuthShellBranding }] =
|
||||
await Promise.all([
|
||||
import('@/lib/email'),
|
||||
import('@/lib/email/shell'),
|
||||
import('@/lib/email/auth-shell-branding'),
|
||||
]);
|
||||
|
||||
const branding = await resolveAuthShellBranding();
|
||||
const appName = branding?.appName ?? 'CRM';
|
||||
const subject = `Reset your ${appName} password`;
|
||||
const safeName = (user.name || 'there').replace(/[<>&]/g, '');
|
||||
const body = `
|
||||
<p style="margin-bottom:16px;">Hi ${safeName},</p>
|
||||
<p style="margin-bottom:16px;">You requested a password reset for your ${appName} account.</p>
|
||||
<p style="margin-bottom:16px;">
|
||||
<a href="${safeUrl(url)}" style="color:#2563eb;font-weight:600;">Click here to set a new password</a>
|
||||
— the link expires in 1 hour.
|
||||
</p>
|
||||
<p style="color:#64748b;">If you didn't request this, you can safely ignore this email.</p>
|
||||
`;
|
||||
|
||||
const html = renderShell({
|
||||
title: subject,
|
||||
body,
|
||||
branding: branding
|
||||
? {
|
||||
logoUrl: branding.logoUrl,
|
||||
backgroundUrl: branding.backgroundUrl,
|
||||
primaryColor: null,
|
||||
emailHeaderHtml: null,
|
||||
emailFooterHtml: null,
|
||||
}
|
||||
: null,
|
||||
});
|
||||
const text = `Reset your password: ${url}`;
|
||||
await sendEmail(user.email, subject, html, undefined, text);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user