diff --git a/.gitignore b/.gitignore index a547bf3..7e511a5 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,5 @@ dist-ssr *.njsproj *.sln *.sw? +.history/ + diff --git a/src/App.tsx b/src/App.tsx index 79c8089..d6a3e9a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,269 @@ -import { RouterProvider } from "react-router-dom"; -import router from "./router"; +import { useState } from "react"; +import { useRef } from "react"; +import { useEffect } from "react"; + +import info from "../data.json"; +import { username, hostname, path, symbol } from "../constants"; + +const options = info.options.map((option) => option.label); +import { Queue } from "queue-typescript"; + +const historyCommand = new Queue(); +let count = 1; +let historyPos = 1; + +// + +const WelcomeSection = () => { + return ( +
+

+ Welcome to my portfolio! +

+

+ Instructions - This portfolio is a replica of a terminal. You need to + provide commands for any functionality. +

+

+ Hint - Use 'clear' command to clear the terminal. +

+
+ ); +}; function App() { - return ; + const [showWelcome, setShowWelcome] = useState(true); + const [history, setHistory] = useState([ + { + command: "help", + output: + "Here are the available commands:
" + + info.options + .map((option) => option.label + " - " + option.about) + .join("
") + + "
" + + info.additional_commands + .map((option) => option.label + " - " + option.about) + .join("
"), + }, + ]); + const [customUserName, setCustomUserName] = useState(""); + const [userInput, setUserInput] = useState(""); + const handleArrowKeyPress = (event: { key: string }) => { + if (event.key === "ArrowUp") { + if (historyPos > 0) { + setUserInput(history[historyPos - 1]["command"]); + historyPos -= 1; + } + } else if (event.key === "ArrowDown") { + if (historyPos < history.length - 1) { + setUserInput(history[historyPos + 1]["command"]); + historyPos += 1; + } else if ((historyPos = history.length)) { + setUserInput(""); + // historyPos+=1 + } + } + }; + const executeCommand = (command: string) => { + if (command.trim().startsWith("setname")) { + command = command; + //Handled by previous commit + } else { + command = command.split(" ")[0]; + } + command = command.trim().toLowerCase(); + historyPos = history.length + 1; + if (command !== "history") { + historyCommand.enqueue(count++ + ` ` + command + `
`); + } + if (options.includes(command)) { + let output = info.options.find( + (option) => option.label === command + )!.value; + + // check if 'data' exists within the options + if (info.options.find((option) => option.label === command)?.data) { + console.log("data exists"); + // append to output + const data = info.options.find( + (option) => option.label === command + )!.data; + + output += data?.map((item) => { + return `

+ ${item.label}
+ ${item.value}`; + }); + } + + setHistory((history) => [ + ...history, + { + command, + output, + }, + ]); + } else { + if (command === "help") { + setHistory((history) => [ + ...history, + { + command: command, + output: + "Here are the available commands:
" + + info.options + .map((option) => option.label + " - " + option.about) + .join("
") + + "
" + + info.additional_commands + .map((option) => option.label + " - " + option.about) + .join("
"), + }, + ]); + } else if (command === "clear") { + setHistory([]); + historyPos -= 1; + setShowWelcome(false); // Hide welcome section on clear command + } else if (command === "") { + setHistory((history) => [ + ...history, + { + command: command, + output: "", + }, + ]); + } else if (command === "history") { + setHistory((history) => [ + ...history, + { + command: command, + output: displayHistory(), + }, + ]); + } + // functionality for setname command + else if (command.trim().startsWith("setname")) { + // get the name from the command + const splitCommand = command.split(" "); + const name = splitCommand.slice(1).join(" "); + // set the custom username + setCustomUserName(name); + // update history + setHistory((history) => [ + ...history, + { + command: command, + output: `Hello ${name}!`, + }, + ]); + } else { + setHistory((history) => [ + ...history, + { + command: command, + output: "command not found", + }, + ]); + } + } + }; + + const displayHistory = () => { + let his = ""; + const HistoryArray = historyCommand.toArray(); + HistoryArray.forEach((i) => { + his += i; + }); + return his; + }; + + const inputRef = useRef(null); + const focusInput = () => { + if (inputRef.current) { + inputRef.current.focus(); + } + }; + + const handleInputChange = (e: React.ChangeEvent) => { + setUserInput(e.target.value); + }; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + executeCommand(userInput); + setUserInput(""); + }; + + useEffect(() => { + document.addEventListener("click", focusInput); + + // Cleanup the event listener when the component unmounts + return () => { + document.removeEventListener("click", focusInput); + }; + }, []); + + return ( +
+ {showWelcome && } + {/*

+ Welcome to my portfolio! +

+

+ Instructions - This portfolio is a replica of a terminal. You need to + provide commands for any functionality.{" "} +

+

+ Hint - Use 'clear' command to clear the terminal.{" "} +

*/} +
+
+ { + /* History */ + history.map((history) => ( +
+ + {history.command}
+ +
+ )) + } + {/* Prompt */} +
+ + +
+ +
+
+
+
+
+
+ ); } +const Prompt = (props: { customUserName: string }) => { + return ( + + + {props.customUserName == "" ? username : props.customUserName}@ + {hostname} + + :{path} + {symbol} + + ); +}; + export default App;