feat(intake): residence-type capture + CRM-owned inquiry emails for website cutover
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:
44
tests/unit/validators/residential-interest.test.ts
Normal file
44
tests/unit/validators/residential-interest.test.ts
Normal 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',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user