diff --git a/src/app/[slug]/page.tsx b/src/app/[slug]/page.tsx
index cbfa012..3350136 100644
--- a/src/app/[slug]/page.tsx
+++ b/src/app/[slug]/page.tsx
@@ -35,8 +35,9 @@ async function fetchPostData(slugOrId: string) {
}
}
-export default async function NoticiaDetail({ params }: { params: { slug: string } }) {
- const post = await fetchPostData(params.slug);
+export default async function NoticiaDetail({ params }: { params: Promise<{ slug: string }> }) {
+ const { slug } = await params;
+ const post = await fetchPostData(slug);
const hasSidebar = await hasSidebarContent();
if (!post) {
diff --git a/src/app/clasificados/page.tsx b/src/app/clasificados/page.tsx
index 028391b..ef1643a 100644
--- a/src/app/clasificados/page.tsx
+++ b/src/app/clasificados/page.tsx
@@ -13,10 +13,10 @@ async function fetchClasificadosData() {
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
const settings: any = settingsRes.documents.length > 0 ? settingsRes.documents[0] : {};
- const postsCount = settings.classifieds_count || 9;
+ const postsCount = settings.feed_news_count || 12;
const cardSettings = {
showCategory: settings.news_card_show_category ?? false,
- showFooterDate: settings.news_card_show_footer_date ?? true,
+ showFooterDate: settings.show_news_date ?? false,
showFooterButton: settings.news_card_show_footer_button ?? true,
footerText: settings.news_card_footer_text || ""
};
diff --git a/src/app/dashboard/[entity]/[id]/page.tsx b/src/app/dashboard/[entity]/[id]/page.tsx
index 2362030..0ba2f57 100644
--- a/src/app/dashboard/[entity]/[id]/page.tsx
+++ b/src/app/dashboard/[entity]/[id]/page.tsx
@@ -5,7 +5,7 @@ import Link from 'next/link';
import { updateDocumentServer } from '@/app/actions/appwrite';
import { redirect } from 'next/navigation';
-export default async function EditEntityPage({ params }: { params: { entity: string, id: string } }) {
+export default async function EditEntityPage({ params }: { params: Promise<{ entity: string, id: string }> }) {
const { entity, id } = await params;
const collectionId = collectionMap[entity];
diff --git a/src/app/dashboard/[entity]/new/page.tsx b/src/app/dashboard/[entity]/new/page.tsx
index bbd622b..27c0874 100644
--- a/src/app/dashboard/[entity]/new/page.tsx
+++ b/src/app/dashboard/[entity]/new/page.tsx
@@ -5,7 +5,7 @@ import Link from 'next/link';
import { createDocumentServer } from '@/app/actions/appwrite';
import { redirect } from 'next/navigation';
-export default async function NewEntityPage({ params }: { params: { entity: string } }) {
+export default async function NewEntityPage({ params }: { params: Promise<{ entity: string }> }) {
const { entity } = await params;
const collectionId = collectionMap[entity];
diff --git a/src/app/dashboard/[entity]/page.tsx b/src/app/dashboard/[entity]/page.tsx
index 0ca24a6..4ec10a3 100644
--- a/src/app/dashboard/[entity]/page.tsx
+++ b/src/app/dashboard/[entity]/page.tsx
@@ -11,8 +11,8 @@ export default async function EntityPage({
params,
searchParams
}: {
- params: { entity: string },
- searchParams: { q?: string, page?: string }
+ params: Promise<{ entity: string }>,
+ searchParams: Promise<{ q?: string, page?: string }>
}) {
const { entity } = await params;
const sParams = await searchParams;
diff --git a/src/app/dashboard/entity/page.tsx b/src/app/dashboard/entity/page.tsx
index a633835..3f95670 100644
--- a/src/app/dashboard/entity/page.tsx
+++ b/src/app/dashboard/entity/page.tsx
@@ -1,13 +1,26 @@
import { getEntity, updateEntity } from '@/app/actions/entity';
-import { Building, Image as ImageIcon, Link as LinkIcon, Share2, Tv, RadioTower } from 'lucide-react';
+import { Building, Image as ImageIcon, Link as LinkIcon, Share2, Tv, RadioTower, Facebook, Instagram, Twitter, Youtube, Send, Mail, Globe, MapPin, Phone, MessageSquare } from 'lucide-react';
+import { createSessionClient } from '@/lib/appwrite.server';
+import { APPWRITE_ALMEIRA_CONFIG } from '@/lib/appwrite';
export default async function EntityPage() {
let entity: any = null;
+ let cities: any[] = [];
try {
entity = await getEntity();
+
+ const sessionClient = await createSessionClient();
+ if (sessionClient) {
+ const citiesRes = await sessionClient.databases.listDocuments(
+ APPWRITE_ALMEIRA_CONFIG.databaseId,
+ 'cities',
+ []
+ );
+ cities = citiesRes.documents;
+ }
} catch (e) {
- console.error("No se pudo cargar config de entidad:", e);
+ console.error("No se pudo cargar la información de la entidad o ciudades:", e);
}
async function updateEntityClient(formData: FormData) {
@@ -17,7 +30,7 @@ export default async function EntityPage() {
return (
-
+
@@ -25,7 +38,7 @@ export default async function EntityPage() {
Perfil de Entidad
-
Identidad Corporativa, Contacto y Canales de Streaming
+
Identidad Corporativa, Contacto y Canales
@@ -36,7 +49,7 @@ export default async function EntityPage() {
Identidad Visual
-
+
-
+
{entity?.logotipo && (

@@ -57,7 +70,7 @@ export default async function EntityPage() {
type="file"
name="logotipo"
accept="image/*"
- className="w-full bg-slate-950/50 border border-slate-800 rounded-xl file:mr-4 file:py-3 file:px-4 file:rounded-l-xl file:border-0 file:text-sm file:font-semibold file:bg-cyan-500/10 file:text-cyan-400 hover:file:bg-cyan-500/20 text-slate-300 text-sm transition-all"
+ className="w-full bg-slate-950/50 border border-slate-800 rounded-xl file:mr-4 file:py-3 file:px-4 file:rounded-l-xl file:border-0 file:text-[10px] file:font-black file:uppercase file:bg-cyan-500/10 file:text-cyan-400 hover:file:bg-cyan-500/20 text-slate-300 text-sm transition-all"
/>
@@ -71,36 +84,55 @@ export default async function EntityPage() {
{/* Contacto Físico */}
-
Contacto Oficial
+
Contacto Oficial
-
-
-
-
+
+ {/* Email y Sitio Web en líneas separadas como solicitó el usuario */}
+
+
+
-
-
-
+
+
@@ -111,7 +143,7 @@ export default async function EntityPage() {
Canales en Vivo (Streaming)
-
+
-
Esta URL se usará para el reproductor principal de la sección TV.
-
+
-
Enlace directo al flujo de audio para la sección Radio.
- {/* Redes Sociales */}
+ {/* Redes Sociales con Iconos */}
-
diff --git a/src/app/dashboard/profile/page.tsx b/src/app/dashboard/profile/page.tsx
index 8ed3c0c..54e7b5d 100644
--- a/src/app/dashboard/profile/page.tsx
+++ b/src/app/dashboard/profile/page.tsx
@@ -140,7 +140,7 @@ export default function ProfilePage() {
- {loading ? : <>Guardar Cambios >}
+ {loading ? : <>Guardar >}
diff --git a/src/app/dashboard/settings/page.tsx b/src/app/dashboard/settings/page.tsx
index af3a253..7b1bd42 100644
--- a/src/app/dashboard/settings/page.tsx
+++ b/src/app/dashboard/settings/page.tsx
@@ -35,15 +35,26 @@ export default async function SettingsPage() {
const updateData = {
ticker_count: parseInt(formData.get('ticker_count') as string),
- rotation_seconds: parseInt(formData.get('rotation_seconds') as string)
+ feed_news_count: parseInt(formData.get('feed_news_count') as string),
+ rotation_seconds: parseInt(formData.get('rotation_seconds') as string),
+ show_news_date: formData.get('show_news_date') === 'true'
};
- await sessionClient.databases.updateDocument(
- APPWRITE_ALMEIRA_CONFIG.databaseId,
- 'settings',
- formData.get('docId') as string,
- updateData
- );
+ if (formData.get('docId')) {
+ await sessionClient.databases.updateDocument(
+ APPWRITE_ALMEIRA_CONFIG.databaseId,
+ 'settings',
+ formData.get('docId') as string,
+ updateData
+ );
+ } else {
+ await sessionClient.databases.createDocument(
+ APPWRITE_ALMEIRA_CONFIG.databaseId,
+ 'settings',
+ 'unique()',
+ updateData
+ );
+ }
revalidatePath('/dashboard/settings');
revalidatePath('/'); // Revalidate frontpage
@@ -56,7 +67,7 @@ export default async function SettingsPage() {
return (
-
+
@@ -75,58 +86,83 @@ export default async function SettingsPage() {
{/* Configurador del Ticker */}
-
-
-
-
Ticker de Noticias
+
+
+
+ Noticias y Feed
-
- Gobierna el cintillo de 'Últimas Noticias' que rota bajo el encabezado superior estableciendo su límite histórico.
-
-
-
+
+
+
+
{/* Configurador de Rotación (Banners) */}
-
-
-
-
Velocidad Carrusel
+
+
+
+
Visualización
-
- Regula el tiempo en pantalla antes de que cambie la lámina (Afecta Banner Principal y Sliders Patrocinados).
-
-
+
- Segundos
+ Segundos
+
+
+ Estas configuraciones afectan el comportamiento dinámico del sitio web principal y los tiempos de carga de recursos del lado del servidor.
+
-
+
- Guardar Motor Web
+ Guardar
diff --git a/src/app/eventos/page.tsx b/src/app/eventos/page.tsx
index cfdb563..a90b74d 100644
--- a/src/app/eventos/page.tsx
+++ b/src/app/eventos/page.tsx
@@ -13,10 +13,10 @@ async function fetchEventosData() {
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
const settings: any = settingsRes.documents.length > 0 ? settingsRes.documents[0] : {};
- const postsCount = settings.events_count || 9;
+ const postsCount = settings.feed_news_count || 12;
const cardSettings = {
showCategory: settings.news_card_show_category ?? false,
- showFooterDate: settings.news_card_show_footer_date ?? true,
+ showFooterDate: settings.show_news_date ?? false,
showFooterButton: settings.news_card_show_footer_button ?? true,
footerText: settings.news_card_footer_text || ""
};
diff --git a/src/app/globals.css b/src/app/globals.css
index 0356e93..a448ab5 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -86,14 +86,17 @@
/* Scrollbar futurista */
::-webkit-scrollbar {
width: 8px;
+ height: 8px;
}
::-webkit-scrollbar-track {
background: #020617;
}
::-webkit-scrollbar-thumb {
- background: #1e293b;
- border-radius: 4px;
+ background: #06b6d4; /* Cyan */
+ background: linear-gradient(180deg, #06b6d4 0%, #3b82f6 100%);
+ border-radius: 10px;
+ border: 2px solid #020617;
}
::-webkit-scrollbar-thumb:hover {
- background: #334155;
+ background: #22d3ee;
}
diff --git a/src/app/page.tsx b/src/app/page.tsx
index e71ee47..8e0401b 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -13,10 +13,10 @@ async function fetchHomeData() {
const settingsRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'settings', []);
const settings: any = settingsRes.documents.length > 0 ? settingsRes.documents[0] : {};
- const postsCount = settings.feed_count || settings.post_count || 9;
+ const postsCount = settings.feed_news_count || 12;
const cardSettings = {
showCategory: settings.news_card_show_category ?? false,
- showFooterDate: settings.news_card_show_footer_date ?? true,
+ showFooterDate: settings.show_news_date ?? false,
showFooterButton: settings.news_card_show_footer_button ?? true,
footerText: settings.news_card_footer_text || ""
};
diff --git a/src/components/NewsTicker.tsx b/src/components/NewsTicker.tsx
index bc8ec5f..d321dcb 100644
--- a/src/components/NewsTicker.tsx
+++ b/src/components/NewsTicker.tsx
@@ -42,16 +42,16 @@ export default async function NewsTicker() {
]);
// Resolve Media
- const mediaIds = postsRes.documents.map(p => p.imagen_destacada_id).filter(id => id && typeof id === 'string');
+ const mediaIds = postsRes.documents.map((p: any) => p.imagen_destacada_id).filter((id: any) => id && typeof id === 'string');
const mediaMap = new Map();
if (mediaIds.length > 0) {
const mediaRes = await client.databases.listDocuments(APPWRITE_ALMEIRA_CONFIG.databaseId, 'media', [
Query.equal('$id', mediaIds)
]);
- mediaRes.documents.forEach(m => mediaMap.set(m.$id, m));
+ mediaRes.documents.forEach((m: any) => mediaMap.set(m.$id, m));
}
- newsItems = postsRes.documents.map(post => {
+ newsItems = postsRes.documents.map((post: any) => {
const media = mediaMap.get(post.imagen_destacada_id);
let imagenUrl = post.og_image_url || null;
if (media) {
@@ -92,7 +92,7 @@ export default async function NewsTicker() {
>
{noticia.imagenUrl && (
// eslint-disable-next-line @next/next/no-img-element
-

+

)}
{!noticia.imagenUrl && }
diff --git a/src/components/ProgrammingSchedule.tsx b/src/components/ProgrammingSchedule.tsx
index 05ca03b..e9d0bec 100644
--- a/src/components/ProgrammingSchedule.tsx
+++ b/src/components/ProgrammingSchedule.tsx
@@ -4,15 +4,16 @@ import { useEffect, useState, useRef } from 'react';
export default function ProgrammingSchedule({ matrixData }: { matrixData: Record }) {
const [currentTime, setCurrentTime] = useState(new Date());
+ const [viewMode, setViewMode] = useState<'day' | 'week'>('day');
const containerRef = useRef(null);
useEffect(() => {
- // Actualizar cada minuto
+ // Actualizar cada minuto cada que cambie la hora
const interval = setInterval(() => setCurrentTime(new Date()), 60000);
return () => clearInterval(interval);
}, []);
- const days = [
+ const allDays = [
{ key: 'mon', label: 'Lunes', index: 1 },
{ key: 'tue', label: 'Martes', index: 2 },
{ key: 'wed', label: 'Miércoles', index: 3 },
@@ -22,20 +23,26 @@ export default function ProgrammingSchedule({ matrixData }: { matrixData: Record
{ key: 'sun', label: 'Domingo', index: 0 }
];
+ const currentDayIndex = currentTime.getDay();
+
+ // Si estamos en modo día, solo filtramos el día actual
+ const days = viewMode === 'day'
+ ? allDays.filter(d => d.index === currentDayIndex)
+ : allDays;
+
const slots = Array.from({length: 48}).map((_, i) => {
const h = Math.floor(i/2).toString().padStart(2, '0');
const m = i % 2 === 0 ? '00' : '30';
return `${h}:${m}`;
});
- const currentDayIndex = currentTime.getDay();
const currentHour = currentTime.getHours();
const currentMinute = currentTime.getMinutes();
const currentSlotIndex = currentHour * 2 + (currentMinute >= 30 ? 1 : 0);
// Calc rowSpans to unify cells visually
const spans: Record = {};
- days.forEach(d => {
+ allDays.forEach(d => {
const list = slots.map(time => matrixData[`${time}_${d.key}`] || '');
const spanList = new Array(48).fill(1);
for(let i=0; i<48; i++){
@@ -58,30 +65,46 @@ export default function ProgrammingSchedule({ matrixData }: { matrixData: Record
const scrollAmnt = Math.max(0, (currentSlotIndex - 3) * rowHeight);
containerRef.current.scrollTop = scrollAmnt;
}
- }, [currentSlotIndex]);
+ }, [currentSlotIndex, viewMode]);
return (
-
-
+
+
Parrilla de Programación
+
+ {/* Switch Futurista Día / Semana */}
+
+ setViewMode('day')}
+ className={`px-4 py-1.5 rounded-lg text-xs font-black uppercase tracking-widest transition-all ${viewMode === 'day' ? 'bg-cyan-500 text-slate-950 shadow-[0_0_15px_rgba(6,182,212,0.4)]' : 'text-slate-500 hover:text-slate-300'}`}
+ >
+ Hoy
+
+ setViewMode('week')}
+ className={`px-4 py-1.5 rounded-lg text-xs font-black uppercase tracking-widest transition-all ${viewMode === 'week' ? 'bg-cyan-500 text-slate-950 shadow-[0_0_15px_rgba(6,182,212,0.4)]' : 'text-slate-500 hover:text-slate-300'}`}
+ >
+ Semana
+
+
-
+
- |
- Hora
+ |
+ Hora
|
{days.map(d => {
const isToday = d.index === currentDayIndex;
return (
-
+ |
{d.label}
- {isToday && HOY }
+ {isToday && viewMode === 'week' && HOY }
|
)
})}
@@ -95,7 +118,7 @@ export default function ProgrammingSchedule({ matrixData }: { matrixData: Record
return (
- {/* Indicador de Línea de Tiempo Rojo (Midiéndose internamente en sus 30 mins) */}
+ {/* Indicador de Línea de Tiempo Roja */}
{isCurrentSlot && (
|