|
1 | 1 | import{useRouter}from"next/router"; |
2 | | -import{useRef,useState}from"react"; |
| 2 | +import{useEffect,useRef,useState}from"react"; |
3 | 3 |
|
4 | 4 | constTerminal=()=>{ |
5 | | -// Store the value of the input |
6 | 5 | const[value,setValue]=useState(""); |
| 6 | +const[inputFocused,setInputFocused]=useState(false); |
7 | 7 |
|
8 | | -// Automatically select the end of the input as the custom |
9 | | -// cursor only works at the end of the input. |
10 | 8 | constinputRef=useRef<HTMLInputElement>(null); |
| 9 | +constrouter=useRouter(); |
| 10 | + |
| 11 | +// Automatically focus and move cursor to the end |
11 | 12 | constsetInputEnd=()=>{ |
12 | 13 | if(inputRef.current){ |
13 | 14 | constlen=inputRef.current.value.length; |
14 | 15 | inputRef.current.setSelectionRange(len,len); |
15 | 16 | } |
16 | | -} |
| 17 | +}; |
17 | 18 |
|
18 | | -// Keep track of if the input is focused |
19 | | -const[inputFocused,setInputFocused]=useState(false); |
| 19 | +// Use localStorage to keep focus on the terminal if redirecting using terminal |
| 20 | +useEffect(()=>{ |
| 21 | +if(localStorage.getItem("fromTerminal")==="true"){ |
| 22 | +localStorage.removeItem("fromTerminal"); |
| 23 | +if(inputRef.current){ |
| 24 | +inputRef.current.focus(); |
| 25 | +setInputEnd(); |
| 26 | +setInputFocused(true); |
| 27 | +} |
| 28 | +} |
| 29 | +},[]); |
20 | 30 |
|
21 | | -// Using the router to change pages seamlessly |
22 | | -constrouter=useRouter(); |
23 | 31 | constgoToPage=(target:string)=>{ |
| 32 | +localStorage.setItem("fromTerminal","true"); |
24 | 33 | router.push(target); |
25 | 34 | }; |
26 | | - |
27 | | -// Checking for "Enter" and if so, changing to |
28 | | -// the inputted page |
| 35 | + |
29 | 36 | consthandleKey=(key:string)=>{ |
30 | 37 | if(key!=="Enter")return; |
31 | 38 |
|
32 | | -if(value.toLowerCase()==="~" |
33 | | -||value.toLowerCase()==="cd" |
34 | | -||value.toLowerCase()==="cd ~" |
35 | | -||value.toLowerCase()==="cd .." |
36 | | -){ |
| 39 | +constcmd=value.toLowerCase().trim(); |
| 40 | + |
| 41 | +if(["~","cd","cd ~","cd .."].includes(cmd)){ |
37 | 42 | goToPage("/"); |
38 | | -}elseif(value.toLowerCase()==="cd about" |
39 | | -||value.toLowerCase()==="cd about us" |
40 | | -||value.toLowerCase()==="cd about_us" |
41 | | -){ |
| 43 | +}elseif(["cd about","cd about us","cd about_us"].includes(cmd)){ |
42 | 44 | goToPage("/about"); |
43 | | -}elseif(value.toLowerCase()==="cd events" |
44 | | -||value.toLowerCase()==="cd event" |
45 | | -){ |
| 45 | +}elseif(["cd events","cd event"].includes(cmd)){ |
46 | 46 | goToPage("/events"); |
47 | | -}elseif(value.toLowerCase()==="cd resources" |
48 | | -||value.toLowerCase()==="cd resource" |
49 | | -){ |
| 47 | +}elseif(["cd resources","cd resource"].includes(cmd)){ |
50 | 48 | goToPage("/resources"); |
51 | | -}elseif(value.toLowerCase()==="cd sponsors" |
52 | | -||value.toLowerCase()==="cd sponsor" |
53 | | -){ |
| 49 | +}elseif(["cd sponsors","cd sponsor"].includes(cmd)){ |
54 | 50 | goToPage("/sponsors"); |
55 | | -}elseif(value.toLowerCase()==="cd contact" |
56 | | -||value.toLowerCase()==="cd contacts" |
57 | | -||value.toLowerCase()==="cd contact us" |
58 | | -||value.toLowerCase()==="cd contact_us" |
59 | | -){ |
| 51 | +}elseif(["cd contact","cd contacts","cd contact us","cd contact_us"].includes(cmd)){ |
60 | 52 | goToPage("/contact-us"); |
| 53 | +}elseif(cmd==="cd constitution"){ |
| 54 | +goToPage("/about/constitution"); |
| 55 | +}elseif( |
| 56 | +["cd execs","cd directors","cd subcom","cd execs directors subcom","cd execs-directors-subcom","cd execs_directors_subcom"].includes(cmd) |
| 57 | +){ |
| 58 | +goToPage("/about/execs-directors-subcom"); |
| 59 | +}elseif( |
| 60 | +["history","cd our history","cd our-history","cd our_history"].includes(cmd) |
| 61 | +){ |
| 62 | +goToPage("/about/our-history"); |
| 63 | +}elseif( |
| 64 | +["cd faq","cd faqs","cd questions","cd frequently asked questions"].includes(cmd) |
| 65 | +){ |
| 66 | +goToPage("/about/faqs"); |
| 67 | +}elseif( |
| 68 | +["cd election-guide","cd election guide","cd election"].includes(cmd) |
| 69 | +){ |
| 70 | +goToPage("/about/election-guide"); |
61 | 71 | } |
62 | 72 |
|
63 | | -clearInput() |
| 73 | +clearInput(); |
64 | 74 | }; |
65 | 75 |
|
66 | 76 | constclearInput=()=>{ |
67 | 77 | setValue(""); |
68 | 78 | }; |
69 | 79 |
|
70 | 80 | return( |
71 | | -// Using relative + absolute to overlap the `input` and `span` |
72 | 81 | <spanclassName="relative"> |
73 | | -{/* The input */} |
74 | | -<inputtype="text"id="input"value={value}ref={inputRef}maxLength={40} |
| 82 | +<input |
| 83 | +type="text" |
| 84 | +id="input" |
| 85 | +value={value} |
| 86 | +ref={inputRef} |
| 87 | +maxLength={40} |
75 | 88 | className="absolute text-blue-500 p-0 m-0 bg-transparent outline-none caret-transparent w-[50vw] z-10" |
76 | 89 | onKeyDown={(e)=>{ |
77 | | -handleKey(e.key) |
78 | | -setInputEnd() |
| 90 | +handleKey(e.key); |
| 91 | +setInputEnd(); |
79 | 92 | }} |
80 | 93 | onChange={(e)=>setValue(e.target.value)} |
81 | 94 | onFocus={()=>setInputFocused(true)} |
82 | 95 | onBlur={()=>{ |
83 | | -clearInput() |
84 | | -setInputFocused(false) |
| 96 | +clearInput(); |
| 97 | +setInputFocused(false); |
85 | 98 | }} |
86 | | -></input> |
87 | | -{/* The custom cursor */} |
| 99 | +/> |
88 | 100 | <spanclassName="absolute w-[60vw] p-0 m-0 z-0"> |
89 | | -{/* The invisable span that is the same length as the input */} |
| 101 | +<spanclassName="invisible whitespace-pre pointer-events-none text-base"> |
| 102 | +{value} |
| 103 | +</span> |
90 | 104 | <span |
91 | | -className="invisible whitespace-pre pointer-events-none text-base" |
92 | | ->{value}</span> |
93 | | -{/* The custom cursor */} |
94 | | -<spanid="cursor"className={`text-${inputFocused ?"white" :"gray-500"} pointer-events-none inline-block animate-blink p-0 m-0`}>_</span> |
| 105 | +id="cursor" |
| 106 | +className={`text-${ |
| 107 | +inputFocused ?"white" :"gray-500" |
| 108 | +} pointer-events-none inline-block animate-blink p-0 m-0`} |
| 109 | +> |
| 110 | + _ |
| 111 | +</span> |
95 | 112 | </span> |
96 | 113 | </span> |
97 | | -) |
98 | | -} |
| 114 | +); |
| 115 | +}; |
99 | 116 |
|
100 | | -exportdefaultTerminal |
| 117 | +exportdefaultTerminal; |