1- import React , { type ReactNode , useState , useEffect } from ' react' ;
1+ import React , { type ReactNode , useState , useEffect } from " react" ;
22import Link from "@docusaurus/Link" ;
3- import type { Props } from ' @theme/Footer/Layout' ;
4- import ' ./enhanced-footer.css' ;
5- import Counter from ' ./Counter' ;
3+ import type { Props } from " @theme/Footer/Layout" ;
4+ import " ./enhanced-footer.css" ;
5+ import Counter from " ./Counter" ;
66import { createPortal } from "react-dom" ;
77
8-
98// Dynamic stats interface
109interface FooterStats {
1110 activeUsers : string ;
@@ -14,6 +13,8 @@ interface FooterStats {
1413 supportHours : string ;
1514}
1615
16+ const emailRegex = / ^ [ ^ \s @ ] + @ [ ^ \s @ ] + \. [ ^ \s @ ] + $ / ;
17+
1718export default function FooterLayout ( {
1819 style,
1920 links,
@@ -22,14 +23,15 @@ export default function FooterLayout({
2223} : Props ) : ReactNode {
2324 const [ currentYear , setCurrentYear ] = useState ( new Date ( ) . getFullYear ( ) ) ;
2425 const [ stats , setStats ] = useState < FooterStats > ( {
25- activeUsers : ' 50K+' ,
26- tutorials : ' 200+' ,
27- successRate : ' 95%' ,
28- supportHours : ' 24/7'
26+ activeUsers : " 50K+" ,
27+ tutorials : " 200+" ,
28+ successRate : " 95%" ,
29+ supportHours : " 24/7" ,
2930 } ) ;
30- const [ email , setEmail ] = useState ( '' ) ;
31+ const [ email , setEmail ] = useState ( "" ) ;
3132 const [ isSubscribed , setIsSubscribed ] = useState ( false ) ;
3233 const [ showToast , setShowToast ] = useState ( false ) ;
34+ const [ error , setError ] = useState ( "" ) ;
3335
3436 useEffect ( ( ) => {
3537 // Simulate real-time stats updates
@@ -44,36 +46,46 @@ export default function FooterLayout({
4446 activeUsers : `${ Math . floor ( ( baseUsers + randomGrowth ) / 1000 ) } K+` ,
4547 tutorials : `${ baseTutorials + Math . floor ( randomGrowth / 10 ) } +` ,
4648 successRate : `${ 95 + Math . floor ( Math . random ( ) * 3 ) } %` ,
47- supportHours : ' 24/7'
49+ supportHours : " 24/7" ,
4850 } ) ;
4951 } catch ( error ) {
50- console . log ( ' Using fallback stats' ) ;
52+ console . log ( " Using fallback stats" ) ;
5153 }
5254 } ;
5355
5456 fetchStats ( ) ;
5557 const interval = setInterval ( fetchStats , 30000 ) ; // Update every 30 seconds
56-
58+
5759 return ( ) => clearInterval ( interval ) ;
5860 } , [ ] ) ;
59-
61+
6062 const handleSubscribe = ( e : React . FormEvent ) => {
6163 e . preventDefault ( ) ;
62- if ( email ) {
63- setIsSubscribed ( true ) ;
64- setShowToast ( true ) ;
65-
66- // Hide toast after 3 seconds
67- setTimeout ( ( ) => {
68- setShowToast ( false ) ;
69- } , 3000 ) ;
70-
71- // Reset form after 3 seconds
72- setTimeout ( ( ) => {
73- setIsSubscribed ( false ) ;
74- setEmail ( '' ) ;
75- } , 3000 ) ;
64+
65+ if ( ! email ) {
66+ setError ( "Email is required" ) ;
67+ return ;
7668 }
69+
70+ if ( ! emailRegex . test ( email ) ) {
71+ setError ( "Please enter a valid email address" ) ;
72+ return ;
73+ }
74+
75+ setError ( "" ) ;
76+ setIsSubscribed ( true ) ;
77+ setShowToast ( true ) ;
78+
79+ // Hide toast after 3 seconds
80+ setTimeout ( ( ) => {
81+ setShowToast ( false ) ;
82+ } , 3000 ) ;
83+
84+ // Reset form after 3 seconds
85+ setTimeout ( ( ) => {
86+ setIsSubscribed ( false ) ;
87+ setEmail ( "" ) ;
88+ } , 3000 ) ;
7789 } ;
7890
7991 return (
@@ -343,7 +355,10 @@ export default function FooterLayout({
343355344356 className = "newsletter-input"
345357 value = { email }
346- onChange = { ( e ) => setEmail ( e . target . value ) }
358+ onChange = { ( e ) => {
359+ setEmail ( e . target . value ) ;
360+ setError ( "" ) ;
361+ } }
347362 required
348363 />
349364 < button
@@ -355,6 +370,7 @@ export default function FooterLayout({
355370 >
356371 { isSubscribed ? "✓ Subscribed!" : "Subscribe Now →" }
357372 </ button >
373+ { error && < p className = "error-text" > { error } </ p > }
358374 </ form >
359375 < div className = "newsletter-stats" >
360376 < span className = "newsletter-stat" >
@@ -461,4 +477,4 @@ export default function FooterLayout({
461477 </ div >
462478 </ footer >
463479 ) ;
464- }
480+ }
0 commit comments