@@ -11,25 +11,12 @@ import {
1111} from 'lucide-react' ;
1212import { motion } from 'framer-motion' ;
1313import { toast } from 'sonner' ;
14- import { supabase } from '@/integrations/supabase/client' ;
15- import { z } from 'zod' ;
1614
17- // Validación con Zod para asegurar datos limpios
18- const contactFormSchema = z . object ( {
19- name : z . string ( ) . trim ( ) . min ( 2 , "Mínimo 2 caracteres" ) ,
20- email : z . string ( ) . trim ( ) . email ( "Email inválido" ) ,
21- subject : z . string ( ) . trim ( ) . min ( 3 , "Asunto requerido" ) ,
22- message : z . string ( ) . trim ( ) . min ( 10 , "Mensaje demasiado corto" )
23- } ) ;
24-
25- type ContactFormData = z . infer < typeof contactFormSchema > ;
15+ // ELIMINADA LA IMPORTACIÓN DE SUPABASE PARA EVITAR EL ERROR DE BUILD EN VERCEL
2616
2717const Contact : React . FC = ( ) => {
28- const [ formData , setFormData ] = useState < ContactFormData > ( { name : '' , email : '' , subject : '' , message : '' } ) ;
18+ const [ formData , setFormData ] = useState ( { name : '' , email : '' , subject : '' , message : '' } ) ;
2919 const [ isSubmitting , setIsSubmitting ] = useState ( false ) ;
30- const [ formErrors , setFormErrors ] = useState < Partial < Record < keyof ContactFormData , string > > > ( { } ) ;
31- const [ honeypot , setHoneypot ] = useState ( '' ) ; // Protección anti-spam
32-
3320 const [ terminalInput , setTerminalInput ] = useState ( '' ) ;
3421 const [ isTyping , setIsTyping ] = useState ( false ) ;
3522 const [ terminalHistory , setTerminalHistory ] = useState ( [
@@ -43,39 +30,22 @@ const Contact: React.FC = () => {
4330 if ( terminalRef . current ) terminalRef . current . scrollTop = terminalRef . current . scrollHeight ;
4431 } , [ terminalHistory , isTyping ] ) ;
4532
46- const handleFormSubmit = async ( e : React . FormEvent ) => {
33+ const handleFormSubmit = ( e : React . FormEvent ) => {
4734 e . preventDefault ( ) ;
48- if ( honeypot ) return ; // Bloqueo silencioso de bots
49-
50- const result = contactFormSchema . safeParse ( formData ) ;
51- if ( ! result . success ) {
52- const errors : any = { } ;
53- result . error . errors . forEach ( err => { errors [ err . path [ 0 ] ] = err . message ; } ) ;
54- setFormErrors ( errors ) ;
55- return ;
56- }
57-
5835 setIsSubmitting ( true ) ;
59- try {
60- // Envío a Supabase Edge Function (Configurada para alien69flow@proton.me)
61- const { error } = await supabase . functions . invoke ( 'send-contact-email' , {
62- body : { ...formData , destination : 'alien69flow@proton.me' }
63- } ) ;
64-
65- if ( error ) throw error ;
6636
67- toast . success ( 'SEÑAL TRANSMITIDA' , {
68- description : 'Mensaje enviado con éxito a la red Proton.' ,
69- style : { background : '#0a0a0a' , border : '1px solid #39FF14' , color : '#39FF14' }
70- } ) ;
37+ // MÉTODO SEGURO Y DIRECTO: Abre el gestor de correo del usuario con los datos rellenos
38+ // Puedes cambiar 'tu-gmail@gmail.com' por tu dirección real.
39+ const mailtoLink = `mailto:alien69flow@proton.me?subject=${ encodeURIComponent ( formData . subject ) } &body=${ encodeURIComponent ( "De: " + formData . name + "\nEmail: " + formData . email + "\n\nMensaje:\n" + formData . message ) } ` ;
40+
41+ window . location . href = mailtoLink ;
42+
43+ toast . success ( 'PREPARANDO ENVÍO' , {
44+ description : 'Se abrirá tu gestor de correo para enviar la señal.' ,
45+ style : { background : '#0a0a0a' , border : '1px solid #39FF14' , color : '#39FF14' }
46+ } ) ;
7147
72- setFormData ( { name : '' , email : '' , subject : '' , message : '' } ) ;
73- setFormErrors ( { } ) ;
74- } catch ( error ) {
75- toast . error ( 'FALLO DE TRANSMISIÓN' , { description : 'Reintenta o contacta vía RRSS.' } ) ;
76- } finally {
77- setIsSubmitting ( false ) ;
78- }
48+ setTimeout ( ( ) => setIsSubmitting ( false ) , 2000 ) ;
7949 } ;
8050
8151 const handleTerminalSubmit = ( e : React . FormEvent ) => {
@@ -87,12 +57,9 @@ const Contact: React.FC = () => {
8757 setIsTyping ( true ) ;
8858
8959 setTimeout ( ( ) => {
90- let response = "[SISTEMA]: Comando no reconocido. Escriba 'ayuda'." ;
91- if ( userMsg . includes ( 'ayuda' ) ) response = "[AI-TOR]: Comandos disponibles: status, dao, seguridad." ;
92- if ( userMsg . includes ( 'status' ) ) response = "[LOG]: Todos los sistemas operativos. Latencia mínima." ;
93- if ( userMsg . includes ( 'dao' ) ) response = "[AI-TOR]: La gobernanza se ejecuta on-chain mediante contratos inteligentes." ;
94- if ( userMsg . includes ( 'seguridad' ) ) response = "[INFO]: Encriptación end-to-end activa via Proton." ;
95-
60+ let response = "[SISTEMA]: Comando no reconocido." ;
61+ if ( userMsg . includes ( 'ayuda' ) ) response = "[AI-TOR]: Comandos: status, dao, seguridad." ;
62+ if ( userMsg . includes ( 'status' ) ) response = "[LOG]: Sistemas estables. Esperando comunicación." ;
9663 setTerminalHistory ( prev => [ ...prev , { type : 'ai' , text : response } ] ) ;
9764 setIsTyping ( false ) ;
9865 } , 600 ) ;
@@ -115,83 +82,71 @@ const Contact: React.FC = () => {
11582 return (
11683 < div className = "min-h-screen bg-transparent pb-24 px-4 md:px-12 font-exo overflow-hidden" >
11784 < main className = "max-w-7xl mx-auto pt-16" >
118-
119- { /* Header Seccion */ }
12085 < motion . div initial = { { opacity : 0 , y : - 20 } } animate = { { opacity : 1 , y : 0 } } className = "mb-16 text-center lg:text-left" >
12186 < h1 className = "text-5xl md:text-8xl font-nasalization bg-gradient-to-r from-alien-green via-alien-gold to-alien-green bg-clip-text text-transparent drop-shadow-[0_0_15px_rgba(57,255,20,0.2)]" >
12287 COMMUNICATIONS
12388 </ h1 >
124- < div className = "flex items-center justify-center lg:justify-start gap-4 mt-4 text-gray-500 font-mono text-[10px] tracking-[0.4em]" >
89+ < div className = "flex items-center justify-center lg:justify-start gap-4 mt-4 text-gray-400 font-mono text-[10px] tracking-[0.4em]" >
12590 < Cpu className = "w-3 h-3 text-alien-gold animate-spin-slow" />
126- < span > ALPHABETICAL_ORDER_INDEX // ENCRYPTED_LINK </ span >
91+ < span > SISTEMA DE CONTACTO DIRECTO // ALPHABETICAL_ORDER </ span >
12792 </ div >
12893 </ motion . div >
12994
130- < div className = "grid grid-cols-1 lg:grid-cols-2 gap-10 mb-20 items-stretch" >
131-
132- { /* FORMULARIO DE CONTACTO */ }
95+ < div className = "grid grid-cols-1 lg:grid-cols-2 gap-10 mb-20" >
96+ { /* FORMULARIO */ }
13397 < motion . div initial = { { opacity : 0 , x : - 30 } } animate = { { opacity : 1 , x : 0 } } className = "bg-white/[0.02] backdrop-blur-3xl border border-white/10 p-8 md:p-10 rounded-[2.5rem] shadow-2xl relative group overflow-hidden" >
134- < div className = "absolute inset-0 bg-alien-green/5 opacity-0 group-hover:opacity-100 transition-opacity duration-1000" />
135- < div className = "flex justify-between items-center mb-10 relative z-10" >
136- < h2 className = "text-xl font-nasalization text-alien-green flex items-center gap-3 tracking-tighter" >
137- < ShieldCheck className = "w-5 h-5" /> PROTOCOLO DE ENVÍO
138- </ h2 >
139- < span className = "text-[9px] text-gray-500 font-mono" > DEST: PROTON.ME</ span >
140- </ div >
141-
98+ < h2 className = "text-xl font-nasalization text-alien-green mb-10 flex items-center gap-3 relative z-10" >
99+ < ShieldCheck className = "w-5 h-5" /> PROTOCOLO DE ENVÍO
100+ </ h2 >
142101 < form onSubmit = { handleFormSubmit } className = "space-y-6 relative z-10" >
143- { /* Honeypot invisible */ }
144- < input type = "text" className = "hidden" value = { honeypot } onChange = { ( e ) => setHoneypot ( e . target . value ) } />
145-
146102 < div className = "grid grid-cols-1 md:grid-cols-2 gap-6" >
147103 < div className = "space-y-2" >
148- < Label className = "text-[10px] text-alien-green/60 uppercase ml-1" > Alias / Nombre</ Label >
149- < Input value = { formData . name } onChange = { ( e ) => setFormData ( { ...formData , name : e . target . value } ) } className = "bg-black/60 border-white/5 focus:border-alien-green/50 h-14 rounded-2xl" placeholder = "Identidad" />
150- { formErrors . name && < p className = "text-red-500 text-[10px] ml-1" > { formErrors . name } </ p > }
104+ < Label className = "text-[10px] text-gray-500 uppercase ml-1 tracking-widest" > Nombre</ Label >
105+ < Input value = { formData . name } onChange = { ( e ) => setFormData ( { ...formData , name : e . target . value } ) } required className = "bg-black/60 border-white/5 focus:border-alien-green/50 h-14 rounded-2xl text-white" />
151106 </ div >
152107 < div className = "space-y-2" >
153- < Label className = "text-[10px] text-alien-green/60 uppercase ml-1" > Nodo de Respuesta </ Label >
154- < Input type = "email" value = { formData . email } onChange = { ( e ) => setFormData ( { ...formData , email : e . target . value } ) } className = "bg-black/60 border-white/5 focus:border-alien-green/50 h-14 rounded-2xl" placeholder = "email@dominio.com " />
108+ < Label className = "text-[10px] text-gray-500 uppercase ml-1 tracking-widest" > Email </ Label >
109+ < Input type = "email" value = { formData . email } onChange = { ( e ) => setFormData ( { ...formData , email : e . target . value } ) } required className = "bg-black/60 border-white/5 focus:border-alien-green/50 h-14 rounded-2xl text-white " />
155110 </ div >
156111 </ div >
157112 < div className = "space-y-2" >
158- < Label className = "text-[10px] text-alien-green/60 uppercase ml-1" > Etiqueta de Asunto</ Label >
159- < Input value = { formData . subject } onChange = { ( e ) => setFormData ( { ...formData , subject : e . target . value } ) } className = "bg-black/60 border-white/5 focus:border-alien-green/50 h-14 rounded-2xl" />
113+ < Label className = "text-[10px] text-gray-500 uppercase ml-1 tracking-widest" > Asunto</ Label >
114+ < Input value = { formData . subject } onChange = { ( e ) => setFormData ( { ...formData , subject : e . target . value } ) } required className = "bg-black/60 border-white/5 focus:border-alien-green/50 h-14 rounded-2xl text-white " />
160115 </ div >
161116 < div className = "space-y-2" >
162- < Label className = "text-[10px] text-alien-green/60 uppercase ml-1" > Cuerpo del Mensaje</ Label >
163- < Textarea value = { formData . message } onChange = { ( e ) => setFormData ( { ...formData , message : e . target . value } ) } rows = { 5 } className = "bg-black/60 border-white/5 focus:border-alien-green/50 rounded-2xl resize-none" />
117+ < Label className = "text-[10px] text-gray-500 uppercase ml-1 tracking-widest" > Mensaje</ Label >
118+ < Textarea value = { formData . message } onChange = { ( e ) => setFormData ( { ...formData , message : e . target . value } ) } required rows = { 5 } className = "bg-black/60 border-white/5 focus:border-alien-green/50 rounded-2xl resize-none text-white " />
164119 </ div >
165- < Button type = "submit" disabled = { isSubmitting } className = "w-full bg-gradient-to-r from-alien-green to-alien-gold text-black font-black h-16 rounded-2xl hover:brightness-125 transition-all shadow-lg shadow-alien-green/10 " >
166- { isSubmitting ? < Loader2 className = "animate-spin" /> : 'DESPLEGAR PAQUETE DE DATOS ' }
120+ < Button type = "submit" disabled = { isSubmitting } className = "w-full bg-gradient-to-r from-alien-green to-alien-gold text-black font-black h-16 rounded-2xl hover:brightness-125 transition-all" >
121+ { isSubmitting ? < Loader2 className = "animate-spin" /> : 'DESPLEGAR MENSAJE DIRECTO ' }
167122 </ Button >
168123 </ form >
169124 </ motion . div >
170125
171- { /* TERMINAL AI TOR */ }
126+ { /* TERMINAL */ }
172127 < motion . div initial = { { opacity : 0 , x : 30 } } animate = { { opacity : 1 , x : 0 } } className = "flex flex-col bg-black/80 border-2 border-white/5 rounded-[2.5rem] overflow-hidden group" >
173128 < div className = "bg-white/5 p-5 border-b border-white/5 flex justify-between items-center" >
174129 < span className = "text-[10px] font-mono text-alien-gold flex items-center gap-3 tracking-[0.2em]" >
175130 < Terminal className = "w-4 h-4" /> AI-TOR CONSOLE v2.0
176131 </ span >
177- < div className = "w-2 h-2 rounded-full bg-alien-green animate-pulse shadow-[0_0_10px_#39FF14] " />
132+ < div className = "w-2 h-2 rounded-full bg-alien-green animate-pulse" />
178133 </ div >
179134 < div ref = { terminalRef } className = "flex-1 p-8 font-mono text-[11px] space-y-4 overflow-y-auto max-h-[450px] scrollbar-hide" >
180135 { terminalHistory . map ( ( m , i ) => (
181136 < div key = { i } className = { m . type === 'ai' ? 'text-alien-green' : 'text-alien-gold/70' } >
182137 < span className = "opacity-40" > { m . type === 'ai' ? '>>>' : 'USR>' } </ span > { m . text }
183138 </ div >
184139 ) ) }
185- { isTyping && < div className = "text-alien-green animate-pulse" > _Sincronizando ...</ div > }
140+ { isTyping && < div className = "text-alien-green animate-pulse" > _Procesando ...</ div > }
186141 </ div >
187142 < form onSubmit = { handleTerminalSubmit } className = "p-6 bg-white/5 flex gap-4 border-t border-white/5" >
188143 < ChevronRight className = "text-alien-gold w-5 h-5" />
189- < input value = { terminalInput } onChange = { ( e ) => setTerminalInput ( e . target . value ) } className = "bg-transparent border-none outline-none flex-1 text-alien-gold text-xs font-mono" placeholder = "Ingresar comando de sistema ..." />
144+ < input value = { terminalInput } onChange = { ( e ) => setTerminalInput ( e . target . value ) } className = "bg-transparent border-none outline-none flex-1 text-alien-gold text-xs font-mono" placeholder = "Comando ..." />
190145 </ form >
191146 </ motion . div >
192147 </ div >
193148
194- { /* REDES SOCIALES ORDENADAS ALFABÉTICAMENTE */ }
149+ { /* REDES SOCIALES */ }
195150 < div className = "grid grid-cols-2 sm:grid-cols-3 md:grid-cols-5 gap-4" >
196151 { socialLinks . map ( ( item , i ) => (
197152 < motion . a
@@ -200,28 +155,15 @@ const Contact: React.FC = () => {
200155 initial = { { opacity : 0 , y : 15 } }
201156 animate = { { opacity : 1 , y : 0 } }
202157 transition = { { delay : i * 0.05 } }
203- whileHover = { ! item . comingSoon ? { scale : 1.05 , borderColor : '#39FF14' } : { } }
204158 className = { `p-6 rounded-[2rem] border flex flex-col items-center justify-center gap-4 transition-all ${
205- item . comingSoon
206- ? 'bg-white/[0.01] border-white/5 opacity-20 cursor-not-allowed'
207- : 'bg-white/[0.04] border-white/10 group'
159+ item . comingSoon ? 'opacity-20 cursor-not-allowed border-white/5' : 'bg-white/[0.04] border-white/10 group hover:border-alien-green'
208160 } `}
209161 >
210- < item . icon className = { `w-6 h-6 transition-all duration-500 ${
211- item . comingSoon ? 'text-gray-700' : 'text-gray-400 group-hover:text-alien-green group-hover:rotate-[360deg]'
212- } `} />
213- < div className = "text-center" >
214- < p className = { `text-[9px] font-nasalization uppercase tracking-widest ${
215- item . comingSoon ? 'text-gray-700' : 'text-gray-300 group-hover:text-white'
216- } `} >
217- { item . name }
218- </ p >
219- { item . comingSoon && < span className = "text-[7px] text-alien-gold font-bold block mt-1 tracking-tighter" > SOON</ span > }
220- </ div >
162+ < item . icon className = { `w-6 h-6 ${ item . comingSoon ? 'text-gray-700' : 'text-gray-400 group-hover:text-alien-green group-hover:rotate-[360deg]' } ` } />
163+ < p className = "text-[9px] font-nasalization uppercase tracking-widest text-gray-300" > { item . name } </ p >
221164 </ motion . a >
222165 ) ) }
223166 </ div >
224-
225167 </ main >
226168 </ div >
227169 ) ;
0 commit comments