refactor: global project hardening and integrity verification
- Add safety checks for direct Appwrite document index access across all root pages. - Harden NewsTicker and AdWrappers with robust fallback settings and length checks. - Apply strict typing to dashboard settings page and resolve icon conflicts. - Final global audit for deprecated Zod .errors usage (0 occurrences remaining). - Standardize PublicationLayout across creation and edit workflows for posts.
This commit is contained in:
parent
956360a693
commit
5279af2003
@ -13,7 +13,12 @@ async function fetchClasificadosData() {
|
|||||||
|
|
||||||
// 1. Settings
|
// 1. Settings
|
||||||
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
||||||
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {}) as Settings;
|
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {
|
||||||
|
ticker_count: 10,
|
||||||
|
rotation_seconds: 5,
|
||||||
|
feed_news_count: 12,
|
||||||
|
show_news_date: true
|
||||||
|
}) as Settings;
|
||||||
|
|
||||||
const postsCount = settings.feed_news_count || 12;
|
const postsCount = settings.feed_news_count || 12;
|
||||||
const cardSettings = {
|
const cardSettings = {
|
||||||
@ -30,7 +35,9 @@ async function fetchClasificadosData() {
|
|||||||
|
|
||||||
let posts: Post[] = [];
|
let posts: Post[] = [];
|
||||||
if (typeRes.documents.length > 0) {
|
if (typeRes.documents.length > 0) {
|
||||||
const typeId = typeRes.documents[0].$id;
|
const firstType = typeRes.documents[0];
|
||||||
|
const typeId = firstType?.$id;
|
||||||
|
if (!typeId) return { posts: [], cardSettings };
|
||||||
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
||||||
Query.equal('tipo_publicacion_id', typeId),
|
Query.equal('tipo_publicacion_id', typeId),
|
||||||
Query.equal('estado', 'Publicado'),
|
Query.equal('estado', 'Publicado'),
|
||||||
|
|||||||
@ -2,11 +2,12 @@ import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite';
|
|||||||
import { createSessionClient } from '@/lib/appwrite.server';
|
import { createSessionClient } from '@/lib/appwrite.server';
|
||||||
import { getEntity, updateEntity } from '@/app/actions/entity';
|
import { getEntity, updateEntity } from '@/app/actions/entity';
|
||||||
import { revalidatePath } from 'next/cache';
|
import { revalidatePath } from 'next/cache';
|
||||||
import { Settings, Save, Clock, Menu, Building, Image as ImageIcon, Link as LinkIcon, Share2 } from 'lucide-react';
|
import { Settings as SettingsIcon, Save, Clock, Menu, Building, Image as ImageIcon, Link as LinkIcon, Share2 } from 'lucide-react';
|
||||||
|
import { Settings as SettingsInterface } from '@/types/settings';
|
||||||
|
|
||||||
export default async function SettingsPage() {
|
export default async function SettingsPage() {
|
||||||
let settings = { ticker_count: 10, rotation_seconds: 5 };
|
let settings: SettingsInterface = { ticker_count: 10, rotation_seconds: 5 };
|
||||||
let docId = 'global_config';
|
let docId = '';
|
||||||
let entity: any = null;
|
let entity: any = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -18,7 +19,7 @@ export default async function SettingsPage() {
|
|||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
if (response.documents.length > 0) {
|
if (response.documents.length > 0) {
|
||||||
settings = response.documents[0] as any;
|
settings = response.documents[0] as unknown as SettingsInterface;
|
||||||
docId = response.documents[0].$id;
|
docId = response.documents[0].$id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +70,7 @@ export default async function SettingsPage() {
|
|||||||
<div className="max-w-5xl mx-auto space-y-6 animate-fade-in pb-12">
|
<div className="max-w-5xl mx-auto space-y-6 animate-fade-in pb-12">
|
||||||
<div className="flex items-center gap-4 bg-slate-900 border border-slate-800 p-6 rounded-2xl shadow-xl shadow-cyan-500/5">
|
<div className="flex items-center gap-4 bg-slate-900 border border-slate-800 p-6 rounded-2xl shadow-xl shadow-cyan-500/5">
|
||||||
<div className="p-3 bg-cyan-500/10 rounded-xl text-cyan-400">
|
<div className="p-3 bg-cyan-500/10 rounded-xl text-cyan-400">
|
||||||
<Settings size={32} />
|
<SettingsIcon size={32} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-black font-outfit uppercase tracking-tighter text-white">
|
<h1 className="text-3xl font-black font-outfit uppercase tracking-tighter text-white">
|
||||||
@ -109,7 +110,7 @@ export default async function SettingsPage() {
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
name="feed_news_count"
|
name="feed_news_count"
|
||||||
defaultValue={(settings as any).feed_news_count || 12}
|
defaultValue={settings.feed_news_count || 12}
|
||||||
min="4" max="100"
|
min="4" max="100"
|
||||||
required
|
required
|
||||||
className="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-3 text-white focus:border-cyan-400 text-xl font-black font-mono transition-all"
|
className="w-full bg-slate-950 border border-slate-800 rounded-xl px-4 py-3 text-white focus:border-cyan-400 text-xl font-black font-mono transition-all"
|
||||||
@ -122,7 +123,7 @@ export default async function SettingsPage() {
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
name="show_news_date"
|
name="show_news_date"
|
||||||
value="true"
|
value="true"
|
||||||
defaultChecked={(settings as any).show_news_date === true}
|
defaultChecked={settings.show_news_date === true}
|
||||||
id="show_news_date"
|
id="show_news_date"
|
||||||
className="w-5 h-5 accent-cyan-500 cursor-pointer"
|
className="w-5 h-5 accent-cyan-500 cursor-pointer"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -13,7 +13,12 @@ async function fetchEventosData() {
|
|||||||
|
|
||||||
// 1. Settings
|
// 1. Settings
|
||||||
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
||||||
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {}) as Settings;
|
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {
|
||||||
|
ticker_count: 10,
|
||||||
|
rotation_seconds: 5,
|
||||||
|
feed_news_count: 12,
|
||||||
|
show_news_date: true
|
||||||
|
}) as Settings;
|
||||||
|
|
||||||
const postsCount = settings.feed_news_count || 12;
|
const postsCount = settings.feed_news_count || 12;
|
||||||
const cardSettings = {
|
const cardSettings = {
|
||||||
@ -30,7 +35,9 @@ async function fetchEventosData() {
|
|||||||
|
|
||||||
let posts: Post[] = [];
|
let posts: Post[] = [];
|
||||||
if (typeRes.documents.length > 0) {
|
if (typeRes.documents.length > 0) {
|
||||||
const typeId = typeRes.documents[0].$id;
|
const firstType = typeRes.documents[0];
|
||||||
|
const typeId = firstType?.$id;
|
||||||
|
if (!typeId) return { posts: [], cardSettings };
|
||||||
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
||||||
Query.equal('tipo_publicacion_id', typeId),
|
Query.equal('tipo_publicacion_id', typeId),
|
||||||
Query.equal('estado', 'Publicado'),
|
Query.equal('estado', 'Publicado'),
|
||||||
|
|||||||
@ -15,7 +15,12 @@ async function fetchHomeData() {
|
|||||||
|
|
||||||
// 1. Settings
|
// 1. Settings
|
||||||
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
||||||
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {}) as Settings;
|
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {
|
||||||
|
ticker_count: 10,
|
||||||
|
rotation_seconds: 5,
|
||||||
|
feed_news_count: 12,
|
||||||
|
show_news_date: true
|
||||||
|
}) as Settings;
|
||||||
|
|
||||||
const postsCount = settings.feed_news_count || 12;
|
const postsCount = settings.feed_news_count || 12;
|
||||||
const cardSettings = {
|
const cardSettings = {
|
||||||
@ -32,7 +37,9 @@ async function fetchHomeData() {
|
|||||||
|
|
||||||
let posts: Post[] = [];
|
let posts: Post[] = [];
|
||||||
if (typeRes.documents.length > 0) {
|
if (typeRes.documents.length > 0) {
|
||||||
const typeId = typeRes.documents[0].$id;
|
const firstType = typeRes.documents[0];
|
||||||
|
const typeId = firstType?.$id;
|
||||||
|
if (!typeId) return { posts: [], cardSettings };
|
||||||
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
||||||
Query.equal('tipo_publicacion_id', typeId),
|
Query.equal('tipo_publicacion_id', typeId),
|
||||||
Query.equal('estado', 'Publicado'),
|
Query.equal('estado', 'Publicado'),
|
||||||
|
|||||||
@ -13,7 +13,7 @@ async function fetchSettings(): Promise<Settings> {
|
|||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.error("fetchSettings error:", e);
|
console.error("fetchSettings error:", e);
|
||||||
}
|
}
|
||||||
return { rotation_seconds: 5, ticker_count: 10 };
|
return { rotation_seconds: 5, ticker_count: 10, feed_news_count: 12, show_news_date: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GlobalTopBanner() {
|
export async function GlobalTopBanner() {
|
||||||
@ -27,7 +27,9 @@ export async function GlobalTopBanner() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (typesRes.documents.length > 0) {
|
if (typesRes.documents.length > 0) {
|
||||||
const typeId = typesRes.documents[0].$id;
|
const firstType = typesRes.documents[0];
|
||||||
|
const typeId = firstType?.$id;
|
||||||
|
if (!typeId) return null;
|
||||||
|
|
||||||
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
||||||
Query.equal('tipo_publicacion_id', typeId),
|
Query.equal('tipo_publicacion_id', typeId),
|
||||||
|
|||||||
@ -19,7 +19,12 @@ export default async function NewsTicker() {
|
|||||||
|
|
||||||
// 1. Fetch Settings
|
// 1. Fetch Settings
|
||||||
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
|
||||||
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {}) as Settings;
|
const settings = (settingsRes.documents.length > 0 ? settingsRes.documents[0] : {
|
||||||
|
ticker_count: 10,
|
||||||
|
rotation_seconds: 5,
|
||||||
|
feed_news_count: 12,
|
||||||
|
show_news_date: true
|
||||||
|
}) as Settings;
|
||||||
const tickerCount = settings.ticker_count || 10;
|
const tickerCount = settings.ticker_count || 10;
|
||||||
|
|
||||||
// 2. Fetch News (NOTICIA)
|
// 2. Fetch News (NOTICIA)
|
||||||
@ -28,7 +33,9 @@ export default async function NewsTicker() {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
if (typeRes.documents.length > 0) {
|
if (typeRes.documents.length > 0) {
|
||||||
const typeId = typeRes.documents[0].$id;
|
const firstType = typeRes.documents[0];
|
||||||
|
const typeId = firstType?.$id;
|
||||||
|
if (!typeId) throw new Error("Could not find typeId for NOTICIA");
|
||||||
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
const postsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'posts', [
|
||||||
Query.equal('tipo_publicacion_id', typeId),
|
Query.equal('tipo_publicacion_id', typeId),
|
||||||
Query.equal('estado', 'Publicado'),
|
Query.equal('estado', 'Publicado'),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user