All files / lib/whatsapp url-utils.ts

100% Statements 16/16
85% Branches 17/20
100% Functions 3/3
100% Lines 16/16

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99      2x                         2x       2x                 13x         19x                                                         16x   16x           16x 16x 16x             16x               16x 16x 16x   16x       16x    
// WhatsApp URL generation utilities
import { normalizeToE164, formatNational } from "@interioring/utils/validation/phone";
 
export const REQUIREMENT_TYPES = {
	modular_kitchen: "Modular Kitchen",
	wardrobes_storage: "Wardrobes & Storage",
	full_home_interior: "Full Home Interior",
	full_office_interior: "Full Office Interior",
	living_room: "Living Room",
	bedroom: "Bedroom",
	pooja_room: "Pooja Room",
	other: "Other",
} as const;
 
export type RequirementType = keyof typeof REQUIREMENT_TYPES;
 
export const VALID_REQUIREMENT_TYPES = Object.keys(
	REQUIREMENT_TYPES,
) as RequirementType[];
 
export const VALID_SOURCE_TYPES = [
	"marketplace",
	"pro_website",
	"chatgpt_app",
] as const;
 
export type SourceType = (typeof VALID_SOURCE_TYPES)[number];
 
export function getRequirementTypeLabel(type: string): string {
	return REQUIREMENT_TYPES[type as RequirementType] ?? type.replace(/_/g, " ");
}
 
/** Strip HTML tags and non-printable chars, keep basic punctuation */
function sanitizeText(input: string): string {
	return input
		.replace(/<[^>]*>/g, "") // strip HTML tags
		.replace(/[^\p{L}\p{N}\s.,!?;:''"()\-/&@#%+₹$€£]/gu, "") // keep letters, digits, whitespace, basic punctuation
		.trim();
}
 
/**
 * Build a WhatsApp redirect URL with pre-filled message.
 * In non-production environments, uses the override number and adds [TEST] prefix.
 */
export function buildWhatsAppRedirectUrl(params: {
	proWhatsapp: string;
	proName: string;
	customerName: string;
	customerPhone: string;
	requirementType?: string;
	requirementDescription?: string;
	environment?: string;
	overrideNumber?: string;
}): string {
	const {
		proWhatsapp,
		proName,
		customerName,
		customerPhone,
		requirementType,
		requirementDescription,
		environment,
		overrideNumber,
	} = params;
 
	const isProduction = environment === "production";
 
	// Use override number in non-production environments. Both inputs go
	// through the canonical parser so any format (E.164, national, formatted)
	// resolves to digits-only-with-country-code for the wa.me URL.
	const rawTarget =
		!isProduction && overrideNumber ? overrideNumber : proWhatsapp;
	const targetE164 = normalizeToE164(rawTarget);
	const phoneWithCountryCode = targetE164
		? targetE164.slice(1) // strip leading "+"
		: rawTarget.replace(/\D/g, ""); // last-resort fallback for malformed legacy data
 
	// Use custom description for "other", otherwise use the label map.
	// Sanitize user-provided text to prevent malicious content.
	const requirementDisplay =
		requirementType === "other" && requirementDescription
			? sanitizeText(requirementDescription)
			: requirementType
				? getRequirementTypeLabel(requirementType)
				: "interior design services";
 
	// Build message — sanitize all user-provided values. Show the customer's
	// phone in human-readable national format inside the message body.
	const safeName = sanitizeText(customerName);
	const customerDisplay = formatNational(customerPhone) || customerPhone;
	const baseMessage = `Hi, I saw your work on Interioring and I'm interested in ${requirementDisplay}. My name is ${safeName}. Could you please call me back on ${customerDisplay}?`;
 
	const message = isProduction
		? baseMessage
		: `[TEST] Pro: ${proName} (${formatNational(proWhatsapp) || proWhatsapp}) | ${baseMessage}`;
 
	return `https://wa.me/${phoneWithCountryCode}?text=${encodeURIComponent(message)}`;
}