@acrsolutions/chat-components
Version:
Un set di componenti per la creazione di un'applicazione di messaggistica
197 lines (196 loc) • 8 kB
JavaScript
import { always, filter, map, pipe } from 'lodash/fp';
import { getTypedObjectKeys, includesIgnoreCase } from './utils';
/**
*
* @param templateSegments : array di stringhe, dove gli elementi sono i segnaposto delle variabili {{1}}, {{2}} e le stringhe di testo
* @param templateInsertedValues : oggetto con le chiavi dei segnaposto e i valori delle variabili {1: 'ciao'}
* @returns una stringa con il testo del template, con i segnaposto sostituiti dai valori delle variabili
*/
export function reconstructTemplateText(templateSegments, templateInsertedValues) {
const text = templateSegments.map((segment) => {
//isola le stringhe con i segnaposto {{1}}, {{2}}
const match = segment.match(/{{(\d+)}}/);
//recupera l'id del segnaposto (esempio {{1}} --> 1) e lo usa per recuperare il valore delle variabili
const placeholderId = match ? match[1] : 0;
const text = templateInsertedValues[placeholderId]
? templateInsertedValues[placeholderId]
: segment;
return text;
});
//ricompone il testo del template con i segnaposto sostituiti dai valori delle variabili
return text.join('');
}
/**
*
* @param text : il testo del template base, con i segnaposto {{1}}, {{2}} dove l'utente inserisce le variabili
* @returns lo stesso testo diviso in un array di stringhe, dove gli elementi sono i segnaposto e le stringhe di testo
*/
export function toSplittedTemplatePlaceholders(text) {
return text.split(/(\{\{\d+\}\})/g);
}
/**
*
* @param variablesFromUser : array di oggetti con le chiavi key e value, dove key è il nome della variabile e value è il valore della variabile
* @returns oggetto con le chiavi 1, 2, 3... e i valori delle variabili
* Rende compatibile il template e le variabili inserite dall'utente
*/
export function getTemplateInsertedValues(variablesFromUser) {
const acc = {};
variablesFromUser.forEach((variable, i) => {
acc[i + 1] = variable.value;
});
return acc;
}
/**
* @param templateText il testo del template base, con i segnaposto {{1}}, {{2}} dove l'utente inserisce le variabili
* @param templateSectionKey la chiave della sezione del template, ad esempio BUTTONS, TEXT, ecc.
* E' la chiave con cui vengono salvati i valori delle variabili.
* @param variablesFromMessage array di oggetti con le chiavi key e value.
* Se valorizzato: ci si trova in un messaggio di tipo template
* @param values oggetto con le chiavi sectionkey_1, sectionkey_2... e i valori delle variabili.
* Se valorizzato: si sta creando un template nuovo.
* @description Questa funzione costruisce il testo del template con le variabili inserite dall'utente.
* Può prendere i valori delle variabili in forma di oggetto oppure in forma di array di oggetti.
* Questo perchè la preview in un invio di nuovo messaggio template riceve le variabili in forma differente
* dalla preview di un messaggio template nella conversazione.
* @returns il testo completo del template con le variabili inserite dall'utente
*/
export function buildTemplateTextWithInsertedValues({ templateText, templateSectionKey, variablesFromMessage, values, }) {
// Se non ci sono valori e non ci sono variabili dal messaggio, restituisci una stringa vuota
if (!values && !variablesFromMessage)
return '';
const segments = toSplittedTemplatePlaceholders(templateText);
const filteredValues = pipe(
//sempre: un array di chiavi tipizzate, composte da templateType_1, templateType_2, ecc.
always(getTypedObjectKeys(values ?? {})),
//ignora tutte quelle che non hanno la chiave sezione template corretta
filter((key) => includesIgnoreCase(templateSectionKey, key.toString())), map((key) => {
const value = values?.[key] ?? '';
//se la chiave è BUTTONS, l'ultima parte della chiave è il numero del segnaposto
const lastKeyPart = templateSectionKey === 'BUTTONS'
? key.toString().split('_').pop()
: null;
const index = lastKeyPart ?? key.toString().split('_')[1];
return { [index]: value };
}))();
const obj = Object.assign({}, ...filteredValues);
//se non ci sono variabili dal messaggio, usa i valori filtrati
const filteredVariables = variablesFromMessage?.filter((v) => v.key.includes(templateSectionKey));
const insertedValues = filteredVariables
? getTemplateInsertedValues(filteredVariables)
: obj ?? {};
return reconstructTemplateText(segments, insertedValues);
}
export const extractFileDataFromFile = async (file) => {
const readFileAsBase64 = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
if (e.target?.result) {
const base64String = e.target.result;
resolve(base64String);
// resolve(e.target.result as ArrayBuffer);
}
else {
resolve(null);
return;
}
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
};
const base64 = await readFileAsBase64(file); // Legge il file e lo converte in Base64
const base64String = base64?.split(',')[1] ?? null;
if (!base64String)
return null;
return {
fileBytes: base64String,
fileName: file.name,
};
};
export function getUserInitials(userFullName) {
if (!userFullName.includes(' '))
return userFullName[0];
const user = userFullName.split(' ');
const userName = user?.[0] ?? '';
const userSurname = user?.[1] ?? '';
const initials = userName[0] + userSurname[0];
return initials;
}
/**
*
* @param sentDate data di invio del messaggio in formato ISOstring: YYYY-MM-DDTHH:mm:ss.sssZ
* @returns La data in formato "ieri", "giorno della settimana" o "giorno mese anno"
*/
export function buildPreviewDate(sentDate) {
const now = Date.now();
const sendDate = new Date(sentDate).getTime();
const oneDay = 24 * 60 * 60 * 1000;
const twoDays = 2 * oneDay;
const oneWeek = 7 * oneDay;
// Tra 24 e 48 ore fa → "ieri"
if (now - oneDay > sendDate && now - twoDays < sendDate) {
return 'ieri';
}
// Tra 48 ore fa e 1 settimana fa → Giorno della settimana
if (now - twoDays > sendDate && now - oneWeek < sendDate) {
const days = [
'domenica',
'lunedì',
'martedì',
'mercoledì',
'giovedì',
'venerdì',
'sabato',
];
return days[new Date(sendDate).getDay()];
}
// Più di una settimana fa → "giorno + mese" (es. 21 Feb)
if (now - oneWeek > sendDate) {
const dateObj = new Date(sendDate);
const day = dateObj.getDate();
const months = [
'Gen',
'Feb',
'Mar',
'Apr',
'Mag',
'Giu',
'Lug',
'Ago',
'Set',
'Ott',
'Nov',
'Dic',
];
const month = months[dateObj.getMonth()];
const year = dateObj.getFullYear();
return `${day} ${month} ${year}`;
}
// Meno di 24 ore fa → Ora in formato HH:mm
return sentDate.split('T')[1].slice(0, 5);
}
export function buildSentDate(sentDate) {
const months = [
'Gen',
'Feb',
'Mar',
'Apr',
'Mag',
'Giu',
'Lug',
'Ago',
'Set',
'Ott',
'Nov',
'Dic',
];
const sentDateAsDate = new Date(sentDate);
// Estrarre giorno, mese e anno
const day = sentDateAsDate.getDate();
const month = months[sentDateAsDate.getMonth()]; // Converti il mese in formato abbreviato
const year = sentDateAsDate.getFullYear();
// Costruire il formato desiderato
return `${day} ${month} ${year}`;
}