chore: format dates globally in datatable and entity form

This commit is contained in:
Carlos (Almeira) 2026-06-22 08:58:08 -05:00
parent f99709cf35
commit 2b545b28d5
6 changed files with 121 additions and 7 deletions

View File

@ -42,8 +42,8 @@ fi
# 7. Copiar archivo de entorno de ejemplo o variables
if [ -f ".env.local" ]; then
echo "Copiando variables locales como plantilla .env.production.example..."
cp .env.local "$DEPLOY_DIR/.env.production.example"
echo "Copiando variables locales a .env.production..."
cp .env.local "$DEPLOY_DIR/.env.production"
fi
# 7.5. Modificar package.json para evitar que Hostinger intente hacer build

View File

@ -82,8 +82,7 @@ export default async function EntityPage({
documents = JSON.parse(JSON.stringify(response.documents));
total = response.total;
if (entity === 'posts') {
const fields = SCHEMA_MAP[entity] || [];
const fields = SCHEMA_MAP[entity] || [];
await Promise.all(
fields
.filter((f) => f.type === 'relation' && f.relationCollection)
@ -113,7 +112,20 @@ export default async function EntityPage({
} catch { }
})
);
}
// Enrich documents with resolved relation data for DataTable
documents = documents.map(doc => {
const enriched = { ...doc };
fields.forEach(field => {
if (field.type === 'relation' && typeof enriched[field.name] === 'string' && relationData[field.name]) {
const relDoc = relationData[field.name].find(r => r.$id === enriched[field.name]);
if (relDoc) {
enriched[field.name] = relDoc;
}
}
});
return enriched;
});
} catch (error) {
console.error(`Error fetching entity ${entity}:`, error);
}

View File

@ -145,6 +145,15 @@ export const DataTable = ({
value = Array.isArray(value) ? `[Lista (${value.length})]` : value.$id || '[Vinculado]';
}
}
if (field.type === 'date' && value) {
try {
value = new Intl.DateTimeFormat('es-CO', {
year: 'numeric', month: 'short', day: '2-digit',
hour: '2-digit', minute: '2-digit'
}).format(new Date(value as string));
} catch(e) {}
}
if (typeof value === 'boolean') {
value = value ? 'Sí' : 'No';

View File

@ -148,7 +148,10 @@ export const EntityForm = ({
if (val === undefined || val === null) return '';
if (field.type === 'boolean') return val ? 'true' : 'false';
if (field.type === 'date') return new Date(val).toISOString().slice(0, 16);
if (field.type === 'date') {
if (!val) return '';
try { return new Date(val).toISOString().slice(0, 16); } catch(e) { return ''; }
}
if (field.type === 'relation') return typeof val === 'object' ? val.$id : val;
return val;
};

View File

@ -36,7 +36,7 @@ export const PostSchema = z.object({
message: 'Estado inválido.',
}),
tipo: z.enum(['noticia', 'evento', 'aviso', 'comunicado', 'galeria'], {
tipo: z.enum(['noticia', 'evento', 'aviso', 'clasificado', 'blog'], {
message: 'Tipo de contenido inválido.',
}),

View File

@ -0,0 +1,90 @@
const { Client, Databases, Query } = require('node-appwrite');
require('dotenv').config({ path: '.env.local' });
const client = new Client()
.setEndpoint(process.env.NEXT_PUBLIC_APPWRITE_ENDPOINT)
.setProject(process.env.NEXT_PUBLIC_APPWRITE_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);
const databases = new Databases(client);
const DB_ID = process.env.APPWRITE_DATABASE_ID;
const makeSlug = (text) => {
if (!text) return '';
return text
.normalize("NFD")
.replace(/[\u0300-\u036f]/g, "")
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/(^-|-$)+/g, '');
};
async function updateSlugs() {
try {
console.log('Connecting to Appwrite to update Multivision slugs...');
const collections = await databases.listCollections(DB_ID);
const map = {};
collections.collections.forEach(c => { map[c.name.toLowerCase()] = c.$id; });
const postsCollectionId = map['posts'] || 'posts';
let cursor = null;
let updatedCount = 0;
let totalCount = 0;
while (true) {
const queries = [
Query.startsWith('slug', 'multivision-'),
Query.limit(100)
];
if (cursor) queries.push(Query.cursorAfter(cursor));
const res = await databases.listDocuments(DB_ID, postsCollectionId, queries);
console.log(`Fetched ${res.documents.length} matching documents in this batch.`);
for (const doc of res.documents) {
totalCount++;
const newSlug = makeSlug(doc.titulo);
console.log(`Updating document ${doc.$id}`);
console.log(` Old slug: ${doc.slug}`);
console.log(` New slug: ${newSlug}`);
try {
await databases.updateDocument(DB_ID, postsCollectionId, doc.$id, {
slug: newSlug
});
updatedCount++;
} catch (updateErr) {
console.error(` Failed to update ${doc.$id}: ${updateErr.message}`);
if (updateErr.message.includes('unique') || updateErr.code === 409) {
const alternativeSlug = `${newSlug}-${Math.floor(Math.random() * 1000)}`;
console.log(` Trying alternative slug: ${alternativeSlug}`);
try {
await databases.updateDocument(DB_ID, postsCollectionId, doc.$id, {
slug: alternativeSlug
});
updatedCount++;
} catch (e) {
console.error(` Failed alternative update for ${doc.$id}: ${e.message}`);
}
}
}
}
if (res.documents.length < 100) break;
cursor = res.documents[res.documents.length - 1].$id;
}
console.log(`\nOperation complete. Found ${totalCount} multivision posts, successfully updated ${updatedCount}.`);
process.exit(0);
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
}
updateSlugs();