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