+
+
+ {/* ββ Section Header ββ */}
+
+
+
+
+ {/* ββ Filter Tabs ββ */}
+
+
+ {(['upcoming', 'past'] as SortOrder[]).map((tab) => {
+ const count = tab === 'upcoming' ? upcomingCount : pastCount;
+ const isActive = filter === tab;
+ return (
+ setFilter(tab)}
+ className="flex items-center gap-2 px-5 py-2 rounded-full font-montserrat text-sm font-semibold transition-all duration-200 cursor-pointer"
+ style={{
+ background: isActive ? '#FFD670' : 'rgba(255,255,255,0.06)',
+ color: isActive ? '#2C3844' : '#9ca3af',
+ border: isActive ? '1.5px solid #FFD670' : '1.5px solid rgba(255,255,255,0.1)',
+ }}
+ >
+ {tab.charAt(0).toUpperCase() + tab.slice(1)}
+
+ {count}
+
+
+ );
+ })}
+
+
+
+ {/* ββ Loading State ββ */}
+ {loading && (
+
+ )}
+
+ {/* ββ Error State ββ */}
+ {error && !loading && (
+
+ Failed to load events. Please try again later.
+
+ )}
+
+ {/* ββ Events Grid ββ */}
+ {!loading && !error && filteredEvents.length > 0 && (
+
+ {filteredEvents.map((event, idx) => (
+
+ ))}
+
+ )}
+
+ {/* ββ Empty State ββ */}
+ {!loading && !error && filteredEvents.length === 0 && (
+
+
+
π
+
+ No {filter} events right now
+
+
+ {filter === 'upcoming'
+ ? "Check back soon β we've got exciting things planned!"
+ : "Past events will appear here once they've wrapped up."}
+
+
+
+ )}
+
+
+ );
+}
+
+export default EventsList;
diff --git a/src/components/hero/HTMLBox.tsx b/src/components/hero/HTMLBox.tsx
index e496111..ef90eee 100644
--- a/src/components/hero/HTMLBox.tsx
+++ b/src/components/hero/HTMLBox.tsx
@@ -1,8 +1,14 @@
import "../styles/fadeSlideUpAnimation.css";
+import RevealOnScroll from "../universal/RevealOnScroll";
const HTMLBox = () => {
return (
-
+
{/* Bracket SVG - Left */}
@@ -74,7 +80,7 @@ const HTMLBox = () => {
-
+
);
};
diff --git a/src/components/hero/Stats.tsx b/src/components/hero/Stats.tsx
index 16aa5fb..2d904ec 100644
--- a/src/components/hero/Stats.tsx
+++ b/src/components/hero/Stats.tsx
@@ -1,10 +1,12 @@
/**
* Stats Component
* Displays key club statistics with animated count-up effects
+ * Now with scroll-reveal - animations trigger when scrolled into view!
*/
import { useEffect, useState } from 'react';
import CountUp from 'react-countup';
+import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
/**
* Individual stat item configuration
@@ -43,18 +45,27 @@ const statsData: StatItem[] = [
export const Stats = () => {
const [startAnimation, setStartAnimation] = useState(false);
- // Trigger animation on component mount
+ // Detect when Stats component scrolls into view
+ const { ref, isVisible } = useIntersectionObserver({
+ rootMargin: '50px',
+ threshold: 0.1,
+ once: true,
+ });
+
+ // Trigger animation when component is visible
useEffect(() => {
- // Small delay for smoother visual experience
- const timer = setTimeout(() => {
- setStartAnimation(true);
- }, 100);
+ if (isVisible) {
+ // Small delay for smoother visual experience
+ const timer = setTimeout(() => {
+ setStartAnimation(true);
+ }, 100);
- return () => clearTimeout(timer);
- }, []);
+ return () => clearTimeout(timer);
+ }
+ }, [isVisible]);
return (
-
+
{/* Stats Grid - flex row mobile, 3 columns desktop */}
{statsData.map((stat, index) => (
diff --git a/src/components/hero/Welcome.tsx b/src/components/hero/Welcome.tsx
index 0176966..76bb33f 100644
--- a/src/components/hero/Welcome.tsx
+++ b/src/components/hero/Welcome.tsx
@@ -2,10 +2,13 @@
* Welcome Component
* Displays "WELCOME TO" using decorative letter assets arranged in a scrapbook style,
* followed by "Laurier Computing Society"
+ *
+ * Now with scroll-reveal animations!
*/
import ScrapbookText from '../universal/ScrapbookText';
import Mascots from '../universal/Mascots';
+import RevealOnScroll from '../universal/RevealOnScroll';
import '../styles/fadeSlideUpAnimation.css';
/**
@@ -22,12 +25,18 @@ export const Welcome: React.FC = () => {
{/* Laurier Computing Society Text */}
-
- LAURIER COMPUTING SOCIETY
-
+
+ LAURIER COMPUTING SOCIETY
+
+
{/* Mascots Section */}
diff --git a/src/components/initiatives/MeetThePros.tsx b/src/components/initiatives/MeetThePros.tsx
index 0f46ead..1969f40 100644
--- a/src/components/initiatives/MeetThePros.tsx
+++ b/src/components/initiatives/MeetThePros.tsx
@@ -1,5 +1,6 @@
import ScrapbookText from "../universal/ScrapbookText";
import ImageGallery from "../universal/ImageGallery";
+import RevealOnScroll from "../universal/RevealOnScroll";
export default function MeetThePros() {
// Image gallery data for Meet the Pros events
@@ -17,30 +18,47 @@ export default function MeetThePros() {
-
+
+
PROFESSIONALS
-
+
+
-
+
+
Our flagship event bringing together professionals from different fields to give students a first hand retelling of the field and provide them with advice.
We bring out the coolest guest speakers from the tech industry and giving you a chance to ask questions, hear their experience, and even make meaningful connections.
-
+
+
{/* Image Gallery */}
-
-
-
+
+
+
);
diff --git a/src/components/initiatives/SignUpForm.tsx b/src/components/initiatives/SignUpForm.tsx
deleted file mode 100644
index f83cdae..0000000
--- a/src/components/initiatives/SignUpForm.tsx
+++ /dev/null
@@ -1,201 +0,0 @@
-import { useState } from 'react';
-import FormField from './FormField';
-import { EXPERIENCE_OPTIONS, FORM_COLORS } from './formConstants';
-
-interface SignUpFormProps {
- onClose: () => void;
- isOpen: boolean;
-}
-
-export default function SignUpForm({ onClose, isOpen }: SignUpFormProps) {
- const [formData, setFormData] = useState({
- fullName: '',
- email: '',
- phone: '',
- topic: '',
- experience: '',
- bio: '',
- });
-
- const [isSubmitting, setIsSubmitting] = useState(false);
- const [submitMessage, setSubmitMessage] = useState('');
-
- const handleChange = (e: React.ChangeEvent
) => {
- const { name, value } = e.target;
- setFormData(prev => ({
- ...prev,
- [name]: value
- }));
- };
-
- const handleSubmit = async (e: React.FormEvent) => {
- e.preventDefault();
- setIsSubmitting(true);
- setSubmitMessage('');
-
- try {
- // Here you can add your Firebase submission logic
- console.log('Form submitted:', formData);
- setSubmitMessage('Thank you for signing up! We will contact you soon.');
- setTimeout(() => {
- setFormData({
- fullName: '',
- email: '',
- phone: '',
- topic: '',
- experience: '',
- bio: '',
- });
- onClose();
- }, 2000);
- } catch (error) {
- console.error('Error submitting form:', error);
- setSubmitMessage('An error occurred. Please try again.');
- } finally {
- setIsSubmitting(false);
- }
- };
-
- if (!isOpen) return null;
-
- return (
- <>
- {/* Modal */}
-
-
- {/* Header */}
-
-
- SPEAKER SIGN UP
-
-
- β
-
-
-
- {/* Form Content */}
-
-
-
-
-
- >
- );
-}
\ No newline at end of file
diff --git a/src/components/initiatives/SpeakerSignUp.tsx b/src/components/initiatives/SpeakerSignUp.tsx
index 78a7b7e..8ec4f4c 100644
--- a/src/components/initiatives/SpeakerSignUp.tsx
+++ b/src/components/initiatives/SpeakerSignUp.tsx
@@ -1,14 +1,12 @@
-import { useState } from 'react';
+import RevealOnScroll from '../universal/RevealOnScroll';
import { Mascots } from '../universal/Mascots';
-import SignUpForm from './SignUpForm';
export default function SpeakerSignup() {
- const [isFormOpen, setIsFormOpen] = useState(false);
-
return (
<>
-
-
+
+
+
{/* Doug Mascot positioned to pop out of top and clip at bottom - trying */}
@@ -21,11 +19,13 @@ export default function SpeakerSignup() {
WANT TO BE A SPEAKER AT OUR NEXT MTP SESSION?
- We'd love to hear from anyone eager to inform the youth of today about the dangers of the outside world [employement]. Click the button below and sign up to attend our next session!
+ We'd love to hear from anyone eager to inform the youth of today about the dangers of the outside world [employment]. Click the button below and sign up to attend our next session!
-
- {/* Popup Form Modal */}
- setIsFormOpen(false)} />
+
>
);
}
diff --git a/src/components/styles/fadeSlideUpAnimation.css b/src/components/styles/fadeSlideUpAnimation.css
index 04a264a..47d96d7 100644
--- a/src/components/styles/fadeSlideUpAnimation.css
+++ b/src/components/styles/fadeSlideUpAnimation.css
@@ -17,4 +17,21 @@
transform: translateY(20px);
animation: fadeSlideUpFromBottom 0.8s ease-out forwards;
animation-delay: 0.3s;
+}
+
+/* Faster version for scroll-reveal components (no delay, quicker animation) */
+@keyframes fadeSlideUpFast {
+ from {
+ opacity: 0;
+ transform: translateY(20px);
+ }
+
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.fadeSlideUpFast {
+ animation: fadeSlideUpFast 0.5s ease-out forwards;
}
\ No newline at end of file
diff --git a/src/components/team/TeamCard.tsx b/src/components/team/TeamCard.tsx
index 8f26c4b..1e5703a 100644
--- a/src/components/team/TeamCard.tsx
+++ b/src/components/team/TeamCard.tsx
@@ -4,6 +4,8 @@
* Styled with dark theme and accent color hover effects
*/
+import RevealOnScroll from '../universal/RevealOnScroll';
+
interface TeamMember {
id: string;
name: string;
@@ -50,12 +52,13 @@ export function TeamCard({ member }: TeamCardProps) {
const accentColor = accentColorMap[colorIndex];
return (
-
- {/* Image Container - Circular with colored border */}
-
+
+
+ {/* Image Container - Circular with colored border */}
+
{member.picture_url ? (
)}
-
+
- {/* Info Section */}
-
- {/* Member Name */}
-
- {member.name}
-
-
- {/* Member Role */}
- {member.role && (
-
- {member.role}
-
- )}
+ {/* Info Section */}
+
+ {/* Member Name */}
+
+ {member.name}
+
+
+ {/* Member Role */}
+ {member.role && (
+
+ {member.role}
+
+ )}
- {/* Social Links Container */}
- {(member.github_url || member.linkedin_url) && (
-
- {/* GitHub Link */}
- {showGithub && member.github_url && (
-
-
-
- )}
+ {/* Social Links Container */}
+ {(member.github_url || member.linkedin_url) && (
+
+ {/* GitHub Link */}
+ {showGithub && member.github_url && (
+
+
+
+ )}
- {/* LinkedIn Link */}
- {showLinkedin && member.linkedin_url && (
-
-
-
- )}
-
- )}
+ {/* LinkedIn Link */}
+ {showLinkedin && member.linkedin_url && (
+
+
+
+ )}
+
+ )}
+
-
+
);
}
diff --git a/src/components/universal/Mascots.tsx b/src/components/universal/Mascots.tsx
index 970a8b6..e99b26d 100644
--- a/src/components/universal/Mascots.tsx
+++ b/src/components/universal/Mascots.tsx
@@ -2,9 +2,12 @@
* Mascots Component
* Displays the three mascot characters (Coco, Doug, Krill) in an overlapping arrangement
* Similar to ScrapbookText but with mascot SVGs instead of letters
+ *
+ * Now supports scroll-reveal animations - mascots animate when scrolled into view!
*/
import React, { useMemo } from 'react';
+import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
import '../styles/scrapbookAnimations.css';
interface MascotsProps {
@@ -46,6 +49,7 @@ interface MascotItemProps {
size: number;
overlapAmount: number;
mascotIndex: number;
+ isVisible?: boolean; // Whether element is visible in viewport
}
const MascotItem: React.FC
= ({
@@ -58,6 +62,7 @@ const MascotItem: React.FC = ({
size,
overlapAmount,
mascotIndex,
+ isVisible = true,
}) => {
const staggerDelay = mascotIndex * 120; // 120ms stagger between mascots
@@ -69,7 +74,7 @@ const MascotItem: React.FC = ({
transition: 'transform 0.2s ease-out',
marginRight: `-${overlapAmount}px`,
zIndex,
- animation: `mascotAppear 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) ${staggerDelay}ms both`,
+ animation: isVisible ? `mascotAppear 0.7s cubic-bezier(0.34, 1.56, 0.64, 1) ${staggerDelay}ms both` : 'none',
}}
>
= ({
// Track window width for responsive sizing
const [isMobile, setIsMobile] = React.useState(false);
+ // Observer for scroll-reveal animation
+ const { ref, isVisible } = useIntersectionObserver({
+ rootMargin: '50px',
+ threshold: 0.1,
+ once: true,
+ });
+
React.useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth < 768);
checkMobile();
@@ -122,7 +134,7 @@ export const Mascots: React.FC = ({
}, []);
return (
-
+
{displayedMascots.map((mascot, index) => (
= ({
zIndex={index + 1}
size={responsiveMascotSize}
overlapAmount={overlapAmount}
+ isVisible={isVisible}
/>
))}
diff --git a/src/components/universal/RevealOnScroll.tsx b/src/components/universal/RevealOnScroll.tsx
new file mode 100644
index 0000000..78d4391
--- /dev/null
+++ b/src/components/universal/RevealOnScroll.tsx
@@ -0,0 +1,92 @@
+/**
+ * RevealOnScroll Wrapper Component
+ *
+ * Wraps animated content and only applies animation classes when scrolled into view.
+ * Works seamlessly with existing animation classes like fadeSlideUpFromBottom,
+ * scrapbookLetterAppear, mascotAppear, etc.
+ *
+ * @example
+ *
+ * Heading
+ *
+ */
+
+import React, { type ReactNode } from 'react';
+import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
+
+interface RevealOnScrollProps {
+ /**
+ * The content to reveal on scroll
+ */
+ children: ReactNode;
+
+ /**
+ * CSS class(es) to apply when element is visible
+ * Can include animation classes like 'fadeSlideUpFromBottom'
+ */
+ visibleClassName?: string;
+
+ /**
+ * CSS class to apply when element is not visible (for paused state)
+ */
+ hiddenClassName?: string;
+
+ /**
+ * Additional CSS classes for the container
+ */
+ className?: string;
+
+ /**
+ * How close to viewport edge should animation trigger (default: '0px')
+ * Examples: '100px' triggers 100px before entering, '-50px' triggers 50px after entering
+ */
+ rootMargin?: string;
+
+ /**
+ * Visibility threshold (0-1, default: 0.1)
+ * 0 = any part visible, 1 = entire element visible
+ */
+ threshold?: number | number[];
+
+ /**
+ * If true, animation plays only once on first scroll into view (default: true)
+ */
+ once?: boolean;
+
+ /**
+ * Wrapper element type (default: 'div')
+ */
+ as?: React.ElementType;
+}
+
+/**
+ * RevealOnScroll Component
+ * Utility wrapper for scroll-reveal animations
+ */
+export const RevealOnScroll: React.FC
= ({
+ children,
+ visibleClassName = '',
+ hiddenClassName = '',
+ className = '',
+ rootMargin = '0px',
+ threshold = 0.1,
+ once = true,
+ as: Component = 'div',
+}) => {
+ const { ref, isVisible } = useIntersectionObserver({
+ rootMargin,
+ threshold,
+ once,
+ });
+
+ const animationClass = isVisible ? visibleClassName : hiddenClassName;
+ const combinedClassName = `${className} ${animationClass}`.trim();
+
+ return (
+
+ {children}
+
+ );
+};
+
+export default RevealOnScroll;
diff --git a/src/components/universal/ScrapbookText.tsx b/src/components/universal/ScrapbookText.tsx
index 9d06d78..3e48d0a 100644
--- a/src/components/universal/ScrapbookText.tsx
+++ b/src/components/universal/ScrapbookText.tsx
@@ -2,9 +2,12 @@
* ScrapbookText Component
* Universal component for displaying text in scrapbook style using letter assets
* Supports letters: A, C, D, E, F, G, H, I, K, L, M, N, O, P, R, S, T, U, V, W
+ *
+ * Now supports scroll-reveal animations - letters animate when scrolled into view!
*/
import React, { useMemo } from 'react';
+import { useIntersectionObserver } from '../../hooks/useIntersectionObserver';
import '../styles/scrapbookAnimations.css';
interface ScrapbookTextProps {
@@ -83,6 +86,7 @@ interface ScrapbookLetterProps {
zIndex: number;
size: number;
letterClassName?: string;
+ isVisible?: boolean; // Whether element is visible in viewport
}
const ScrapbookLetter: React.FC = ({
@@ -94,6 +98,7 @@ const ScrapbookLetter: React.FC
size,
letterClassName,
letterIndex,
+ isVisible = true,
}) => {
const assetPath = letterAssets[letter];
const staggerDelay = letterIndex * 60; // 60ms stagger between letters
@@ -110,7 +115,7 @@ const ScrapbookLetter: React.FC
>
= ({
// Track window width for responsive sizing
const [isMobile, setIsMobile] = React.useState(false);
+ // Observer for scroll-reveal animation
+ const { ref, isVisible } = useIntersectionObserver({
+ rootMargin: '50px',
+ threshold: 0.1,
+ once: true,
+ });
+
React.useEffect(() => {
const checkMobile = () => setIsMobile(window.innerWidth < 768);
checkMobile();
@@ -164,7 +176,7 @@ export const ScrapbookText: React.FC
= ({
}, [uppercaseText]);
return (
-
+
{uppercaseText.split('').map((char, index) => {
if (char === ' ') {
return (
@@ -191,6 +203,7 @@ export const ScrapbookText: React.FC
= ({
scale={transform.scale}
size={responsiveLetterSize}
letterClassName={letterClassName}
+ isVisible={isVisible}
/>
);
})}
diff --git a/src/data/eventsData.ts b/src/data/eventsData.ts
deleted file mode 100644
index 32bf03b..0000000
--- a/src/data/eventsData.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * Sample Events Data
- * Edit this file to add/remove/modify events
- */
-
-export interface EventData {
- id: string;
- title: string;
- description: string;
- date: string;
- time: string;
- location: string;
- image: string;
-}
-
-// Placeholder images from Unsplash (tech/coding themed)
-const placeholderImages = {
- coding: 'https://images.unsplash.com/photo-1517694712202-14dd9538aa97?w=800&q=80',
- lecture: 'https://images.unsplash.com/photo-1524178232363-1fb2b075b655?w=800&q=80',
- networking: 'https://images.unsplash.com/photo-1515187029135-18ee286d815b?w=800&q=80',
- workshop: 'https://images.unsplash.com/photo-1531482615713-2afd69097998?w=800&q=80',
-};
-
-export const eventsData: EventData[] = [
- {
- id: 'cp164-review',
- title: 'CP164 Midterm Review',
- description:
- 'An interactive midterm review session for computer science students taking the essential first year course, Data Structures (CP164). Refresh your knowledge of key concepts in a lively and interactive format!',
- date: 'February 11, 2026',
- time: '7:30 PM - 9:00 PM',
- location: 'Lazaridis Hall, Waterloo Campus',
- image: placeholderImages.coding,
- },
- {
- id: 'cp264-review',
- title: 'CP264 Midterm Review',
- description:
- 'A comprehensive review session for Data Structures II (CP264). Engage with the material through mini quizzes and win exciting prizes while preparing for your midterm!',
- date: 'February 18, 2026',
- time: '7:30 PM - 9:00 PM',
- location: 'Science Building, Waterloo Campus',
- image: placeholderImages.lecture,
- },
- {
- id: 'meet-the-pros',
- title: 'Meet The Professionals',
- description:
- 'Our flagship event bringing together industry professionals from different fields. Get first-hand insights about the tech industry and make meaningful connections.',
- date: 'March 5, 2026',
- time: '6:00 PM - 8:30 PM',
- location: 'Arts Building Atrium',
- image: placeholderImages.networking,
- },
- {
- id: 'coding-workshop',
- title: 'React Workshop',
- description:
- 'Hands-on workshop covering React fundamentals, hooks, and best practices. Perfect for beginners looking to level up their frontend development skills.',
- date: 'March 12, 2026',
- time: '5:00 PM - 7:00 PM',
- location: 'Computer Lab, Lazaridis Hall',
- image: placeholderImages.workshop,
- },
-];
-
-export default eventsData;
diff --git a/src/hooks/useIntersectionObserver.ts b/src/hooks/useIntersectionObserver.ts
new file mode 100644
index 0000000..5a253f7
--- /dev/null
+++ b/src/hooks/useIntersectionObserver.ts
@@ -0,0 +1,70 @@
+import { useEffect, useRef, useState } from 'react';
+
+interface UseIntersectionObserverOptions {
+ /**
+ * Margin around the target element to trigger the callback (default: '0px')
+ * Example: '100px' would trigger when element is 100px away from viewport edge
+ */
+ rootMargin?: string;
+ /**
+ * Threshold of visibility required to trigger (0-1, default: 0.1)
+ * 0 = any part visible, 1 = entire element visible
+ */
+ threshold?: number | number[];
+ /**
+ * If true, observer will disconnect after first intersection (default: false)
+ * Useful if you only want animation to play once on scroll into view
+ */
+ once?: boolean;
+}
+
+/**
+ * Custom hook to detect when an element enters the viewport
+ * Perfect for scroll-reveal animations and lazy loading
+ *
+ * @example
+ * const { ref, isVisible } = useIntersectionObserver();
+ * return (
+ *
+ * Content here
+ *
+ * );
+ */
+export function useIntersectionObserver(options: UseIntersectionObserverOptions = {}) {
+ const { rootMargin = '0px', threshold = 0.1, once = false } = options;
+ const ref = useRef(null);
+ const [isVisible, setIsVisible] = useState(false);
+
+ useEffect(() => {
+ const observer = new IntersectionObserver(
+ ([entry]) => {
+ if (entry.isIntersecting) {
+ setIsVisible(true);
+ // Disconnect after first intersection if 'once' is true
+ if (once && ref.current) {
+ observer.unobserve(ref.current);
+ }
+ } else if (!once) {
+ // If not in 'once' mode, allow animation to replay when scrolling back
+ setIsVisible(false);
+ }
+ },
+ {
+ rootMargin,
+ threshold,
+ }
+ );
+
+ if (ref.current) {
+ observer.observe(ref.current);
+ }
+
+ return () => {
+ if (ref.current) {
+ observer.unobserve(ref.current);
+ }
+ };
+ }, [rootMargin, threshold, once]);
+
+ return { ref, isVisible };
+}
diff --git a/src/pages/Events.tsx b/src/pages/Events.tsx
index 4173bf7..52e90f5 100644
--- a/src/pages/Events.tsx
+++ b/src/pages/Events.tsx
@@ -1,53 +1,10 @@
/**
* Events Page
- * Displays upcoming events with interactive gallery and synchronized details
+ * Displays events fetched from Supabase via EventsList component.
*/
-import { useState } from 'react';
-import EventDetails from '../components/events/EventDetails';
-import EventGallery from '../components/events/EventGallery';
-import ScrapbookText from '../components/universal/ScrapbookText';
-import { eventsData } from '../data/eventsData';
-import '../components/styles/fadeSlideUpAnimation.css';
+import { EventsList } from '../components/events/EventsList';
export default function Events() {
- const [currentEventIndex, setCurrentEventIndex] = useState(0);
- const currentEvent = eventsData[currentEventIndex];
-
- return (
-
-
- {/* Section Header */}
-
-
-
-
- {/* Main Content: Two-column layout */}
-
- {/* Left: Event Details */}
-
-
-
-
- {/* Right: Event Gallery */}
-
-
-
-
-
-
- );
+ return ;
}