Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9a63ffa
Initial commit
PGSCOM May 31, 2026
c73ab6d
Pin en la pantalla
PGSCOM May 31, 2026
83f831b
Estilo de los circulos
PGSCOM May 31, 2026
fd815ff
Fix z-index
PGSCOM May 31, 2026
c1da432
Animación formar el circulo
PGSCOM May 31, 2026
add9245
Optimización
PGSCOM Jun 1, 2026
a504150
Nueva animación lateral
PGSCOM Jun 1, 2026
308f688
Hacia atrás fluido
PGSCOM Jun 1, 2026
9e273da
Centrado y mejora de animación
PGSCOM Jun 1, 2026
d9d2374
Mejora de animación
PGSCOM Jun 1, 2026
f5175bb
Animación de carga
PGSCOM Jun 1, 2026
e036840
Fix animación de carga
PGSCOM Jun 1, 2026
d5be30d
Animación carga
PGSCOM Jun 1, 2026
73a2bb6
Aumento de radio del circulo de carga
PGSCOM Jun 1, 2026
045f80e
Optimización
PGSCOM Jun 2, 2026
c8790ef
Fixes varios
PGSCOM Jun 2, 2026
26b6757
Fix animación hacia atrás y recarga y proyecto-card duplicado
PGSCOM Jun 2, 2026
82ca79a
Limpieza
PGSCOM Jun 9, 2026
f302c41
Optimización para moviles
PGSCOM Jun 9, 2026
0ee9067
Nueva landing page
PGSCOM Jun 10, 2026
657b7b2
Modo claro
PGSCOM Jun 10, 2026
4e5c42f
Fix tamaño máscara
PGSCOM Jun 10, 2026
9544b49
Fix degradado a blanco de parte 2
PGSCOM Jun 10, 2026
efc9532
Fix color logo scroll
PGSCOM Jun 10, 2026
7a2ec5a
Logo redondeado
PGSCOM Jun 10, 2026
1aa10da
Cambio pantalla de carga
PGSCOM Jun 10, 2026
fc3abda
Texto pantalla de carga quitado
PGSCOM Jun 10, 2026
662b4e5
Tarjeta proyectos landing pages
PGSCOM Jun 10, 2026
3ae9382
Botón contacto eliminado
PGSCOM Jun 10, 2026
8fdd302
Animación scroll al pulsar "Ver Proyecetos"
PGSCOM Jun 10, 2026
472c750
Navegación de proyectos
PGSCOM Jun 10, 2026
5ab5774
Refactor project styles for category orbit and bubble map layout; enh…
PGSCOM Jun 11, 2026
be47933
Cambio en la sección de proyectos
PGSCOM Jun 11, 2026
f6fad2c
Rediseño sección de proyectos
PGSCOM Jun 11, 2026
7136aa5
Fix texto al cambiar mueve toda la landing page
PGSCOM Jun 11, 2026
3592d4d
Añadido filtrado de competencias al portfolio
PGSCOM Jun 11, 2026
37eeffa
Fix diseño linea en filtro
PGSCOM Jun 11, 2026
813d959
Añadir imagen en subproyectos
PGSCOM Jun 11, 2026
ffad477
Añadir link en subproyectos
PGSCOM Jun 11, 2026
37cf010
Diseño proyectos (Añadido lineas para que se vea bien que los subproy…
PGSCOM Jun 11, 2026
f551f71
Animaciones siempre activas
PGSCOM Jun 11, 2026
5fe4344
Mejorar diseño y funcionalidad de subtarjetas en la sección de proyectos
PGSCOM Jun 11, 2026
5f4068f
Smooth scroll
PGSCOM Jun 11, 2026
18980ac
Cambio sistema de guardado del .json
PGSCOM Jun 11, 2026
240a3cd
Optimización
PGSCOM Jun 11, 2026
77bc75b
Cambio de formato página de proyectos
PGSCOM Jun 11, 2026
fdcfa34
Fix 100% de la pantalla en iPhone
PGSCOM Jun 13, 2026
1e4c95d
Assets inecesarios eliminados
PGSCOM Jun 13, 2026
af745e4
Revert "Fix 100% de la pantalla en iPhone"
PGSCOM Jun 13, 2026
2b940a3
Merge branch 'v4' into animación-scroll-v2
PGSCOM Jun 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// @ts-check
import { defineConfig } from 'astro/config';

import react from '@astrojs/react';

// https://astro.build/config
export default defineConfig({
integrations: [react()]
site: 'https://pgscom.es',
});
37 changes: 14 additions & 23 deletions functions/contact.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
interface TurnstileResponse {
success: boolean;
'error-codes'?: string[];
}

export const onRequestPost: PagesFunction = async ({ request, env }) => {
console.log('📨 Recibiendo petición de contacto...');

try {
const contentType = request.headers.get('content-type') || '';
console.log('Content-Type:', contentType);
let data: Record<string, string> = {};

if (contentType.includes('application/json')) {
data = await request.json();
console.log('✅ Datos JSON parseados');
} else if (contentType.includes('application/x-www-form-urlencoded')) {
const form = await request.formData();
data = Object.fromEntries([...form.entries()].map(([k, v]) => [k, String(v)]));
console.log('✅ Datos form-data parseados');
} else {
console.error('❌ Content-type no soportado:', contentType);
return new Response(JSON.stringify({ ok: false, error: 'Unsupported content type' }), {
Expand All @@ -22,8 +22,7 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
}

const { nombre, email, asunto, mensaje } = data;
console.log('Datos recibidos:', { nombre, email, asunto, mensajeLength: mensaje?.length });


if (!nombre || !email || !asunto || !mensaje) {
console.error('❌ Campos faltantes');
return new Response(JSON.stringify({ ok: false, error: 'Missing fields' }), {
Expand All @@ -32,7 +31,6 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
});
}

// Basic email validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
console.error('❌ Email inválido:', email);
Expand All @@ -45,11 +43,11 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
// Validar Turnstile
const turnstileToken = data['cf-turnstile-response'];
if (!turnstileToken) {
console.error('❌ Token de Turnstile faltante');
return new Response(JSON.stringify({ ok: false, error: 'Turnstile token missing' }), {
status: 400,
headers: { 'content-type': 'application/json' },
});
console.error('❌ Token de Turnstile faltante');
return new Response(JSON.stringify({ ok: false, error: 'Turnstile token missing' }), {
status: 400,
headers: { 'content-type': 'application/json' },
});
}

const ip = request.headers.get('CF-Connecting-IP');
Expand All @@ -64,20 +62,16 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
method: 'POST',
});

const turnstileOutcome: any = await turnstileResult.json();
const turnstileOutcome: TurnstileResponse = await turnstileResult.json();
if (!turnstileOutcome.success) {
console.error('❌ Validación de Turnstile fallida:', turnstileOutcome);
return new Response(JSON.stringify({ ok: false, error: 'Invalid Turnstile token' }), {
console.error('❌ Validación de Turnstile fallida:', turnstileOutcome);
return new Response(JSON.stringify({ ok: false, error: 'Invalid Turnstile token' }), {
status: 403,
headers: { 'content-type': 'application/json' },
});
}

// Enviar mensaje via Telegram Bot
console.log('🔍 Verificando variables de Telegram...');
console.log('TELEGRAM_BOT_TOKEN presente:', !!env.TELEGRAM_BOT_TOKEN);
console.log('TELEGRAM_CHAT_ID presente:', !!env.TELEGRAM_CHAT_ID);

if (!env.TELEGRAM_BOT_TOKEN || !env.TELEGRAM_CHAT_ID) {
console.error('❌ Variables de entorno de Telegram NO configuradas');
return new Response(JSON.stringify({
Expand All @@ -103,7 +97,6 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
`🕐 ${new Date().toLocaleString('es-ES', { timeZone: 'Europe/Madrid' })}`,
].join('\n');

console.log('📤 Enviando mensaje a Telegram...');
const tgResp = await fetch(tgApi, {
method: 'POST',
headers: { 'content-type': 'application/json' },
Expand All @@ -115,7 +108,6 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
});

const tgData = await tgResp.json();
console.log('Respuesta de Telegram:', { status: tgResp.status, ok: tgData.ok });

if (!tgResp.ok || !tgData.ok) {
console.error('❌ Error de Telegram:', JSON.stringify(tgData));
Expand All @@ -128,7 +120,6 @@ export const onRequestPost: PagesFunction = async ({ request, env }) => {
});
}

console.log('✅ Mensaje enviado exitosamente a Telegram');
return new Response(JSON.stringify({ ok: true }), {
status: 200,
headers: { 'content-type': 'application/json' },
Expand Down
Loading
Loading