feat(intake): residence-type capture + CRM-owned inquiry emails for website cutover
All checks were successful
Build & Push Docker Images / lint (push) Successful in 3m5s
Build & Push Docker Images / build-and-push (push) Successful in 9m17s

Website register-interest form now offers the 3 residence types as a
multi-select; the choice + preferred-contact flow into the CRM inquiry
payload, the inbox detail, and the residential emails.

- inquiry inbox detail surfaces residence type(s), preferred contact,
  type-of-interest, comments (full data capture)
- residential-inquiry emails: client confirmation names the chosen
  villa(s); sales alert converted to the canonical detail-line format
  (uniform with berth/contact) + residence type(s)/preferred contact +
  plain-text part
- website-intake-fields parses residence_types[] + method_of_contact
- contact_form alerts split to their own recipient key
  (contact_notification_recipients)
- Residential Interests section: new residence_type field (schema +
  migration 0099, validators, inline select on the detail)
- contact-form-alert email refactor shipped (interest-alert style)

Tests: website-intake-fields, residential-inquiry templates,
contact-form-alert, residential-interest validators.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L2qc3xZTfif7N4Wq3QDa8X
This commit is contained in:
2026-06-25 20:58:53 +02:00
parent 64a488dc15
commit 866930c943
16 changed files with 469 additions and 126 deletions

View File

@@ -0,0 +1,44 @@
import { describe, expect, it } from 'vitest';
import {
RESIDENCE_TYPES,
createResidentialInterestSchema,
updateResidentialInterestSchema,
} from '@/lib/validators/residential';
describe('residential interest residenceType', () => {
it('accepts a known residence type', () => {
const parsed = createResidentialInterestSchema.parse({
residentialClientId: 'rc_1',
residenceType: 'Two Bedroom Marina Villa',
});
expect(parsed.residenceType).toBe('Two Bedroom Marina Villa');
});
it('coerces empty string to null (inline-select clear)', () => {
const parsed = updateResidentialInterestSchema.parse({ residenceType: '' });
expect(parsed.residenceType).toBeNull();
});
it('accepts explicit null', () => {
const parsed = updateResidentialInterestSchema.parse({ residenceType: null });
expect(parsed.residenceType).toBeNull();
});
it('rejects an unknown residence type', () => {
expect(() =>
createResidentialInterestSchema.parse({
residentialClientId: 'rc_1',
residenceType: 'Penthouse Suite',
}),
).toThrow();
});
it('exposes the three offered unit types', () => {
expect(RESIDENCE_TYPES).toEqual([
'Two Bedroom Marina Villa',
'Four Bedroom Oceanfront Villa',
'Five Bedroom Oceanfront Villa',
]);
});
});