aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhongheng Liu <z.liu@outlook.com.gr>2024-01-31 21:07:45 +0200
committerZhongheng Liu <z.liu@outlook.com.gr>2024-01-31 21:07:45 +0200
commit4117c11c356652381a9564688139d9c3f25eb983 (patch)
tree153d1fa6951ca28c5a469e3d99a9be0cfa46f979
parent7e5f5bdf774a2f3b5d65b90c55ced6553419a960 (diff)
downloadepq-web-4117c11c356652381a9564688139d9c3f25eb983.tar.gz
epq-web-4117c11c356652381a9564688139d9c3f25eb983.tar.bz2
epq-web-4117c11c356652381a9564688139d9c3f25eb983.zip
CSS styling overhaul
FIXED Issue with rendering time - minutes now in fixed 2-digit format ADD Sidebar Topbar components to help with UI/UX ADD Avatar and Menu PNG files for style TODO Improve styling ET AL removed redundant code
-rw-r--r--src/App.css4
-rw-r--r--src/App.tsx18
-rw-r--r--src/Chat/Chat.css8
-rw-r--r--src/Intl/strings.json2
-rw-r--r--src/Login/Login.css1
-rw-r--r--src/MessageDisplay/MessageDisplay.tsx115
-rw-r--r--src/Sidebar/Components/Avatar.css5
-rw-r--r--src/Sidebar/Components/Avatar.tsx9
-rw-r--r--src/Sidebar/Components/SidebarMenu.tsx50
-rw-r--r--src/Sidebar/Components/placeholder.jpgbin0 -> 17203 bytes
-rw-r--r--src/Sidebar/Sidebar.css47
-rw-r--r--src/Sidebar/Sidebar.tsx24
-rw-r--r--src/Topbar/Topbar.css10
-rw-r--r--src/Topbar/Topbar.tsx33
-rw-r--r--src/Topbar/menu.pngbin0 -> 10450 bytes
-rw-r--r--src/type/messageTypes.ts1
16 files changed, 261 insertions, 66 deletions
diff --git a/src/App.css b/src/App.css
index e4849cc..bb372cd 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,6 +1,6 @@
body {
- background-color: black;
- color: #00FF33;
+ /* background-color: black;
+ color: #00FF33; */
margin: 1%;
min-height: 100vh;
}
diff --git a/src/App.tsx b/src/App.tsx
index 7d908e3..a5f11ac 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -7,6 +7,8 @@ import strings from "./Intl/strings.json";
import { LangContext, LoginContext, LoginType } from "./context";
import { contentTypes, domain, endpoints, port } from "./consts";
import { Login } from "./Login/Login";
+import { Sidebar } from "./Sidebar/Sidebar";
+import { Topbar } from "./Topbar/Topbar";
// what we "in the business" call type gymnastics
const Wrapper = (): React.ReactElement => {
const [lang, setLang] = useState<LangType>("en_US");
@@ -16,11 +18,19 @@ const Wrapper = (): React.ReactElement => {
? `IRC logged in as ${login.username}`
: "IRC Chat";
}, [login]);
+ const [sidebarEnabled, setSidebarEnabled] = useState(false);
return (
<LangContext.Provider value={lang}>
- <h1>{strings[lang].homepage.title}</h1>
- <p>{strings[lang].homepage.description}</p>
<LoginContext.Provider value={login}>
+ <Topbar
+ setSidebarEnable={(enabled: boolean) =>
+ setSidebarEnabled(enabled)
+ }
+ ></Topbar>
+ <Sidebar
+ isEnabled={sidebarEnabled}
+ setEnable={(enabled: boolean) => setSidebarEnabled(enabled)}
+ ></Sidebar>
{/* callbacks for altering the Lang/Login contexts */}
<Login
setLogin={(value) => {
@@ -97,8 +107,8 @@ const App = ({
})
.then((responseBody: { success: boolean }) => {
if (responseBody.success) {
- // TODO Put new username response true handler method stub
- } else {
+ // TODO Put new username response true handler method stub
+ } else {
console.error(
"Server POST message failed."
);
diff --git a/src/Chat/Chat.css b/src/Chat/Chat.css
index 76b19f6..cc5dd7b 100644
--- a/src/Chat/Chat.css
+++ b/src/Chat/Chat.css
@@ -12,6 +12,14 @@
}
.chat {
+ /* float: left; */
/* min-height: 80vh; */
position: relative;
+ box-shadow:
+ 0 2.8px 2.2px rgba(0, 0, 0, 0.034),
+ 0 6.7px 5.3px rgba(0, 0, 0, 0.048),
+ 0 12.5px 10px rgba(0, 0, 0, 0.06),
+ 0 22.3px 17.9px rgba(0, 0, 0, 0.072),
+ 0 41.8px 33.4px rgba(0, 0, 0, 0.086),
+ 0 100px 80px rgba(0, 0, 0, 0.12)
}
diff --git a/src/Intl/strings.json b/src/Intl/strings.json
index ceff215..e5081b5 100644
--- a/src/Intl/strings.json
+++ b/src/Intl/strings.json
@@ -1,6 +1,6 @@
{
"variableNames": ["userName", "content"],
- "acceptedLangs": ["en_US", "zh_TW", "el_GR"],
+ "acceptedLangs": ["en_US", "zh_TW", "el_GR", "ar_SA"],
"en_US": {
"homepage": {
"userNamePrompt": "Your username: ",
diff --git a/src/Login/Login.css b/src/Login/Login.css
index 21bceff..2776f45 100644
--- a/src/Login/Login.css
+++ b/src/Login/Login.css
@@ -1,3 +1,4 @@
.uname-error-text {
color: red;
}
+.login {} \ No newline at end of file
diff --git a/src/MessageDisplay/MessageDisplay.tsx b/src/MessageDisplay/MessageDisplay.tsx
index 18a9277..3ebf8af 100644
--- a/src/MessageDisplay/MessageDisplay.tsx
+++ b/src/MessageDisplay/MessageDisplay.tsx
@@ -5,64 +5,61 @@ import strings from "../Intl/strings.json";
import "./MessageDisplay.css";
import { queryByRole } from "@testing-library/react";
export const MessageDisplay = ({
- type,
- fromUserId,
- toUserId,
- content,
- timeMillis,
+ type,
+ fromUserId,
+ toUserId,
+ content,
+ timeMillis,
}: Message): React.ReactElement<Message> => {
- const dateTime: Date = new Date(timeMillis);
- const lang = useContext(LangContext);
- const msgPage = strings[lang].chat;
- /* FIXED funny error
- * DESCRIPTION
- * The line below was
- * return (<p>[{dateTime.toLocaleString(Intl.DateTimeFormat().resolvedOptions().timeZone)}]...</p>)
- * The line incorrectly generated a value of "UTC" as the parameter to toLocaleString()
- * While "UTC" is an accepted string value, in EEST, aka. "Europe/Athens" timezone string is not an acceptable parameter.
- * This caused the return statement to fail, and the message fails to render, despite it being correctly committed to the db.
- * Funny clown moment 🤡
- */
- const timeString = `${
- dateTime.getHours() > 12
- ? dateTime.getHours() - 12
- : dateTime.getHours()
- }:${dateTime.getMinutes()} ${dateTime.getHours() > 12 ? "PM" : "AM"}`;
- switch (type) {
- case MessageType.HELLO as MessageType:
- return (
- <p className="msg">
- [{timeString}]{" "}
- {msgPage.joinMessage.replace(
- "$userName",
- fromUserId
- )}
- </p>
- );
- case MessageType.MESSAGE as MessageType:
- return (
- <p className="msg">
- [{timeString}]{" "}
- {msgPage.serverMessage
- .replace(
- "$userName",
- fromUserId
- )
- .replace("$content", content)}
- </p>
- );
- case MessageType.DATA as MessageType:
- return <></>;
- case MessageType.CHNAME as MessageType:
- return <></>;
- default:
- console.error("Illegal MessageType reported!");
- return (
- <p className="msg-err">
- [{timeString}] **THIS MESSAGE CANNOT BE
- CORRECTLY SHOWN BECAUSE THE CLIENT
- ENCOUNTERED AN ERROR**
- </p>
- );
- }
+ const dateTime: Date = new Date(timeMillis);
+ const lang = useContext(LangContext);
+ const msgPage = strings[lang].chat;
+ /* FIXED funny error
+ * DESCRIPTION
+ * The line below was
+ * return (<p>[{dateTime.toLocaleString(Intl.DateTimeFormat().resolvedOptions().timeZone)}]...</p>)
+ * The line incorrectly generated a value of "UTC" as the parameter to toLocaleString()
+ * While "UTC" is an accepted string value, in EEST, aka. "Europe/Athens" timezone string is not an acceptable parameter.
+ * This caused the return statement to fail, and the message fails to render, despite it being correctly committed to the db.
+ * Funny clown moment 🤡
+ */
+ const timeString = `${
+ dateTime.getHours() > 12
+ ? dateTime.getHours() - 12
+ : dateTime.getHours()
+ }:${
+ dateTime.getMinutes() >= 10
+ ? dateTime.getMinutes()
+ : `0${dateTime.getMinutes().toString()}`
+ } ${dateTime.getHours() > 12 ? "PM" : "AM"}`;
+ switch (type) {
+ case MessageType.HELLO as MessageType:
+ return (
+ <p className="msg">
+ [{timeString}]{" "}
+ {msgPage.joinMessage.replace("$userName", fromUserId)}
+ </p>
+ );
+ case MessageType.MESSAGE as MessageType:
+ return (
+ <p className="msg">
+ [{timeString}]{" "}
+ {msgPage.serverMessage
+ .replace("$userName", fromUserId)
+ .replace("$content", content)}
+ </p>
+ );
+ case MessageType.DATA as MessageType:
+ return <></>;
+ case MessageType.CHNAME as MessageType:
+ return <></>;
+ default:
+ console.error("Illegal MessageType reported!");
+ return (
+ <p className="msg-err">
+ [{timeString}] **THIS MESSAGE CANNOT BE CORRECTLY SHOWN
+ BECAUSE THE CLIENT ENCOUNTERED AN ERROR**
+ </p>
+ );
+ }
};
diff --git a/src/Sidebar/Components/Avatar.css b/src/Sidebar/Components/Avatar.css
new file mode 100644
index 0000000..f2da859
--- /dev/null
+++ b/src/Sidebar/Components/Avatar.css
@@ -0,0 +1,5 @@
+.avatar {
+ width: 100%;
+ display: flex;
+ justify-content:center;
+} \ No newline at end of file
diff --git a/src/Sidebar/Components/Avatar.tsx b/src/Sidebar/Components/Avatar.tsx
new file mode 100644
index 0000000..700f20d
--- /dev/null
+++ b/src/Sidebar/Components/Avatar.tsx
@@ -0,0 +1,9 @@
+import "./Avatar.css";
+import placeholderImage from "./placeholder.jpg";
+export const Avatar = () => {
+ return (
+ <div className="avatar">
+ <img src={placeholderImage} width="75px"></img>
+ </div>
+ );
+};
diff --git a/src/Sidebar/Components/SidebarMenu.tsx b/src/Sidebar/Components/SidebarMenu.tsx
new file mode 100644
index 0000000..be176d2
--- /dev/null
+++ b/src/Sidebar/Components/SidebarMenu.tsx
@@ -0,0 +1,50 @@
+import "../Sidebar.css";
+import { Avatar } from "./Avatar";
+export const SidebarMenuItem = ({
+ text,
+ href,
+ handler,
+}: {
+ text: string;
+ href?: string;
+ handler?: () => void;
+}) => {
+ return (
+ <div
+ className="sidebar-menu-item"
+ onClick={
+ handler
+ ? () => {
+ handler();
+ }
+ : () => {}
+ }
+ >
+ <li>
+ <span>
+ <i>{href ? <a href={href}>{text}</a> : text}</i>
+ </span>
+ </li>
+ <hr></hr>
+ </div>
+ );
+};
+export const SidebarMenu = ({
+ exitHandler,
+}: {
+ exitHandler: (enabled: boolean) => void;
+}) => {
+ return (
+ <div className="sidebar-menu">
+ <Avatar></Avatar>
+ <SidebarMenuItem text="My Account"></SidebarMenuItem>
+ <SidebarMenuItem text="Personalisation"></SidebarMenuItem>
+ <SidebarMenuItem text="Language"></SidebarMenuItem>
+ <SidebarMenuItem text="Server Configuration"></SidebarMenuItem>
+ <SidebarMenuItem
+ text="Return to homepage"
+ handler={() => exitHandler(false)}
+ ></SidebarMenuItem>
+ </div>
+ );
+};
diff --git a/src/Sidebar/Components/placeholder.jpg b/src/Sidebar/Components/placeholder.jpg
new file mode 100644
index 0000000..6789d3b
--- /dev/null
+++ b/src/Sidebar/Components/placeholder.jpg
Binary files differ
diff --git a/src/Sidebar/Sidebar.css b/src/Sidebar/Sidebar.css
new file mode 100644
index 0000000..baa1161
--- /dev/null
+++ b/src/Sidebar/Sidebar.css
@@ -0,0 +1,47 @@
+
+.sidebar {
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ top: 0;
+ left: 0;
+ background-color: rgba(0, 0, 0, 0.5);
+ animation: fadeIn, 5s;
+ z-index: 10;
+}
+.sidebar-menu-item {
+ margin: 5px;
+ transition: all 0.5s;
+}
+
+.sidebar-menu-item:hover {
+ background-color: rgba(0, 0, 0, 0.2);
+ box-shadow: 5px 5px rgba(0, 0, 0, 0.5);
+}
+.sidebar-content {
+ background-color: white;
+ width: max(15%, 200px);
+ height: 100%;
+ box-shadow: 10px 10px rgba(0, 0, 0, 0.5);
+}
+@keyframes fadeIn {
+ 0% {background-color: transparent;}
+ 100% {background-color: rgba(0, 0, 0, 0.5);;}
+}
+@-moz-keyframes fadeIn {
+ 0% {background-color: transparent;}
+ 100% {background-color: rgba(0, 0, 0, 0.5);;}
+}
+ @-webkit-keyframes fadeIn {
+ 0% {background-color: transparent;}
+ 100% {background-color: rgba(0, 0, 0, 0.5);;}
+}
+
+ @-o-keyframes fadeIn {
+ 0% {background-color: transparent;}
+ 100% {background-color: rgba(0, 0, 0, 0.5);;}
+}
+ @-ms-keyframes fadeIn {
+ 0% {background-color: transparent;}
+ 100% {background-color: rgba(0, 0, 0, 0.5);;}
+} \ No newline at end of file
diff --git a/src/Sidebar/Sidebar.tsx b/src/Sidebar/Sidebar.tsx
new file mode 100644
index 0000000..ea5dfed
--- /dev/null
+++ b/src/Sidebar/Sidebar.tsx
@@ -0,0 +1,24 @@
+import { useState } from "react";
+import "./Sidebar.css";
+import { SidebarMenu } from "./Components/SidebarMenu";
+export const Sidebar = ({
+ isEnabled,
+ setEnable,
+}: {
+ isEnabled: boolean;
+ setEnable: (enabled: boolean) => void;
+}) => {
+ return isEnabled ? (
+ <div className="sidebar">
+ <div className="sidebar-content">
+ <SidebarMenu
+ exitHandler={(value) => {
+ setEnable(value);
+ }}
+ ></SidebarMenu>
+ </div>
+ </div>
+ ) : (
+ <></>
+ );
+};
diff --git a/src/Topbar/Topbar.css b/src/Topbar/Topbar.css
new file mode 100644
index 0000000..ffd3d68
--- /dev/null
+++ b/src/Topbar/Topbar.css
@@ -0,0 +1,10 @@
+.topbar {
+ width: 100vw;
+ height: 10%;
+ z-index: 5;
+ display: flex;
+ justify-content: baseline;
+}
+.topbar-span .children {
+ margin-left: 10px;
+} \ No newline at end of file
diff --git a/src/Topbar/Topbar.tsx b/src/Topbar/Topbar.tsx
new file mode 100644
index 0000000..0c4022f
--- /dev/null
+++ b/src/Topbar/Topbar.tsx
@@ -0,0 +1,33 @@
+import "./Topbar.css";
+import strings from "../Intl/strings.json";
+import { useContext } from "react";
+import { LangContext } from "../context";
+import menu from "./menu.png";
+export const Topbar = ({
+ setSidebarEnable,
+}: {
+ setSidebarEnable: (enabled: boolean) => void;
+}) => {
+ const lang = useContext(LangContext);
+ return (
+ <div className="topbar">
+ <img
+ onClick={() => {
+ setSidebarEnable(true);
+ }}
+ src={menu}
+ width="100px"
+ height="100px"
+ alt="Open Selection Menu"
+ ></img>
+ <span className="topbar-span">
+ <h1 className="topbar-span children">
+ {strings[lang].homepage.title}
+ </h1>
+ {/* <p className="topbar-span children">
+ {strings[lang].homepage.description}
+ </p> */}
+ </span>
+ </div>
+ );
+};
diff --git a/src/Topbar/menu.png b/src/Topbar/menu.png
new file mode 100644
index 0000000..ae9b91a
--- /dev/null
+++ b/src/Topbar/menu.png
Binary files differ
diff --git a/src/type/messageTypes.ts b/src/type/messageTypes.ts
index f83594a..0bc76ee 100644
--- a/src/type/messageTypes.ts
+++ b/src/type/messageTypes.ts
@@ -42,5 +42,6 @@ export type Message = {
content: string;
timeMillis: number;
};
+// Type gymnastics to provide dynamic ESLint support
export const acceptedLangs = ["en_US", "zh_TW", "el_GR", "ar_SA"] as const;
export type LangType = (typeof acceptedLangs)[number];