11import React , { useState , useEffect } from 'react' ;
22import axios from 'axios' ;
33import { Container , Grid , Typography , Paper } from '@material-ui/core' ;
4+ import Card from '@material-ui/core/Card' ;
5+ import CardHeader from '@material-ui/core/CardHeader' ;
6+ import CardMedia from '@material-ui/core/CardMedia' ;
7+ import CardContent from '@material-ui/core/CardContent' ;
8+ import CardActions from '@material-ui/core/CardActions' ;
9+ import Button from '@material-ui/core/Button' ;
10+ import Dialog from '@material-ui/core/Dialog' ;
11+ import DialogTitle from '@material-ui/core/DialogTitle' ;
12+ import DialogContent from '@material-ui/core/DialogContent' ;
13+ import Snackbar from '@material-ui/core/Snackbar' ;
14+ import MuiAlert from '@material-ui/lab/Alert' ;
415import { Link } from 'react-router-dom' ;
516import { makeStyles } from '@material-ui/core/styles' ;
617import Avatar from '../components/Avatar' ;
718import EventCard from '../components/EventCard' ;
819import { hostname , ecats , images , execom , alumni } from '../links' ;
920import AlumniAccordions from '../components/AlumniAccordions' ;
1021import SpacyDivider from '../components/SpacyDivider' ;
22+ import { imagePath } from '../data/misc' ;
23+
24+ function Alert ( props ) {
25+ return < MuiAlert elevation = { 6 } variant = "filled" { ...props } /> ;
26+ }
27+
28+ // Hardcoded past-event entry: no admin/DB access is currently available to add this
29+ // through the normal Add Event flow, so it's blended into the Events grid manually here.
30+ const rosysseyEvent = {
31+ ename : 'ROSyssey - Journey into Robotics' ,
32+ eventstart : '2026-06-08T09:30:00' ,
33+ eventend : '2026-06-10T16:30:00' ,
34+ keywords : 'ROS2, Robotics, micro-ROS, ESP32' ,
35+ poster : `${ imagePath } /ras/rosyssey/rosyssey_4.jpg` ,
36+ details : `ROSyssey was a three-day hands-on robotics workshop conducted by the Robotics and Automation Society, IEEE RVCE Student Branch, at the Design Thinking Huddle, RV College of Engineering. It introduced 30 undergraduate participants to ROS2, micro-ROS, embedded systems integration, and mobile robot development, combining theory with hands-on implementation of a differential-drive rover platform.
37+
38+ Day 1 covered environment setup and ROS2 fundamentals. Day 2 covered ROS2 programming, micro-ROS on ESP32, and rover assembly. Day 3 focused on rover control, ROS2 velocity commands, encoder feedback, teleoperation, and IMU-based sensor fusion.
39+
40+ The workshop concluded with the NODE ZERO Capture the Flag (CTF) Challenge on 4 July 2026, an eight-level competitive event testing participants' proficiency in ROS2, micro-ROS, Linux, robot communication, debugging, and system integration.
41+
42+ Organized by the Robotics and Automation Society, IEEE RVCE Student Branch, with support from Astra Robotics RVCE.` ,
43+ gallery : [ 1 , 2 , 3 , 5 , 6 ] . map ( n => `${ imagePath } /ras/rosyssey/rosyssey_${ n } .jpg` ) ,
44+ } ;
1145
1246const useStyles = makeStyles ( theme => ( {
1347 root : theme . root ,
@@ -25,8 +59,88 @@ const useStyles = makeStyles(theme => ({
2559 margin : 'auto' ,
2660 paddingTop : theme . spacing ( 4 ) ,
2761 } ,
62+ eventcard : {
63+ ...theme . eventcard ,
64+ height : '100%' ,
65+ maxWidth : 345 ,
66+ margin : 'auto' ,
67+ '&:hover' : {
68+ boxShadow :
69+ '0px 5px 5px -3px rgba(0,0,0,0.2), 0px 8px 10px 1px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12)' ,
70+ transitionDuration : 200 ,
71+ } ,
72+ } ,
73+ media : {
74+ height : 0 ,
75+ paddingTop : '56.25%' ,
76+ } ,
2877} ) ) ;
2978
79+ // Visually matches EventCard exactly (same classes/markup), but "Read More" opens a dialog
80+ // with the full report instead of navigating to /events/:eid, since this entry has no
81+ // backend record to fetch. "Share" copies the RAS page link instead of a per-event link.
82+ function RosysseyEventCard ( ) {
83+ const classes = useStyles ( ) ;
84+ const [ dialogOpen , setDialogOpen ] = useState ( false ) ;
85+ const [ snackOpen , setSnackOpen ] = useState ( false ) ;
86+ const eventTimes = {
87+ start : new Date ( rosysseyEvent . eventstart ) ,
88+ end : new Date ( rosysseyEvent . eventend ) ,
89+ } ;
90+
91+ const handleShare = ( ) => {
92+ setSnackOpen ( true ) ;
93+ navigator . clipboard . writeText ( window . location . origin + '/#/society/ras' ) ;
94+ } ;
95+
96+ return (
97+ < >
98+ < Card title = { rosysseyEvent . ename } className = { classes . eventcard } >
99+ < CardHeader
100+ title = { rosysseyEvent . ename }
101+ subheader = { eventTimes . start . toString ( ) . slice ( 4 , 15 ) + ' to ' + eventTimes . end . toString ( ) . slice ( 4 , 15 ) }
102+ titleTypographyProps = { { noWrap : true } }
103+ />
104+ < CardMedia className = { classes . media } image = { rosysseyEvent . poster } title = { rosysseyEvent . ename } />
105+ < CardContent >
106+ < Typography variant = "body2" color = "textSecondary" component = "p" noWrap >
107+ Keywords: { rosysseyEvent . keywords }
108+ </ Typography >
109+ </ CardContent >
110+ < CardActions disableSpacing style = { { marginTop : 'auto' } } >
111+ < Button size = "small" onClick = { handleShare } >
112+ Share
113+ </ Button >
114+ < Snackbar open = { snackOpen } autoHideDuration = { 2000 } onClose = { ( ) => setSnackOpen ( false ) } >
115+ < Alert onClose = { ( ) => setSnackOpen ( false ) } severity = "success" >
116+ Link Copied!
117+ </ Alert >
118+ </ Snackbar >
119+ < Button size = "small" onClick = { ( ) => setDialogOpen ( true ) } >
120+ Read More
121+ </ Button >
122+ </ CardActions >
123+ </ Card >
124+ < Dialog open = { dialogOpen } onClose = { ( ) => setDialogOpen ( false ) } maxWidth = "md" fullWidth >
125+ < DialogTitle > { rosysseyEvent . ename } </ DialogTitle >
126+ < DialogContent >
127+ < Typography variant = "body1" style = { { whiteSpace : 'pre-line' } } >
128+ { rosysseyEvent . details }
129+ </ Typography >
130+ < br />
131+ < Grid container spacing = { 2 } >
132+ { rosysseyEvent . gallery . map ( src => (
133+ < Grid item xs = { 12 } sm = { 6 } md = { 4 } key = { src } >
134+ < img src = { src } alt = "ROSyssey workshop" style = { { width : '100%' , borderRadius : 4 , display : 'block' } } />
135+ </ Grid >
136+ ) ) }
137+ </ Grid >
138+ </ DialogContent >
139+ </ Dialog >
140+ </ >
141+ ) ;
142+ }
143+
30144export default function RASSocietyPage ( props ) {
31145 const classes = useStyles ( ) ;
32146
@@ -75,30 +189,29 @@ export default function RASSocietyPage(props) {
75189 </ Typography >
76190 </ Paper >
77191 < SpacyDivider color = "rgb(12 104 171)" />
78- { events . length !== 0 && (
79- < >
80- < Paper className = { classes . paper } >
81- < Typography variant = "h3" > Events</ Typography >
82- < br />
83- < Grid container spacing = { 2 } justify = "center" >
84- { events . slice ( 0 , 3 ) . map ( item => {
85- return (
86- < Grid item xs = { 12 } md = { 4 } >
87- < EventCard event = { item } />
88- </ Grid >
89- ) ;
90- } ) }
91- </ Grid >
92- < br />
93- { events . length >= 4 && (
94- < Link to = { '/events?ecat=' + ecats . ras } className = { classes . link } >
95- Click here for more events
96- </ Link >
97- ) }
98- </ Paper >
99- < SpacyDivider color = "rgb(12 104 171)" />
100- </ >
101- ) }
192+ < Paper className = { classes . paper } >
193+ < Typography variant = "h3" > Events</ Typography >
194+ < br />
195+ < Grid container spacing = { 2 } justify = "center" >
196+ < Grid item xs = { 12 } md = { 4 } >
197+ < RosysseyEventCard />
198+ </ Grid >
199+ { events . slice ( 0 , 2 ) . map ( item => {
200+ return (
201+ < Grid item xs = { 12 } md = { 4 } >
202+ < EventCard event = { item } />
203+ </ Grid >
204+ ) ;
205+ } ) }
206+ </ Grid >
207+ < br />
208+ { events . length >= 3 && (
209+ < Link to = { '/events?ecat=' + ecats . ras } className = { classes . link } >
210+ Click here for more events
211+ </ Link >
212+ ) }
213+ </ Paper >
214+ < SpacyDivider color = "rgb(12 104 171)" />
102215 < Paper className = { classes . paper } >
103216 < Typography variant = "h3" > Executive Committee</ Typography >
104217 < br />
0 commit comments