aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/App.css10
-rw-r--r--src/App.tsx23
-rw-r--r--src/Chat/Chat.css20
-rw-r--r--src/Chat/Chat.tsx5
-rw-r--r--src/Intl/strings.json196
-rw-r--r--src/Login/Login.tsx50
-rw-r--r--src/MessageDisplay/MessageDisplay.css4
-rw-r--r--src/MessageDisplay/MessageDisplay.tsx1
-rw-r--r--src/MessageDisplay/messageHandler.tsx5
-rw-r--r--src/index.css16
-rw-r--r--src/type/userTypes.ts6
11 files changed, 209 insertions, 127 deletions
diff --git a/src/App.css b/src/App.css
index 05482ad..e4849cc 100644
--- a/src/App.css
+++ b/src/App.css
@@ -1,6 +1,6 @@
body {
- background-color: black;
- color: #00FF33;
- margin: 1%;
- min-height: 100vh;
-} \ No newline at end of file
+ background-color: black;
+ color: #00FF33;
+ margin: 1%;
+ min-height: 100vh;
+}
diff --git a/src/App.tsx b/src/App.tsx
index e5d3328..7d908e3 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -67,29 +67,10 @@ const App = ({
}: {
changeLang: (value: string) => void;
}): React.ReactElement => {
- const [username, setUsername] = useState<string>();
const [messages, setMessages] = useState<Message[]>([]);
const login = useContext(LoginContext);
const lang = useContext(LangContext);
const home = strings[lang].homepage;
- // TODO refine setName logic -- move to Login handler
- const setNamePrompt = () => {
- var newName = prompt(home.userNamePrompt) as string;
- while (!validateName(newName)) {
- console.log(newName);
-
- prompt("Username invalid! Please enter again.") as string;
- }
- setNameOnServer(newName).then((value) => {
- if (!value.success) {
- alert(value.reason);
- return true;
- } else {
- setUsername(newName);
- return false;
- }
- });
- };
if (!login) {
return <></>;
} else
@@ -116,8 +97,8 @@ const App = ({
})
.then((responseBody: { success: boolean }) => {
if (responseBody.success) {
- setUsername(newUsername as string);
- } 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 d92e700..76b19f6 100644
--- a/src/Chat/Chat.css
+++ b/src/Chat/Chat.css
@@ -1,15 +1,17 @@
.chat-inner-wrapper {
- height: 50vh;
- overflow-y:scroll;
- /* overflow-wrap: normal; */
- display: flex;
- flex-direction: column;
+ height: 50vh;
+ overflow-y: scroll;
+ /* overflow-wrap: normal; */
+ display: flex;
+ flex-direction: column;
}
+
.entry-box {
- margin-top: 5px;
+ margin-top: 5px;
}
+
.chat {
- /* min-height: 80vh; */
- position: relative;
-} \ No newline at end of file
+ /* min-height: 80vh; */
+ position: relative;
+}
diff --git a/src/Chat/Chat.tsx b/src/Chat/Chat.tsx
index 7aff06f..1aa884a 100644
--- a/src/Chat/Chat.tsx
+++ b/src/Chat/Chat.tsx
@@ -125,7 +125,10 @@ const Chat = ({ user }: { user: string }): React.ReactElement => {
return (
<fieldset className="chat">
<legend>
- Logged in as <b>{user}</b>
+ {chatPage.window.title.replaceAll(
+ "$userName",
+ user
+ )}
</legend>
<div className="chat-inner-wrapper">{messages}</div>
<span className="entry-box">
diff --git a/src/Intl/strings.json b/src/Intl/strings.json
index 7dd6bc1..ceff215 100644
--- a/src/Intl/strings.json
+++ b/src/Intl/strings.json
@@ -1,64 +1,136 @@
{
- "variableNames": ["userName", "content"],
- "acceptedLangs": ["en_US", "zh_TW", "el_GR"],
- "en_US": {
- "homepage": {
- "userNamePrompt": "Your username: ",
- "title": "LAN Chat Server",
- "description": "This web application was built for the purposes of an EPQ project.",
- "copyrightText": "Copyright 2024 - 2025 Zhongheng Liu @ Byron College",
- "switchLang": "Switch Language",
- "newLangPrompt": "Input your ISO-639_ISO-3166 language-contry code below - for example: \"en_US\": "
- },
- "chat": {
- "sendButtonPrompt": "Send",
- "serverMessage": "Message from $userName: $content",
- "joinMessage": "$userName joined the server"
- }
- },
- "zh_TW": {
- "homepage": {
- "userNamePrompt": "您的用戶名: ",
- "title": "本地聊天伺服器",
- "description": "該網絡伺服器應用程式專爲Edexcel Level 3 EPQ而製作",
- "copyrightText": "版權所有 2024 - 2025 Zhongheng Liu @ Byron College",
- "switchLang": "切換語言",
- "newLangPrompt": "在下方輸入您想使用的語言的ISO-639_ISO-3166組合語言代碼 - 例如:\"en_US\":"
- },
- "chat": {
- "sendButtonPrompt": "發送",
- "serverMessage": "來自 $userName 的訊息:$content",
- "joinMessage": "$userName 加入了伺服器!"
- }
- },
- "el_GR": {
- "homepage": {
- "userNamePrompt": "το όνομα χρήστη σας: ",
- "title": "Διακομιστής τοπικού δικτύου συνομιλίας",
- "description": "Αυτή η διαδικτυακή εφαρμογή δημιουργήθηκε για τους σκοπούς ενός έργου EPQ.",
- "copyrightText": "Πνευματικά δικαιώματα 2024 - 2025 Zhongheng Liu @ Byron College",
- "switchLang": "Αλλαγή γλώσσας",
- "newLangPrompt": "Εισαγάγετε τον κωδικό γλώσσας-χώρας ISO-639 ISO-3166 παρακάτω - για παράδειγμα: \"en_US\":"
- },
- "chat": {
- "sendButtonPrompt": "Στείλετε",
- "joinMessage": "$userName έγινε μέλος του διακομιστή",
- "serverMessage": "μήνυμα από $userName: $content"
- }
- },
- "ar_SA": {
- "homepage": {
- "userNamePrompt": "اسم المستخدم الخاص بك:",
- "title": "خادم الدردشة LAN",
- "description": "تم إنشاء تطبيق الويب هذا لأغراض مشروع EPQ.",
- "copyrightText": "حقوق الطبع والنشر 2024 - 2025 Zhongheng Liu @ كلية بايرون",
- "switchLang": "تبديل اللغة",
- "newLangPrompt": "أدخل رمز اللغة ISO-639_ISO-3166 أدناه - على سبيل المثال: \"en_US\":"
- },
- "chat": {
- "sendButtonPrompt": "يرسل",
- "joinMessage": "$userName انضم إلى الخادم",
- "serverMessage": "رسالة من $userName: $content"
- }
- }
+ "variableNames": ["userName", "content"],
+ "acceptedLangs": ["en_US", "zh_TW", "el_GR"],
+ "en_US": {
+ "homepage": {
+ "userNamePrompt": "Your username: ",
+ "title": "LAN Chat Server",
+ "description": "This web application was built for the purposes of an EPQ project.",
+ "copyrightText": "Copyright 2024 - 2025 Zhongheng Liu @ Byron College",
+ "switchLang": "Switch Language",
+ "newLangPrompt": "Input your ISO-639_ISO-3166 language-contry code below - for example: \"en_US\": "
+ },
+ "chat": {
+ "window": {
+ "title": "Logged in as $userName"
+ },
+ "sendButtonPrompt": "Send",
+ "serverMessage": "Message from $userName: $content",
+ "joinMessage": "$userName joined the server"
+ },
+ "login": {
+ "error": {
+ "unameTakenOrInvalid": "Username is taken or invalid!",
+ "unameNotExists": "Username does not exist!",
+ "passwdInvalid": "Password incorrect!"
+ },
+ "window": {
+ "title": "Login window",
+ "uname": "Username: ",
+ "login": "Login",
+ "passwd": "Password: ",
+ "register": "Register",
+ "logout": "Logout"
+ }
+ }
+ },
+ "zh_TW": {
+ "homepage": {
+ "userNamePrompt": "您的用戶名: ",
+ "title": "本地聊天伺服器",
+ "description": "該網絡伺服器應用程式專爲Edexcel Level 3 EPQ而製作",
+ "copyrightText": "版權所有 2024 - 2025 Zhongheng Liu @ Byron College",
+ "switchLang": "切換語言",
+ "newLangPrompt": "在下方輸入您想使用的語言的ISO-639_ISO-3166組合語言代碼 - 例如:\"en_US\":"
+ },
+ "chat": {
+ "window": {
+ "title": "當前以 $userName 登入"
+ },
+ "sendButtonPrompt": "發送",
+ "serverMessage": "來自 $userName 的訊息:$content",
+ "joinMessage": "$userName 加入了伺服器!"
+ },
+ "login": {
+ "error": {
+ "unameTakenOrInvalid": "用戶名已存在或不合規!",
+ "unameNotExists": "該用戶不存在!",
+ "passwdInvalid": "密碼不正確!"
+ },
+ "window": {
+ "title": "登入窗口",
+ "uname": "用戶名:",
+ "login": "登入",
+ "passwd": "密碼:",
+ "register": "註冊",
+ "logout": "登出"
+ }
+ }
+ },
+ "el_GR": {
+ "homepage": {
+ "userNamePrompt": "το όνομα χρήστη σας: ",
+ "title": "Διακομιστής τοπικού δικτύου συνομιλίας",
+ "description": "Αυτή η διαδικτυακή εφαρμογή δημιουργήθηκε για τους σκοπούς ενός έργου EPQ.",
+ "copyrightText": "Πνευματικά δικαιώματα 2024 - 2025 Zhongheng Liu @ Byron College",
+ "switchLang": "Αλλαγή γλώσσας",
+ "newLangPrompt": "Εισαγάγετε τον κωδικό γλώσσας-χώρας ISO-639 ISO-3166 παρακάτω - για παράδειγμα: \"en_US\":"
+ },
+ "chat": {
+ "window": {
+ "title": "Συνδεδεμένος ως $userName"
+ },
+ "sendButtonPrompt": "Στείλετε",
+ "joinMessage": "$userName έγινε μέλος του διακομιστή",
+ "serverMessage": "μήνυμα από $userName: $content"
+ },
+ "login": {
+ "error": {
+ "unameTakenOrInvalid": "Το όνομα χρήστη έχει ληφθεί ή δεν είναι έγκυρο!",
+ "unameNotExists": "Το όνομα χρήστη δεν υπάρχει!",
+ "passwdInvalid": "Λάθος κωδικός!"
+ },
+ "window": {
+ "title": "Παράθυρο σύνδεσης",
+ "uname": "Όνομα χρήστη: ",
+ "login": "Σύνδεση",
+ "passwd": "Κωδικός πρόσβασης: ",
+ "register": "Εγγραφή",
+ "logout": "Αποσύνδεση"
+ }
+ }
+ },
+ "ar_SA": {
+ "homepage": {
+ "userNamePrompt": "اسم المستخدم الخاص بك:",
+ "title": "خادم الدردشة LAN",
+ "description": "تم إنشاء تطبيق الويب هذا لأغراض مشروع EPQ.",
+ "copyrightText": "حقوق الطبع والنشر 2024 - 2025 Zhongheng Liu @ كلية بايرون",
+ "switchLang": "تبديل اللغة",
+ "newLangPrompt": "أدخل رمز اللغة ISO-639_ISO-3166 أدناه - على سبيل المثال: \"en_US\":"
+ },
+ "chat": {
+ "window": {
+ "title": "Logged in as $userName"
+ },
+ "sendButtonPrompt": "يرسل",
+ "joinMessage": "$userName انضم إلى الخادم",
+ "serverMessage": "رسالة من $userName: $content"
+ },
+ "login": {
+ "error": {
+ "unameTakenOrInvalid": "Username is taken or invalid!",
+ "unameNotExists": "Username does not exist!",
+ "passwdInvalid": "Password incorrect!"
+ },
+ "window": {
+ "title": "Login window",
+ "uname": "Username: ",
+ "login": "Login",
+ "passwd": "Password: ",
+ "register": "Register",
+ "logout": "Logout"
+ }
+ }
+ }
}
diff --git a/src/Login/Login.tsx b/src/Login/Login.tsx
index 7f5ff79..6518eff 100644
--- a/src/Login/Login.tsx
+++ b/src/Login/Login.tsx
@@ -1,8 +1,9 @@
-import { useState } from "react";
+import { useContext, useState } from "react";
import { contentTypes, domain, endpoints, port } from "../consts";
-import { LoginType } from "../context";
+import { LangContext, LoginType } from "../context";
import { User } from "../type/userTypes";
import "./Login.css";
+import strings from "../Intl/strings.json";
const encrypt = (rawPasswordString: string) => {
// TODO Encryption method stub
return rawPasswordString;
@@ -12,8 +13,10 @@ export const Login = ({
}: {
setLogin: (newLogin: LoginType | undefined) => void;
}): React.ReactElement => {
- const [valid, setValid] = useState<boolean | undefined>(true);
+ const [valid, setValid] = useState<boolean | undefined>(undefined);
const [validText, setValidText] = useState<string | undefined>();
+ const lang = useContext(LangContext);
+ const loginPage = strings[lang].login;
const registrationHandler = () => {
const uname = (
document.getElementById("username") as HTMLInputElement
@@ -36,7 +39,9 @@ export const Login = ({
// 400 Bad request
console.log("Username is taken or invalid!");
setValid(false);
- setValidText("Username is taken or invalid!");
+ setValidText(
+ loginPage.error.unameTakenOrInvalid
+ );
} else if (response.status === 200) {
// 200 OK
const futureDate = new Date();
@@ -73,7 +78,7 @@ export const Login = ({
"404 not found encountered"
);
throw new Error(
- "Username does not exist"
+ loginPage.error.unameNotExists
);
} else if (res.status === 200) {
console.log("200 OK");
@@ -88,9 +93,12 @@ export const Login = ({
const validLogin = passwd === user.passwordHash;
if (!validLogin) {
// login invalid
- throw new Error("Password incorrect!");
+ throw new Error(
+ loginPage.error.passwdInvalid
+ );
} else {
// login valid
+ setValid(true);
const validUntilDate: Date = new Date();
validUntilDate.setHours(
validUntilDate.getHours() + 2
@@ -111,47 +119,51 @@ export const Login = ({
return (
<div className="login">
<fieldset>
- <legend>Login window</legend>
+ <legend>{loginPage.window.title}</legend>
<p className="uname-error-text">
- {valid && valid !== undefined
- ? ""
- : validText}
+ {!valid && valid !== undefined
+ ? validText
+ : ""}
</p>
- <label htmlFor="username">Username: </label>
+ <label htmlFor="username">
+ {loginPage.window.uname}
+ </label>
<br />
<input id="username" type="text"></input>
<br />
- <label htmlFor="passwd">Password: </label>
+ <label htmlFor="passwd">
+ {loginPage.window.passwd}
+ </label>
<br />
<input id="passwd" type="password"></input>
<br />
<button
- disabled={!valid}
+ disabled={valid}
type="submit"
onClick={() => {
loginHandler();
}}
>
- Login
+ {loginPage.window.login}
</button>
<button
- disabled={!valid}
+ disabled={valid}
type="submit"
onClick={() => {
registrationHandler();
}}
>
- Register
+ {loginPage.window.register}
</button>
<button
- disabled={valid}
+ disabled={!valid}
type="submit"
onClick={() => {
setLogin(undefined);
- setValid(false);
+ setValid(undefined);
}}
>
- Logout
+ {loginPage.window.logout}
</button>
</fieldset>
</div>
diff --git a/src/MessageDisplay/MessageDisplay.css b/src/MessageDisplay/MessageDisplay.css
index 15af7eb..7ca7722 100644
--- a/src/MessageDisplay/MessageDisplay.css
+++ b/src/MessageDisplay/MessageDisplay.css
@@ -1,3 +1,3 @@
.msg .msg-err {
- overflow-wrap: break-word;
-} \ No newline at end of file
+ overflow-wrap: break-word;
+}
diff --git a/src/MessageDisplay/MessageDisplay.tsx b/src/MessageDisplay/MessageDisplay.tsx
index 92e9e79..18a9277 100644
--- a/src/MessageDisplay/MessageDisplay.tsx
+++ b/src/MessageDisplay/MessageDisplay.tsx
@@ -3,6 +3,7 @@ import { Message, MessageType } from "../type/messageTypes";
import { LangContext } from "../context";
import strings from "../Intl/strings.json";
import "./MessageDisplay.css";
+import { queryByRole } from "@testing-library/react";
export const MessageDisplay = ({
type,
fromUserId,
diff --git a/src/MessageDisplay/messageHandler.tsx b/src/MessageDisplay/messageHandler.tsx
new file mode 100644
index 0000000..801692e
--- /dev/null
+++ b/src/MessageDisplay/messageHandler.tsx
@@ -0,0 +1,5 @@
+import {Message, MessageType } from "../type/messageTypes"
+export const dataMsgHandler = (msg: Message) => {
+ if (msg.type !== MessageType.DATA) {return <></>}
+}
+export const chnameMsgHandler = () => {}
diff --git a/src/index.css b/src/index.css
index ec2585e..a158d83 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,13 +1,13 @@
body {
- margin: 0;
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
- sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
}
code {
- font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
- monospace;
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ monospace;
}
diff --git a/src/type/userTypes.ts b/src/type/userTypes.ts
index b888745..d5c1e37 100644
--- a/src/type/userTypes.ts
+++ b/src/type/userTypes.ts
@@ -1,7 +1,13 @@
+import { URL } from "url";
+
+export type UserAvatar = {
+ iconUrls: URL[];
+};
export type User = {
id: number;
userName: string;
dateJoined: number;
lastSeen: number;
passwordHash: string;
+ // avatar: UserAvatar;
};