161 lines
3.5 KiB
TypeScript
161 lines
3.5 KiB
TypeScript
import { recordSchema, type Profile } from "./contracts";
|
|
|
|
function field(profile: Profile | null, keys: readonly string[], depth = 0): string {
|
|
if (!profile || depth > 3) {
|
|
return "";
|
|
}
|
|
for (const key of keys) {
|
|
const value = profile[key];
|
|
if (typeof value === "string" && value.trim()) {
|
|
return value.trim();
|
|
}
|
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
return String(value);
|
|
}
|
|
}
|
|
for (const key of ["user", "customer", "profile", "contact"]) {
|
|
const nested = recordSchema.safeParse(profile[key]);
|
|
if (nested.success) {
|
|
const value = field(nested.data, keys, depth + 1);
|
|
if (value) {
|
|
return value;
|
|
}
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
const FIELDS = [
|
|
{
|
|
label: "Correo electrónico",
|
|
keys: [
|
|
"email",
|
|
"emailAddress",
|
|
"email_address",
|
|
"eMail",
|
|
"mail",
|
|
"contactEmail",
|
|
"user_email",
|
|
"customer_email",
|
|
"loginEmail",
|
|
"username_email",
|
|
],
|
|
kind: "email",
|
|
},
|
|
{
|
|
label: "Teléfono",
|
|
keys: [
|
|
"phone",
|
|
"phoneNumber",
|
|
"phone_number",
|
|
"mobile",
|
|
"mobileNumber",
|
|
"telephone",
|
|
"tel",
|
|
"cellphone",
|
|
"contactPhone",
|
|
"user_phone",
|
|
"whatsapp",
|
|
],
|
|
kind: "phone",
|
|
},
|
|
{
|
|
label: "Nombre de usuario",
|
|
keys: ["username", "userName", "user_name", "login", "handle", "nickname", "screenName", "accountName"],
|
|
},
|
|
{
|
|
label: "Rol / Plan",
|
|
keys: ["role", "roleName", "userRole", "plan", "planName", "tier", "subscription", "membership", "accessLevel"],
|
|
},
|
|
{
|
|
label: "Empresa",
|
|
keys: ["company", "companyName", "company_name", "organization", "org", "organizationName", "business"],
|
|
},
|
|
{
|
|
label: "ID de usuario",
|
|
keys: [
|
|
"userId",
|
|
"user_id",
|
|
"uid",
|
|
"accountId",
|
|
"account_id",
|
|
"sub",
|
|
"customerId",
|
|
"customer_id",
|
|
"id",
|
|
"userPk",
|
|
"profileId",
|
|
"profile_id",
|
|
"identityId",
|
|
],
|
|
},
|
|
{
|
|
label: "País / Idioma",
|
|
keys: [
|
|
"country",
|
|
"countryName",
|
|
"country_code",
|
|
"countryCode",
|
|
"locale",
|
|
"language",
|
|
"lang",
|
|
"region",
|
|
"timezone",
|
|
"tz",
|
|
],
|
|
},
|
|
{
|
|
label: "Fecha de registro",
|
|
keys: [
|
|
"createdAt",
|
|
"created_at",
|
|
"created",
|
|
"createdDate",
|
|
"created_date",
|
|
"signUpDate",
|
|
"signup_date",
|
|
"joined",
|
|
"joinDate",
|
|
"join_date",
|
|
"registrationDate",
|
|
],
|
|
kind: "date",
|
|
},
|
|
{
|
|
label: "Último acceso",
|
|
keys: [
|
|
"lastLogin",
|
|
"last_login",
|
|
"lastLoginAt",
|
|
"lastActive",
|
|
"last_active",
|
|
"lastActiveAt",
|
|
"updatedAt",
|
|
"updated_at",
|
|
],
|
|
kind: "date",
|
|
},
|
|
] satisfies { label: string; keys: string[]; kind?: string }[];
|
|
|
|
export function profileRows(profile: Profile | null) {
|
|
return FIELDS.flatMap(({ label, keys, kind }) => {
|
|
let value = field(profile, keys);
|
|
if (!value) {
|
|
return [];
|
|
}
|
|
if (kind === "date") {
|
|
const timestamp = /^\d{10,13}$/.test(value) ? Number(value) * (value.length <= 10 ? 1000 : 1) : value;
|
|
const date = new Date(timestamp);
|
|
if (!Number.isNaN(date.getTime())) {
|
|
value = new Intl.DateTimeFormat("es-CL", {
|
|
timeZone: "America/Santiago",
|
|
dateStyle: "medium",
|
|
timeStyle: "short",
|
|
}).format(date);
|
|
}
|
|
}
|
|
const href =
|
|
kind === "email" ? `mailto:${value}` : kind === "phone" ? `tel:${value.replace(/[^\d+]/g, "")}` : undefined;
|
|
return [{ label, value, href }];
|
|
});
|
|
}
|