File size: 2,715 Bytes
5c876be
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * Input validation utilities.
 */

/**
 * Validate Indian phone numbers.
 *
 * Accepts formats:
 *   - +91XXXXXXXXXX
 *   - 91XXXXXXXXXX
 *   - XXXXXXXXXXX (10 digits, first digit 6-9)
 *
 * @returns true if the phone number is valid for India
 */
export function isValidPhone(phone: string): boolean {
  if (!phone || typeof phone !== 'string') return false;

  const cleaned = phone.replace(/[\s\-()]/g, '');

  // 10-digit Indian mobile (starts with 6-9)
  const tenDigit = /^[6-9]\d{9}$/;
  // With country code prefix
  const withCountryCode = /^(\+91|91)[6-9]\d{9}$/;

  return tenDigit.test(cleaned) || withCountryCode.test(cleaned);
}

/**
 * Validate email address format.
 *
 * Uses a practical regex that covers the vast majority of valid emails
 * without being overly permissive.
 */
export function isValidEmail(email: string): boolean {
  if (!email || typeof email !== 'string') return false;

  // RFC 5322 simplified – practical for real-world use
  const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;

  return emailRegex.test(email.trim());
}

/**
 * Validate Indian vehicle registration number.
 *
 * Accepts formats:
 *   - KA-01-AB-1234  (standard with dashes)
 *   - KA01AB1234      (compact / no separators)
 *   - KA 01 AB 1234   (spaces)
 *
 * Supports both old (2-digit) and new (3-letter + 4-digit) formats:
 *   - KA-01-AB-1234
 *   - KA-01-ABC-1234
 *
 * @returns true if the vehicle number matches Indian format
 */
export function isValidVehicleNumber(num: string): boolean {
  if (!num || typeof num !== 'string') return false;

  const cleaned = num.replace(/[\s\-]/g, '').toUpperCase();

  // State code (2 letters) + District (1-3 digits) + Series (1-3 letters) + Number (1-4 digits)
  const regex = /^[A-Z]{2}[0-9]{1,3}[A-Z]{1,3}[0-9]{1,4}$/;

  return regex.test(cleaned);
}

/**
 * Validate that a string is not empty after trimming.
 */
export function isNotEmpty(value: string | null | undefined): boolean {
  return typeof value === 'string' && value.trim().length > 0;
}

/**
 * Validate Indian PIN code.
 *
 * @returns true if the PIN code is a valid 6-digit Indian postal code
 */
export function isValidPinCode(pin: string): boolean {
  if (!pin || typeof pin !== 'string') return false;
  return /^[1-9][0-9]{5}$/.test(pin.trim());
}

/**
 * Validate display name: 2-50 characters, letters, spaces, dots, hyphens.
 */
export function isValidDisplayName(name: string): boolean {
  if (!name || typeof name !== 'string') return false;
  const trimmed = name.trim();
  return trimmed.length >= 2 && trimmed.length <= 50 && /^[a-zA-Z\s.\-']+$/.test(trimmed);
}