init commit

This commit is contained in:
Jose
2025-09-14 18:41:10 +02:00
commit a8408f0f43
66 changed files with 3016 additions and 0 deletions

15
src/util/alertHelpers.jsx Normal file
View File

@@ -0,0 +1,15 @@
export const renderErrorAlert = (error, options = {}) => {
const { className = 'alert alert-danger py-1 px-2 small', role = 'alert' } = options;
if (!error) return null;
return (
<div className={className} role={role}>
{typeof error === 'string' ? error : 'An unexpected error occurred.'}
</div>
);
};
export const resetErrorIfEditEnds = (editMode, setError) => {
if (!editMode) setError(null);
};

7
src/util/constants.js Normal file
View File

@@ -0,0 +1,7 @@
'use strict';
const CONSTANTS = {
};
export { CONSTANTS };

10
src/util/date.js Normal file
View File

@@ -0,0 +1,10 @@
'use strict';
const getNowAsLocalDatetime = () => {
const now = new Date();
const offset = now.getTimezoneOffset(); // en minutos
const local = new Date(now.getTime() - offset * 60000);
return local.toISOString().slice(0, 16);
};
export { getNowAsLocalDatetime }

View File

@@ -0,0 +1,30 @@
export const DateParser = {
sqlToString: (sqlDate) => {
const [datePart] = sqlDate.split('T');
const [year, month, day] = datePart.split('-');
return `${day}/${month}/${year}`;
},
timestampToString: (timestamp) => {
const [datePart] = timestamp.split('T');
const [year, month, day] = datePart.split('-');
return `${day}/${month}/${year}`;
},
isoToStringWithTime: (isoString) => {
if (!isoString) return '—';
const date = new Date(isoString);
if (isNaN(date)) return '—'; // Para proteger aún más por si llega basura
return new Intl.DateTimeFormat('es-ES', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
hour12: false,
timeZone: 'Europe/Madrid'
}).format(date);
}
};

View File

@@ -0,0 +1,10 @@
export const errorParser = (err) => {
const message = err.response?.data?.message;
try {
const parsed = JSON.parse(message);
return Object.values(parsed)[0];
// eslint-disable-next-line no-unused-vars
} catch (e) {
return message || err.message || "Unknown error";
}
};

View File

@@ -0,0 +1,29 @@
export const generateSecurePassword = (length = 12) => {
const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const lower = 'abcdefghijklmnopqrstuvwxyz';
const digits = '0123456789';
const symbols = '!@#$%^&*'; // <- compatibles con bcrypt
const all = upper + lower + digits + symbols;
if (length < 8) length = 8;
const getRand = (chars) => chars[Math.floor(Math.random() * chars.length)];
let password = [
getRand(upper),
getRand(lower),
getRand(digits),
getRand(symbols),
];
for (let i = password.length; i < length; i++) {
password.push(getRand(all));
}
for (let i = password.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[password[i], password[j]] = [password[j], password[i]];
}
return password.join('');
};

7
src/util/tokenUtils.js Normal file
View File

@@ -0,0 +1,7 @@
export const parseJwt = (token) => {
try {
return JSON.parse(atob(token.split('.')[1]));
} catch (e) {
return null;
}
};