@@ -436,19 +436,45 @@ interface ContextData {
436436 } ;
437437}
438438
439+ // Helper function to extract search terms from user message
440+ function extractSearchTerms ( message : string ) : string [ ] {
441+ const stopWords = [ 'a' , 'an' , 'the' , 'in' , 'on' , 'at' , 'for' , 'to' , 'of' , 'with' , 'by' , 'about' , 'is' , 'are' , 'was' , 'were' , 'be' , 'been' , 'being' , 'have' , 'has' , 'had' , 'do' , 'does' , 'did' , 'can' , 'could' , 'will' , 'would' , 'shall' , 'should' , 'may' , 'might' , 'must' , 'show' , 'me' , 'tell' , 'list' , 'find' , 'search' , 'looking' , 'any' , 'some' , 'all' , 'what' , 'where' , 'when' , 'who' , 'why' , 'how' , 'event' , 'events' , 'hackathon' , 'hackathons' ] ;
442+
443+ const words = message . toLowerCase ( )
444+ . replace ( / [ ^ \w \s ] / g, '' ) // Remove punctuation
445+ . split ( / \s + / ) ;
446+
447+ return words . filter ( word => ! stopWords . includes ( word ) && word . length > 2 ) ;
448+ }
449+
439450// Database service functions
440- async function getEvents ( limit = 10 ) {
451+ async function getEvents ( limit = 10 , searchTerms : string [ ] = [ ] ) {
441452 try {
442453 const supabase = getSupabaseClient ( ) ;
443- const { data, error } = await supabase
454+ const today = new Date ( ) . toISOString ( ) ;
455+
456+ let query = supabase
444457 . from ( 'events' )
445458 . select ( `
446459 id, slug, title, description, excerpt, date, time, duration,
447460 location, locations, status, event_type, registration_deadline,
448461 capacity, registered, category, categories, tags, price, organizer
449462 ` )
450463 . eq ( 'status' , 'live' )
451- . order ( 'date' , { ascending : false } )
464+ . gte ( 'date' , today ) ; // Only future events
465+
466+ // Apply search filters if terms exist
467+ if ( searchTerms . length > 0 ) {
468+ const orConditions = searchTerms . map ( term =>
469+ `title.ilike.%${ term } %,description.ilike.%${ term } %,location.ilike.%${ term } %`
470+ ) . join ( ',' ) ;
471+
472+ // Note: This is a simple OR search. For more complex search, we might need textSearch or RPC
473+ query = query . or ( orConditions ) ;
474+ }
475+
476+ const { data, error } = await query
477+ . order ( 'date' , { ascending : true } ) // Show nearest upcoming events first
452478 . limit ( limit ) ;
453479
454480 if ( error ) throw error ;
@@ -459,10 +485,12 @@ async function getEvents(limit = 10) {
459485 }
460486}
461487
462- async function getHackathons ( limit = 10 ) {
488+ async function getHackathons ( limit = 10 , searchTerms : string [ ] = [ ] ) {
463489 try {
464490 const supabase = getSupabaseClient ( ) ;
465- const { data, error } = await supabase
491+ const today = new Date ( ) . toISOString ( ) ;
492+
493+ let query = supabase
466494 . from ( 'hackathons' )
467495 . select ( `
468496 id, slug, title, description, excerpt, date, time, duration,
@@ -471,7 +499,19 @@ async function getHackathons(limit = 10) {
471499 price, organizer, prize, prize_details, team_size
472500 ` )
473501 . eq ( 'status' , 'live' )
474- . order ( 'date' , { ascending : true } )
502+ . gte ( 'date' , today ) ; // Only future hackathons
503+
504+ // Apply search filters if terms exist
505+ if ( searchTerms . length > 0 ) {
506+ const orConditions = searchTerms . map ( term =>
507+ `title.ilike.%${ term } %,description.ilike.%${ term } %,location.ilike.%${ term } %`
508+ ) . join ( ',' ) ;
509+
510+ query = query . or ( orConditions ) ;
511+ }
512+
513+ const { data, error } = await query
514+ . order ( 'date' , { ascending : true } ) // Show nearest upcoming hackathons first
475515 . limit ( limit ) ;
476516
477517 if ( error ) throw error ;
@@ -657,13 +697,18 @@ async function getContextualData(userMessage: string, context: string, userId?:
657697 return data ;
658698 }
659699
700+ // Extract search terms for smarter data retrieval
701+ const searchTerms = extractSearchTerms ( message ) ;
702+ console . log ( '🔍 Extracted search terms:' , searchTerms ) ;
703+
660704 // Get specific data based on context and message content
661705 if ( message . includes ( 'event' ) || context === 'events' ) {
662- data . events = await getEvents ( 5 ) ;
706+ data . events = await getEvents ( 5 , searchTerms ) ;
663707 }
664708
665709 if ( message . includes ( 'hackathon' ) || context === 'hackathons' ) {
666- data . hackathons = await getHackathons ( 5 ) ;
710+ data . hackathons = await getHackathons ( 5 , searchTerms ) ;
711+ console . log ( `🔍 Found ${ data . hackathons . length } hackathons matching terms:` , searchTerms ) ;
667712 }
668713
669714 if ( message . includes ( 'internship' ) || message . includes ( 'job' ) || message . includes ( 'opportunity' ) || context === 'opportunities' ) {
@@ -676,8 +721,16 @@ async function getContextualData(userMessage: string, context: string, userId?:
676721
677722 // If no specific context, get a bit of everything for comprehensive answers EXCEPT internships
678723 if ( context === 'general' && Object . keys ( data ) . length === 1 ) {
679- data . events = await getEvents ( 3 ) ;
680- data . hackathons = await getHackathons ( 3 ) ;
724+ // If we have specific search terms, try to find matching events/hackathons even in general context
725+ if ( searchTerms . length > 0 ) {
726+ data . events = await getEvents ( 3 , searchTerms ) ;
727+ data . hackathons = await getHackathons ( 3 , searchTerms ) ;
728+ console . log ( `🔍 General Search - Found ${ data . events . length } events and ${ data . hackathons . length } hackathons` ) ;
729+ } else {
730+ data . events = await getEvents ( 3 ) ;
731+ data . hackathons = await getHackathons ( 3 ) ;
732+ }
733+
681734 data . blogs = await getBlogs ( 3 ) ;
682735 // Only include internships if the message specifically mentions them
683736 if ( message . includes ( 'internship' ) || message . includes ( 'job' ) || message . includes ( 'opportunity' ) ) {
@@ -841,18 +894,28 @@ Would you like more details about either program or help choosing which one is r
841894 message . includes ( 'about codeunia' ) ||
842895 ( message . length < 30 && context === 'general' ) ;
843896
844- const isProgrammingQuestion = message . includes ( 'algorithm' ) ||
845- message . includes ( 'code' ) ||
897+ const isProgrammingQuestion = (
898+ message . includes ( 'algorithm' ) ||
899+ message . includes ( 'code ' ) || // Space to avoid matching 'codeunia'
900+ message . includes ( 'coding' ) ||
846901 message . includes ( 'programming' ) ||
847902 message . includes ( 'sort' ) ||
848903 message . includes ( 'function' ) ||
849- message . includes ( 'java' ) ||
904+ message . includes ( 'java ' ) ||
850905 message . includes ( 'python' ) ||
851906 message . includes ( 'javascript' ) ||
852907 message . includes ( 'data structure' ) ||
853- message . includes ( 'give me' ) ||
908+ message . includes ( 'give me code ' ) ||
854909 message . includes ( 'how to' ) ||
855- message . includes ( 'explain' ) ;
910+ message . includes ( 'explain' )
911+ ) && ! (
912+ message . includes ( 'hackathon' ) ||
913+ message . includes ( 'event' ) ||
914+ message . includes ( 'internship' ) ||
915+ message . includes ( 'job' ) ||
916+ message . includes ( 'opportunity' ) ||
917+ message . includes ( 'register' )
918+ ) ;
856919
857920 // Check if user is asking for their name
858921 const isAskingName = message . includes ( 'what is my name' ) ||
@@ -1001,53 +1064,42 @@ CODEUNIA DATA AVAILABLE:
10011064` ;
10021065 }
10031066
1004- // Add events data with date analysis
1067+ // Add events data
10051068 if ( contextData . events && contextData . events . length > 0 ) {
1006- prompt += `\nEVENT DETAILS (analyze dates carefully - current date is ${ formattedCurrentDate } ):\n` ;
1069+ prompt += `\nCURRENTLY ACTIVE EVENTS ( ${ contextData . events . length } found ):\n` ;
10071070 contextData . events . forEach ( ( event : Event ) => {
1008- const eventDate = new Date ( event . date ) ;
1009- const todayStart = new Date ( currentDate . getFullYear ( ) , currentDate . getMonth ( ) , currentDate . getDate ( ) ) ;
1010- const status = eventDate >= todayStart ? 'CURRENT/UPCOMING' : 'COMPLETED' ;
1011-
10121071 prompt += `
1013- EVENT: ${ event . title } [${ status } ]
1072+ EVENT: ${ event . title }
1073+ - ID: ${ event . id }
10141074- Description: ${ event . description }
1015- - Date: ${ event . date } at ${ event . time }
1016- - Duration : ${ event . duration }
1075+ - Date: ${ event . date }
1076+ - Time : ${ event . time }
10171077- Location: ${ event . location }
1018- - Status: ${ event . status }
1019- - Type: ${ Array . isArray ( event . event_type ) ? event . event_type . join ( ', ' ) : event . event_type }
1020- - Registration Deadline: ${ event . registration_deadline }
1021- - Capacity: ${ event . capacity } (${ event . registered } registered)
1022- - Category: ${ event . category }
1023- - Price: ${ event . price }
1024- - Organizer: ${ event . organizer }
1078+ - Price: ${ event . price || 'Free' }
1079+ - STATUS: ${ event . status === 'live' ? 'CURRENT/UPCOMING' : 'COMPLETED' }
10251080- Tags: ${ Array . isArray ( event . tags ) ? event . tags . join ( ', ' ) : event . tags }
10261081` ;
10271082 } ) ;
10281083 }
10291084
1030- // Add hackathons data with date analysis
1085+ // Add hackathons data
10311086 if ( contextData . hackathons && contextData . hackathons . length > 0 ) {
1032- prompt += `\nHACKATHON DETAILS (These are HACKATHONS, not events - analyze dates carefully - current date is ${ formattedCurrentDate } ):\n` ;
1087+ prompt += `\nCURRENTLY ACTIVE HACKATHONS ( ${ contextData . hackathons . length } found ):\n` ;
10331088 contextData . hackathons . forEach ( ( hackathon : Hackathon ) => {
1034- const hackathonDate = new Date ( hackathon . date ) ;
1035- const todayStart = new Date ( currentDate . getFullYear ( ) , currentDate . getMonth ( ) , currentDate . getDate ( ) ) ;
1036- const status = hackathonDate >= todayStart ? 'CURRENT/UPCOMING' : 'COMPLETED' ;
1037-
10381089 prompt += `
1039- HACKATHON: ${ hackathon . title } [ ${ status } ]
1040- - Type: HACKATHON (not an event)
1090+ HACKATHON: ${ hackathon . title }
1091+ - ID: ${ hackathon . id }
10411092- Description: ${ hackathon . description }
1042- - Start Date: ${ hackathon . date }
1043- - Duration: ${ hackathon . duration || 'Not specified' }
1093+ - Date: ${ hackathon . date }
10441094- Theme/Category: ${ hackathon . category || 'General' }
10451095- Location: ${ hackathon . location }
10461096- Prize Pool: ${ hackathon . prize || 'Not specified' }
10471097- Registration Deadline: ${ hackathon . registration_deadline } (last day to register)
1048- - STATUS: ${ status } - ${ status === 'COMPLETED ' ? 'This hackathon has ended ' : 'This hackathon is current or upcoming ' }
1098+ - STATUS: ${ hackathon . status === 'live ' ? 'CURRENT/UPCOMING ' : 'COMPLETED ' }
10491099` ;
10501100 } ) ;
1101+ } else if ( message . includes ( 'hackathon' ) ) {
1102+ prompt += `\nNO ACTIVE HACKATHONS FOUND matching your search.\n` ;
10511103 }
10521104
10531105 // Add internships data
0 commit comments