@@ -795,62 +795,243 @@ export function useTerminal({ portfolioData }: UseTerminalProps) {
795795
796796 const searchTerm = args . join ( ' ' ) . toLowerCase ( ) ;
797797 if ( ! searchTerm ) {
798- addLine ( '<span class="text-terminal-yellow">Usage: search [term]</span>' ) ;
799- addLine ( '<span class="text-white">Example: search python</span>' ) ;
798+ const usageBox = `
799+ <div class="border border-terminal-green/50 rounded-sm mb-4 terminal-glow">
800+ <div class="border-b border-terminal-green/30 px-3 py-1 text-center">
801+ <span class="text-terminal-bright-green text-sm font-bold">SEARCH USAGE</span>
802+ </div>
803+ <div class="p-3 space-y-3 text-xs sm:text-sm">
804+ <div>
805+ <div class="text-terminal-yellow font-bold mb-2">📋 USAGE</div>
806+ <div class="ml-2 space-y-1">
807+ <div class="text-white bg-terminal-green/5 p-2 rounded">
808+ <span class="text-terminal-bright-green font-semibold">search</span> <span class="text-terminal-yellow">[term]</span>
809+ </div>
810+ </div>
811+ </div>
812+ <div>
813+ <div class="text-terminal-yellow font-bold mb-2">💡 EXAMPLES</div>
814+ <div class="ml-2 space-y-1">
815+ <div class="text-white bg-terminal-green/5 p-2 rounded">
816+ <span class="text-terminal-bright-green">search</span> python
817+ </div>
818+ <div class="text-white bg-terminal-green/5 p-2 rounded">
819+ <span class="text-terminal-bright-green">search</span> react
820+ </div>
821+ <div class="text-white bg-terminal-green/5 p-2 rounded">
822+ <span class="text-terminal-bright-green">search</span> machine learning
823+ </div>
824+ </div>
825+ </div>
826+ </div>
827+ </div>
828+ ` . trim ( ) ;
829+
830+ addLine ( usageBox , 'w-full' ) ;
800831 return ;
801832 }
802833
803- addLine ( `<span class="text-terminal-bright-green">Searching for: "${ searchTerm } "</span>` ) ;
804- addLine ( '' ) ;
805-
806- const results : string [ ] = [ ] ;
834+ const results : Array < { category : string , title : string , content : string } > = [ ] ;
807835 const { cv } = portfolioData ;
808836
837+ // Helper function to highlight search terms
838+ const highlightMatch = ( text : string , term : string ) : string => {
839+ const regex = new RegExp ( `(${ term } )` , 'gi' ) ;
840+ return text . replace ( regex , '<span class="bg-terminal-yellow/30 text-terminal-bright-green font-semibold">$1</span>' ) ;
841+ } ;
842+
843+ // Search in intro/about section
809844 cv . sections . intro . forEach ( ( intro , i ) => {
810845 if ( intro . toLowerCase ( ) . includes ( searchTerm ) ) {
811- results . push ( `About (intro ${ i + 1 } ): ${ intro . substring ( 0 , 100 ) } ...` ) ;
846+ results . push ( {
847+ category : 'About' ,
848+ title : `Introduction ${ i + 1 } ` ,
849+ content : highlightMatch ( intro , searchTerm )
850+ } ) ;
812851 }
813852 } ) ;
814853
854+ // Search in technologies/skills
815855 cv . sections . technologies . forEach ( tech => {
816856 if ( tech . label . toLowerCase ( ) . includes ( searchTerm ) || tech . details . toLowerCase ( ) . includes ( searchTerm ) ) {
817- results . push ( `Skills: ${ tech . label } - ${ tech . details } ` ) ;
857+ const matchedContent = [ ] ;
858+ if ( tech . label . toLowerCase ( ) . includes ( searchTerm ) ) {
859+ matchedContent . push ( `Technology: ${ highlightMatch ( tech . label , searchTerm ) } ` ) ;
860+ }
861+ if ( tech . details . toLowerCase ( ) . includes ( searchTerm ) ) {
862+ matchedContent . push ( `Details: ${ highlightMatch ( tech . details , searchTerm ) } ` ) ;
863+ }
864+ results . push ( {
865+ category : 'Skills' ,
866+ title : tech . label ,
867+ content : matchedContent . join ( '<br>' )
868+ } ) ;
818869 }
819870 } ) ;
820871
872+ // Search in experience
821873 cv . sections . experience . forEach ( exp => {
822- const searchableText = `${ exp . company } ${ exp . position } ${ exp . location } ${ exp . highlights . join ( ' ' ) } ` . toLowerCase ( ) ;
823- if ( searchableText . includes ( searchTerm ) ) {
824- results . push ( `Experience: ${ exp . position } at ${ exp . company } ` ) ;
874+ const matchedContent = [ ] ;
875+
876+ if ( exp . company . toLowerCase ( ) . includes ( searchTerm ) ) {
877+ matchedContent . push ( `Company: ${ highlightMatch ( exp . company , searchTerm ) } ` ) ;
878+ }
879+ if ( exp . position . toLowerCase ( ) . includes ( searchTerm ) ) {
880+ matchedContent . push ( `Position: ${ highlightMatch ( exp . position , searchTerm ) } ` ) ;
881+ }
882+ if ( exp . location . toLowerCase ( ) . includes ( searchTerm ) ) {
883+ matchedContent . push ( `Location: ${ highlightMatch ( exp . location , searchTerm ) } ` ) ;
884+ }
885+
886+ // Check highlights for matches
887+ exp . highlights . forEach ( ( highlight , index ) => {
888+ if ( highlight . toLowerCase ( ) . includes ( searchTerm ) ) {
889+ matchedContent . push ( `Highlight ${ index + 1 } : ${ highlightMatch ( highlight , searchTerm ) } ` ) ;
890+ }
891+ } ) ;
892+
893+ if ( matchedContent . length > 0 ) {
894+ results . push ( {
895+ category : 'Experience' ,
896+ title : `${ exp . position } at ${ exp . company } ` ,
897+ content : matchedContent . join ( '<br>' )
898+ } ) ;
899+ }
900+ } ) ;
901+
902+ // Search in education
903+ cv . sections . education . forEach ( edu => {
904+ const matchedContent = [ ] ;
905+
906+ if ( edu . institution . toLowerCase ( ) . includes ( searchTerm ) ) {
907+ matchedContent . push ( `Institution: ${ highlightMatch ( edu . institution , searchTerm ) } ` ) ;
908+ }
909+ if ( edu . degree . toLowerCase ( ) . includes ( searchTerm ) ) {
910+ matchedContent . push ( `Degree: ${ highlightMatch ( edu . degree , searchTerm ) } ` ) ;
911+ }
912+ if ( edu . area . toLowerCase ( ) . includes ( searchTerm ) ) {
913+ matchedContent . push ( `Major: ${ highlightMatch ( edu . area , searchTerm ) } ` ) ;
914+ }
915+ if ( edu . location . toLowerCase ( ) . includes ( searchTerm ) ) {
916+ matchedContent . push ( `Location: ${ highlightMatch ( edu . location , searchTerm ) } ` ) ;
917+ }
918+
919+ // Check highlights for matches
920+ edu . highlights . forEach ( ( highlight , index ) => {
921+ if ( highlight . toLowerCase ( ) . includes ( searchTerm ) ) {
922+ matchedContent . push ( `Highlight ${ index + 1 } : ${ highlightMatch ( highlight , searchTerm ) } ` ) ;
923+ }
924+ } ) ;
925+
926+ if ( matchedContent . length > 0 ) {
927+ results . push ( {
928+ category : 'Education' ,
929+ title : `${ edu . degree } in ${ edu . area } from ${ edu . institution } ` ,
930+ content : matchedContent . join ( '<br>' )
931+ } ) ;
825932 }
826933 } ) ;
827934
935+ // Search in professional projects
828936 cv . sections . selected_projects . forEach ( proj => {
829- const searchableText = `${ proj . name } ${ proj . highlights . join ( ' ' ) } ` . toLowerCase ( ) ;
830- if ( searchableText . includes ( searchTerm ) ) {
831- results . push ( `Project: ${ proj . name } ` ) ;
937+ const matchedContent = [ ] ;
938+
939+ if ( proj . name . toLowerCase ( ) . includes ( searchTerm ) ) {
940+ matchedContent . push ( `Project: ${ highlightMatch ( proj . name , searchTerm ) } ` ) ;
941+ }
942+
943+ // Check highlights for matches
944+ proj . highlights . forEach ( ( highlight , index ) => {
945+ if ( highlight . toLowerCase ( ) . includes ( searchTerm ) ) {
946+ matchedContent . push ( `Detail ${ index + 1 } : ${ highlightMatch ( highlight , searchTerm ) } ` ) ;
947+ }
948+ } ) ;
949+
950+ if ( matchedContent . length > 0 ) {
951+ results . push ( {
952+ category : 'Professional Projects' ,
953+ title : proj . name ,
954+ content : matchedContent . join ( '<br>' )
955+ } ) ;
832956 }
833957 } ) ;
834958
959+ // Search in personal projects
835960 cv . sections . personal_projects . forEach ( proj => {
836- const searchableText = `${ proj . name } ${ proj . highlights . join ( ' ' ) } ` . toLowerCase ( ) ;
837- if ( searchableText . includes ( searchTerm ) ) {
838- results . push ( `Personal Project: ${ proj . name } ` ) ;
961+ const matchedContent = [ ] ;
962+
963+ if ( proj . name . toLowerCase ( ) . includes ( searchTerm ) ) {
964+ matchedContent . push ( `Project: ${ highlightMatch ( proj . name , searchTerm ) } ` ) ;
965+ }
966+
967+ // Check highlights for matches
968+ proj . highlights . forEach ( ( highlight , index ) => {
969+ if ( highlight . toLowerCase ( ) . includes ( searchTerm ) ) {
970+ matchedContent . push ( `Detail ${ index + 1 } : ${ highlightMatch ( highlight , searchTerm ) } ` ) ;
971+ }
972+ } ) ;
973+
974+ if ( matchedContent . length > 0 ) {
975+ results . push ( {
976+ category : 'Personal Projects' ,
977+ title : proj . name ,
978+ content : matchedContent . join ( '<br>' )
979+ } ) ;
839980 }
840981 } ) ;
841982
842- if ( results . length === 0 ) {
843- addLine ( '<span class="text-terminal-yellow">No results found</span>' ) ;
844- } else {
845- addLine ( `<span class="text-terminal-green">Found ${ results . length } result(s):</span>` ) ;
846- addLine ( '' ) ;
847- results . forEach ( ( result , index ) => {
848- setTimeout ( ( ) => {
849- addLine ( `<span class="text-white">• ${ result } </span>` ) ;
850- } , index * 100 ) ;
851- } ) ;
852- }
853- } , [ addLine , portfolioData ] ) ;
983+ // Create the search results box
984+ const searchBox = `
985+ <div class="border border-terminal-green/50 rounded-sm mb-4 terminal-glow max-w-4xl">
986+ <div class="border-b border-terminal-green/30 px-3 py-1 text-center">
987+ <span class="text-terminal-bright-green text-sm font-bold">SEARCH RESULTS</span>
988+ </div>
989+ <div class="p-3 space-y-3 text-xs sm:text-sm">
990+ <div class="bg-terminal-green/5 p-2 rounded">
991+ <span class="text-terminal-yellow font-semibold">Search term:</span>
992+ <span class="text-white"> "${ searchTerm } "</span>
993+ </div>
994+ <div class="bg-terminal-green/5 p-2 rounded">
995+ <span class="text-terminal-bright-green font-semibold">Found ${ results . length } result(s)</span>
996+ </div>
997+ ${ results . length === 0 ? `
998+ <div class="border border-terminal-yellow/30 rounded p-3 text-center">
999+ <div class="text-terminal-yellow font-semibold mb-2">No results found</div>
1000+ <div class="text-white opacity-80 text-xs">
1001+ Try searching for technologies, company names, or project keywords
1002+ </div>
1003+ </div>
1004+ ` : `
1005+ <div class="space-y-3">
1006+ ${ results . map ( ( result , index ) => `
1007+ <div class="border border-terminal-green/20 rounded p-3 ${ index < results . length - 1 ? 'border-b border-terminal-green/30' : '' } ">
1008+ <div class="mb-2">
1009+ <span class="text-terminal-bright-green font-semibold text-xs">[${ result . category . toUpperCase ( ) } ]</span>
1010+ <span class="text-terminal-yellow font-semibold ml-2">${ result . title } </span>
1011+ </div>
1012+ <div class="text-white text-xs opacity-80 bg-terminal-green/5 p-2 rounded leading-relaxed">
1013+ ${ result . content }
1014+ </div>
1015+ </div>
1016+ ` ) . join ( '' ) }
1017+ </div>
1018+ ` }
1019+ <div class="border-t border-terminal-green/30 pt-3">
1020+ <div class="text-terminal-yellow font-bold mb-2">💡 EXPLORE MORE</div>
1021+ <div class="space-y-1 ml-2 text-xs">
1022+ <div><span class="text-white">•</span> Try <span class="text-terminal-bright-green font-semibold"><a href="?cmd=skills">skills</a></span> to see all technologies</div>
1023+ <div><span class="text-white">•</span> Try <span class="text-terminal-bright-green font-semibold"><a href="?cmd=experience">experience</a></span> to view work history</div>
1024+ <div><span class="text-white">•</span> Try <span class="text-terminal-bright-green font-semibold"><a href="?cmd=projects">projects</a></span> to explore all projects</div>
1025+ <div><span class="text-white">•</span> Try <span class="text-terminal-bright-green font-semibold"><a href="?cmd=help">help</a></span> for all available commands</div>
1026+ </div>
1027+ </div>
1028+ </div>
1029+ </div>
1030+ ` . trim ( ) ;
1031+
1032+ // Add the entire search box as a single line
1033+ addLine ( searchBox , 'w-full' ) ;
1034+ } , [ addLine , portfolioData , formatExperiencePeriod ] ) ;
8541035
8551036 const showTheme = useCallback ( ( args : string [ ] ) => {
8561037 const theme = args [ 0 ] ;
@@ -936,7 +1117,11 @@ export function useTerminal({ portfolioData }: UseTerminalProps) {
9361117 <span class="text-terminal-yellow font-semibold">Phone</span>
9371118 </div>
9381119 <div class="col-span-9 bg-terminal-green/5">
939- <span class="text-white"><a href="${ cv . phone } " class="text-terminal-bright-green underline hover:text-terminal-yellow cursor-pointer">${ cv . phone . replace ( / [ ^ \d \+ ] / g, '' ) } </a></span>
1120+ <span class="text-white">
1121+ <a href="${ cv . phone } " class="text-terminal-bright-green underline hover:text-terminal-yellow cursor-pointer">
1122+ ${ cv . phone . replace ( / [ ^ \d \+ ] / g, '' ) }
1123+ </a>
1124+ </span>
9401125 </div>
9411126 </div>
9421127 </div>
0 commit comments