143 lines
3.8 KiB
TypeScript
143 lines
3.8 KiB
TypeScript
import { z } from "zod";
|
|
|
|
export class TValidator {
|
|
/**
|
|
* Validate an empty value
|
|
* @param {string} value - The value to validate
|
|
* @param {string} fieldName - The name of the field for error message
|
|
* @returns {Object} - Validation result object with success and optional error message
|
|
*/
|
|
static validateEmptyValue(value: string, fieldName: string) {
|
|
const schema = z.string().min(1, `${fieldName} cannot be empty`);
|
|
const result = schema.safeParse(value);
|
|
|
|
if (!result.success) {
|
|
return {
|
|
success: false,
|
|
error: `${fieldName} cannot be empty`,
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Validate an email address
|
|
* @param {string} email - The email address to validate
|
|
* @returns {Object} - Validation result object with success and optional error message
|
|
*/
|
|
static validateEmail(email: string) {
|
|
const emptyCheck = this.validateEmptyValue(email, "Email");
|
|
if (!emptyCheck.success) return emptyCheck;
|
|
|
|
const schema = z.string().email("Invalid email address");
|
|
const result = schema.safeParse(email);
|
|
|
|
if (!result.success) {
|
|
return {
|
|
success: false,
|
|
error: "Invalid email address",
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Validate a phone number for Indonesia
|
|
* @param {string} phone - The phone number to validate
|
|
* @returns {Object} - Validation result object with success and optional error message
|
|
*/
|
|
static validatePhone(phone: string) {
|
|
const emptyCheck = this.validateEmptyValue(phone, "Phone");
|
|
if (!emptyCheck.success) return emptyCheck;
|
|
|
|
// Regex for Indonesian phone numbers:
|
|
// - Allows format starting with +62 or 0
|
|
// - For +62 format: +62 followed by 8-12 digits
|
|
// - For 0 format: 0 followed by 9-12 digits (usually starts with 08)
|
|
// - Handles common mobile prefixes (8xx) and landline prefixes
|
|
const schema = z
|
|
.string()
|
|
.regex(
|
|
/^(?:\+62[0-9]{8,12}|0[0-9]{9,12})$/,
|
|
"Invalid Indonesian phone number format"
|
|
);
|
|
const result = schema.safeParse(phone);
|
|
|
|
if (!result.success) {
|
|
return {
|
|
success: false,
|
|
error:
|
|
"Invalid Indonesian phone number format. Use format +62xxxxxxxxxx or 08xxxxxxxxx",
|
|
};
|
|
}
|
|
|
|
return {
|
|
success: true,
|
|
};
|
|
}
|
|
/**
|
|
* Validate the contact form
|
|
* @param {Object} formData - The form data to validate
|
|
* @returns {Object} - Validation result with success flag and errors object
|
|
*/
|
|
static validateContactForm(formData: {
|
|
name: string;
|
|
email: string;
|
|
phone: string;
|
|
typeMessage: string;
|
|
message: string;
|
|
}) {
|
|
const errors: Record<string, string> = {};
|
|
let isValid = true;
|
|
|
|
// Validate name
|
|
const nameResult = this.validateEmptyValue(formData.name, "Name");
|
|
if (!nameResult.success) {
|
|
errors.name = nameResult.error!;
|
|
isValid = false;
|
|
}
|
|
|
|
// Validate email
|
|
const emailResult = this.validateEmail(formData.email);
|
|
if (!emailResult.success) {
|
|
errors.email = emailResult.error!;
|
|
isValid = false;
|
|
}
|
|
|
|
// Validate phone
|
|
const phoneResult = this.validatePhone(formData.phone);
|
|
if (!phoneResult.success) {
|
|
errors.phone = phoneResult.error!;
|
|
isValid = false;
|
|
}
|
|
|
|
// Validate type message
|
|
const typeMessageResult = this.validateEmptyValue(
|
|
formData.typeMessage,
|
|
"Type message"
|
|
);
|
|
if (!typeMessageResult.success) {
|
|
errors.typeMessage = typeMessageResult.error!;
|
|
isValid = false;
|
|
}
|
|
|
|
// Validate message
|
|
const messageResult = this.validateEmptyValue(formData.message, "Message");
|
|
if (!messageResult.success) {
|
|
errors.message = messageResult.error!;
|
|
isValid = false;
|
|
}
|
|
|
|
return {
|
|
success: isValid,
|
|
errors: isValid ? {} : errors,
|
|
};
|
|
}
|
|
}
|