More Restructure, Formatting all file contents

Breaking stuff into components piece by piece. Also used Prettier on all files in one commit. (Should stick to a consistent, readable format !!)
This commit is contained in:
ClarkLach
2024-03-30 01:30:36 -04:00
parent 1a6700a983
commit a4fc9bdce0
20 changed files with 1012 additions and 774 deletions
+1 -3
View File
@@ -11,9 +11,7 @@ export const metadata = {
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
<body className={inter.className}>{children}</body>
</html>
);
}
+198 -158
View File
@@ -4,9 +4,8 @@ import { useState, useEffect } from "react";
import { auth, database } from "../../../firebase-config";
import { ref, onValue, set, remove, get } from "firebase/database";
import { useBeforeunload } from "react-beforeunload";
import {Marker} from "pigeon-maps";
import {onAuthStateChanged} from "firebase/auth"
import { Marker } from "pigeon-maps";
import { onAuthStateChanged } from "firebase/auth";
// Refactored Component Imports
// Data Structure Imports
@@ -20,7 +19,7 @@ import { MainTabChatRoom } from "../../components/app/main_tab/chat";
import { MainTabHome } from "../../components/app/main_tab/home";
// Sidebar Imports
import {Home_Sidebar} from "../../components/app/sidebar/home";
import { Home_Sidebar } from "../../components/app/sidebar/home";
import { Chat_Sidebar } from "../../components/app/sidebar/chat";
import { Profile_Sidebar } from "../../components/app/sidebar/profile";
@@ -43,90 +42,100 @@ function Home() {
const [chatroomUsers, setChatroomUsers] = useState(null); // holds all chatroom users
const [chatroomUsersLoading, setChatroomUsersLoading] = useState(true);
const [markers, setMarkers] = useState([]);
const [isAuthenticated, setAuth] = useState(false)
const [user, setUser] = useState(null)
const [usingSearchParams, setUsingSearchParams] = useState(true)
const [isAuthenticated, setAuth] = useState(false);
const [user, setUser] = useState(null);
const [usingSearchParams, setUsingSearchParams] = useState(true);
useEffect(() => {
const searchParams = new URLSearchParams(document.location.search);
var roomSwitch = null
var roomSwitch = null;
if (searchParams.has("room") && usingSearchParams && user) {
roomSwitch = searchParams.get("room")
setUsingSearchParams(false)
get(ref(database, `rooms/${searchParams.get("room")}`)).then((snapshot) => {
selectChatRoom(snapshot.val())
});
roomSwitch = searchParams.get("room");
setUsingSearchParams(false);
get(ref(database, `rooms/${searchParams.get("room")}`)).then(
(snapshot) => {
selectChatRoom(snapshot.val());
}
);
}
}, [user])
}, [user]);
// Authentication
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
get(ref(database, `users/${user.uid}`))
.then((userData) => {
userData = userData.val()
get(ref(database, `users/${user.uid}`)).then((userData) => {
userData = userData.val();
if (userData) {
setUser(userData)
setAuth(true)
setUser(userData);
setAuth(true);
} else {
window.location.href = "/onboarding"
window.location.href = "/onboarding";
}
})
});
} else {
setAuth(false)
window.location.href = "/login"
setAuth(false);
window.location.href = "/login";
}
})
}, [])
});
}, []);
// Grabs user data, saves to user, then lists the users saved rooms
useEffect(() => {
if (user) {
onValue(ref(database, "/users/" + user.uid + "/rooms"), (snapshot) => {
setRoomLoading(true);
var rooms = snapshot.val();
setMyRoomsObj(rooms);
var roomArr = [];
var markerArr = markers;
for (var room in rooms) {
var newRoom = (
<ChatRoomSidebar
roomObj={rooms[room]}
key={rooms[room].timestamp}
click={selectChatRoom}
/>
);
markerArr.push(
<Marker
width={30}
anchor={[rooms[room].latitude, rooms[room].longitude]}
color="blue"
onClick = {() => window.location.href = "/app?room="+rooms[room].path+"/"+rooms[room].name+"-"+rooms[room].timestamp}
/>
);
roomArr.push(newRoom);
}
setMarkers(markerArr);
setRoomData(roomArr);
setRoomLoading(false);
});
if (user) {
onValue(ref(database, "/users/" + user.uid + "/rooms"), (snapshot) => {
setRoomLoading(true);
var rooms = snapshot.val();
setMyRoomsObj(rooms);
var roomArr = [];
var markerArr = markers;
for (var room in rooms) {
var newRoom = (
<ChatRoomSidebar
roomObj={rooms[room]}
key={rooms[room].timestamp}
click={selectChatRoom}
/>
);
markerArr.push(
<Marker
width={30}
anchor={[rooms[room].latitude, rooms[room].longitude]}
color="blue"
onClick={() =>
(window.location.href =
"/app?room=" +
rooms[room].path +
"/" +
rooms[room].name +
"-" +
rooms[room].timestamp)
}
/>
);
roomArr.push(newRoom);
}
},[user]);
setMarkers(markerArr);
setRoomData(roomArr);
setRoomLoading(false);
});
}
}, [user]);
// Grabs the user location
useEffect(() => {
if ("geolocation" in navigator && user) {
// Retrieve latitude & longitude coordinates from `navigator.geolocation` Web API
navigator.geolocation.getCurrentPosition(({ coords }) => {
setLocation(coords)
setLoadingLoc(false)
var path = String(coords.latitude.toFixed(2)).replace(".","")+"/"+String(coords.longitude.toFixed(2)).replace(".","")
var markersArr = markers
setLocation(coords);
setLoadingLoc(false);
var path =
String(coords.latitude.toFixed(2)).replace(".", "") +
"/" +
String(coords.longitude.toFixed(2)).replace(".", "");
var markersArr = markers;
onValue(ref(database, `/rooms/${path}`), (snapshot) => {
var nearbyArr = []
var nearbyArr = [];
if (snapshot.exists()) {
var data = snapshot.val();
for (var room in data) {
@@ -139,7 +148,15 @@ function Home() {
width={30}
anchor={[data[room].latitude, data[room].longitude]}
color="blue"
onClick = {() => window.location.href = "/app?room="+data[room].path+"/"+data[room].name+"-"+data[room].timestamp}
onClick={() =>
(window.location.href =
"/app?room=" +
data[room].path +
"/" +
data[room].name +
"-" +
data[room].timestamp)
}
/>
);
}
@@ -152,7 +169,7 @@ function Home() {
});
});
}
},[user]);
}, [user]);
// Dont Double Send Leaving Message
useEffect(() => {
@@ -170,98 +187,98 @@ function Home() {
// Selects chat room
function selectChatRoom(roomObj) {
// Path of chatroom
var path = roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp;
// Path of chatroom
var path = roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp;
setChatRoomObj(roomObj);
setChatRoomObj(roomObj);
// Send entered message
var payload = {
body: "entered",
user: user.username,
isSystem: true,
timestamp: new Date().getTime(),
uid: user.uid
};
set(
ref(
database,
`/rooms/${path}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
// Send entered message
var payload = {
body: "entered",
user: user.username,
isSystem: true,
timestamp: new Date().getTime(),
uid: user.uid,
};
set(
ref(
database,
`/rooms/${path}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
// Code for Room Data
set(ref(database, `/rooms/${path}/users/online/${user.uid}`), user);
onValue(ref(database, `/rooms/${path}`), (snapshot) => {
setChatRoomOnline(null);
setChatroomUsers(null);
// Code for Room Data
set(ref(database, `/rooms/${path}/users/online/${user.uid}`), user);
onValue(ref(database, `/rooms/${path}`), (snapshot) => {
setChatRoomOnline(null);
setChatroomUsers(null);
// Active users list
if (
snapshot.val().hasOwnProperty("users") &&
snapshot.val().users.hasOwnProperty("online")
) {
var activeUsers = [];
var activeUsersJSON = snapshot.val().users.online;
for (var user in activeUsersJSON)
activeUsers.push(<Member memberObj={activeUsersJSON[user]} />);
setChatRoomOnline(activeUsers);
}
// Active users list
if (
snapshot.val().hasOwnProperty("users") &&
snapshot.val().users.hasOwnProperty("online")
) {
var activeUsers = [];
var activeUsersJSON = snapshot.val().users.online;
for (var user in activeUsersJSON)
activeUsers.push(<Member memberObj={activeUsersJSON[user]} />);
setChatRoomOnline(activeUsers);
}
// Users who added to "my rooms"
if (
snapshot.val().hasOwnProperty("users") &&
snapshot.val().users.hasOwnProperty("all")
) {
setChatroomUsersLoading(true);
var allUsers = [];
var allUsersJSON = snapshot.val().users.all;
for (var user in allUsersJSON)
allUsers.push(<Member memberObj={allUsersJSON[user]} />);
setChatroomUsers(allUsers);
setChatroomUsersLoading(false);
}
});
setMainTab("chat");
// Users who added to "my rooms"
if (
snapshot.val().hasOwnProperty("users") &&
snapshot.val().users.hasOwnProperty("all")
) {
setChatroomUsersLoading(true);
var allUsers = [];
var allUsersJSON = snapshot.val().users.all;
for (var user in allUsersJSON)
allUsers.push(<Member memberObj={allUsersJSON[user]} />);
setChatroomUsers(allUsers);
setChatroomUsersLoading(false);
}
});
setMainTab("chat");
}
// Fires to tell other uses that you are leaving the room
useBeforeunload(() => {
if (chatRoomObj && mainTab == "chat") {
var payload = {
body: "left",
user: user.username,
isSystem: true,
timestamp: new Date().getTime(),
uid: user.uid
};
set(
ref(
database,
`/rooms/${
chatRoomObj.path +
"/" +
chatRoomObj.name +
"-" +
chatRoomObj.timestamp
}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
remove(
ref(
database,
`/rooms/${
chatRoomObj.path +
"/" +
chatRoomObj.name +
"-" +
chatRoomObj.timestamp
}/users/online/${userID}`
)
);
}
if (chatRoomObj && mainTab == "chat") {
var payload = {
body: "left",
user: user.username,
isSystem: true,
timestamp: new Date().getTime(),
uid: user.uid,
};
set(
ref(
database,
`/rooms/${
chatRoomObj.path +
"/" +
chatRoomObj.name +
"-" +
chatRoomObj.timestamp
}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
remove(
ref(
database,
`/rooms/${
chatRoomObj.path +
"/" +
chatRoomObj.name +
"-" +
chatRoomObj.timestamp
}/users/online/${userID}`
)
);
}
});
return (
@@ -271,32 +288,55 @@ function Home() {
{/* Left Side of Page */}
<div className="col-span-3 h-dvh">
{/* Header */}
<Header mainTab={mainTab} isMyRoom={isMyRoom} chatRoomObj={chatRoomObj} setChatRoomObj={setChatRoomObj} setMainTab={setMainTab} setIsMyRoom={setIsMyRoom} user={user}/>
<Header
mainTab={mainTab}
isMyRoom={isMyRoom}
chatRoomObj={chatRoomObj}
setChatRoomObj={setChatRoomObj}
setMainTab={setMainTab}
setIsMyRoom={setIsMyRoom}
user={user}
/>
{/* Main Page Section */}
<div className="mr-2 h-[calc(100%-110px)]">
{mainTab == "home" && !loadingLoc && (
<MainTabHome loc={location} markers={markers} user={user}/>
<MainTabHome loc={location} markers={markers} user={user} />
)}
{mainTab == "home" && loadingLoc && (
<MainTabHome loc={null} markers={markers} user={user}/>
<MainTabHome loc={null} markers={markers} user={user} />
)}
{mainTab == "chat" && (
<MainTabChatRoom roomObj={chatRoomObj} user={user} />
)}
{mainTab == "chat" && <MainTabChatRoom roomObj={chatRoomObj} user={user}/>}
</div>
</div>
{/* Sidebar (Right Side of Page) */}
{mainTab == "home" && (
<Home_Sidebar tab={tab} nearby={nearby} loadingNearby={loadingNearby} setTab={setTab} isRoomLoading={isRoomLoading} myRooms={myRooms} loadingLoc={loadingLoc} location={location}/>
<Home_Sidebar
tab={tab}
nearby={nearby}
loadingNearby={loadingNearby}
setTab={setTab}
isRoomLoading={isRoomLoading}
myRooms={myRooms}
loadingLoc={loadingLoc}
location={location}
/>
)}
{mainTab == "chat" && (
<Chat_Sidebar chatRoomObj={chatRoomObj} chatroomOnline={chatroomOnline} chatroomUsersLoading={chatroomUsersLoading} chatroomUsers={chatroomUsers} setTab={setTab}/>
)}
{mainTab == "profile" && (
<Profile_Sidebar/>
<Chat_Sidebar
chatRoomObj={chatRoomObj}
chatroomOnline={chatroomOnline}
chatroomUsersLoading={chatroomUsersLoading}
chatroomUsers={chatroomUsers}
setTab={setTab}
/>
)}
{mainTab == "profile" && <Profile_Sidebar />}
</div>
)}
</div>
</div>
);
}
export default Home;
export default Home;
+1 -1
View File
@@ -5,7 +5,7 @@
body {
background-color: aliceblue;
text-align: center;
text-wrap:pretty;
text-wrap: pretty;
}
button {
+1 -3
View File
@@ -11,9 +11,7 @@ export const metadata = {
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
<body className={inter.className}>{children}</body>
</html>
);
}
+109 -53
View File
@@ -1,66 +1,122 @@
"use client";
import { useForm, Form } from "react-hook-form";
import { useRouter } from "next/navigation";
import "../globals.css"
import "../globals.css";
// Firebase imports
import {auth} from "../../../firebase-config";
import { setPersistence, signInWithEmailAndPassword, indexedDBLocalPersistence } from "firebase/auth";
import { auth } from "../../../firebase-config";
import {
setPersistence,
signInWithEmailAndPassword,
indexedDBLocalPersistence,
} from "firebase/auth";
function Login() {
var router = useRouter();
//var { register, handleSubmit } = useForm();
var { register, control, setError, handleSubmit, formState: { errors, isSubmitting, isSubmitted } } = useForm()
var router = useRouter();
//var { register, handleSubmit } = useForm();
var {
register,
control,
setError,
handleSubmit,
formState: { errors, isSubmitting, isSubmitted },
} = useForm();
function authenticate(data) {
setPersistence(auth, indexedDBLocalPersistence)
.then(() => {
signInWithEmailAndPassword(auth,data.email,data.password)
.then((userCredential) => {
if (userCredential.user) {
router.push("/app")
} else {
const formError = { type: "server", message: "Username or Password Incorrect" }
// set same error in both:
setError('password', formError)
setError('email', formError)
}
})
})
}
function authenticate(data) {
setPersistence(auth, indexedDBLocalPersistence).then(() => {
signInWithEmailAndPassword(auth, data.email, data.password).then(
(userCredential) => {
if (userCredential.user) {
router.push("/app");
} else {
const formError = {
type: "server",
message: "Username or Password Incorrect",
};
// set same error in both:
setError("password", formError);
setError("email", formError);
}
}
);
});
}
return (
return (
<div>
<div className="grid h-screen place-items-center">
<div>
<div className="grid h-screen place-items-center">
<div>
<a href="/"><img src="logos/logo_transparent_inverse.png"/></a>
<span className="text-[36px]">
Chat with friends!
</span>
<div>
<h3 className="text-[24px] mt-[25px] mb-2">Login</h3>
{(errors.email && errors.password) && <div className="text-[red] mb-2 text-[18px] text-bold">Invalid Email or Password.</div>}
<Form onSubmit={handleSubmit(authenticate)} encType={'application/json'}
control={control}
>
<input type="email" id="email" className={(errors.email && errors.password) && "err"} {...register("email", { required: true })} placeholder="Enter Email Address"/><br/>
<input type="password" id="password" name="password" className={(errors.email && errors.password) && "err"} {...register("password", { required: true })} placeholder="Enter Password"/><br/>
<button type="submit" className="inline-flex items-center transition ease-in-out duration-150 m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">
{(isSubmitting || isSubmitted) && <span className="inline-block">
<svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" strokeWidth="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</span> }
Log In
</button>
<br/>Need an account? <a href="/register">Sign Up</a><br/>
</Form>
</div>
</div>
</div>
<a href="/">
<img src="logos/logo_transparent_inverse.png" />
</a>
<span className="text-[36px]">Chat with friends!</span>
<div>
<h3 className="text-[24px] mt-[25px] mb-2">Login</h3>
{errors.email && errors.password && (
<div className="text-[red] mb-2 text-[18px] text-bold">
Invalid Email or Password.
</div>
)}
<Form
onSubmit={handleSubmit(authenticate)}
encType={"application/json"}
control={control}
>
<input
type="email"
id="email"
className={errors.email && errors.password && "err"}
{...register("email", { required: true })}
placeholder="Enter Email Address"
/>
<br />
<input
type="password"
id="password"
name="password"
className={errors.email && errors.password && "err"}
{...register("password", { required: true })}
placeholder="Enter Password"
/>
<br />
<button
type="submit"
className="inline-flex items-center transition ease-in-out duration-150 m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full"
>
{(isSubmitting || isSubmitted) && (
<span className="inline-block">
<svg
class="animate-spin -ml-1 mr-3 h-5 w-5 text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
class="opacity-25"
cx="12"
cy="12"
r="10"
strokeWidth="4"
></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</span>
)}
Log In
</button>
<br />
Need an account? <a href="/register">Sign Up</a>
<br />
</Form>
</div>
</div>
)
</div>
</div>
);
}
export default Login;
export default Login;
+2 -4
View File
@@ -5,15 +5,13 @@ const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "ChatMaps: Onboarding",
description: "ChatMaps: Social Media for College Students"
description: "ChatMaps: Social Media for College Students",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
<body className={inter.className}>{children}</body>
</html>
);
}
+61 -43
View File
@@ -1,57 +1,75 @@
"use client";
import "../globals.css"
import "../globals.css";
import { useForm } from "react-hook-form";
import { useRouter } from "next/navigation";
import { ref, set } from "firebase/database";
import {auth, database} from "../../../firebase-config"
import {onAuthStateChanged} from "firebase/auth"
import { auth, database } from "../../../firebase-config";
import { onAuthStateChanged } from "firebase/auth";
function createUser(data) {
onAuthStateChanged(auth, (user) => {
if (user.uid) {
data.uid = user.uid
data.defined = true
data.email = user.email
set(ref(database, `users/${user.uid}`), data);
return true
} else {
return false
}
})
onAuthStateChanged(auth, (user) => {
if (user.uid) {
data.uid = user.uid;
data.defined = true;
data.email = user.email;
set(ref(database, `users/${user.uid}`), data);
return true;
} else {
return false;
}
});
}
function Onboarding() {
var router = useRouter();
var { register, handleSubmit } = useForm();
var router = useRouter();
var { register, handleSubmit } = useForm();
function Onboard(data) {
createUser(data)
router.push("/app");
}
return (
function Onboard(data) {
createUser(data);
router.push("/app");
}
return (
<div>
<div className="grid h-screen place-items-center">
<div>
<div className="grid h-screen place-items-center">
<div>
<img src="logos/logo_transparent_inverse.png"/>
<span className="text-[36px]">
Chat with friends!
</span>
<div className="m-5">
Welcome to ChatMaps! We are excited to have you join our community!<br/>First we just need a little bit of information from you to get started.
</div>
<form action="#" onSubmit={handleSubmit(Onboard)}>
<input type="text" {...register("username")} placeholder="Display Name"/><br/>
<input type="text" {...register("firstName")} placeholder="First Name"/><br/>
<input type="text" {...register("lastName")} placeholder="Last Name"/><br/>
<button type="submit" className="inline-flex items-center px-4 py-2 transition ease-in-out duration-150 bg-[#dee0e0] m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full">Save</button>
</form>
</div>
</div>
<img src="logos/logo_transparent_inverse.png" />
<span className="text-[36px]">Chat with friends!</span>
<div className="m-5">
Welcome to ChatMaps! We are excited to have you join our community!
<br />
First we just need a little bit of information from you to get
started.
</div>
<form action="#" onSubmit={handleSubmit(Onboard)}>
<input
type="text"
{...register("username")}
placeholder="Display Name"
/>
<br />
<input
type="text"
{...register("firstName")}
placeholder="First Name"
/>
<br />
<input
type="text"
{...register("lastName")}
placeholder="Last Name"
/>
<br />
<button
type="submit"
className="inline-flex items-center px-4 py-2 transition ease-in-out duration-150 bg-[#dee0e0] m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full"
>
Save
</button>
</form>
</div>
)
</div>
</div>
);
}
export default Onboarding;
export default Onboarding;
+1 -3
View File
@@ -11,9 +11,7 @@ export const metadata = {
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
<body className={inter.className}>{children}</body>
</html>
);
}
+104 -55
View File
@@ -1,73 +1,122 @@
"use client";
import { useRouter } from "next/navigation";
import { useForm, Form } from "react-hook-form";
import "../globals.css"
import "../globals.css";
import { useState } from "react";
import { createUserWithEmailAndPassword, signInWithEmailAndPassword, setPersistence, indexedDBLocalPersistence } from "firebase/auth";
import {auth} from "../../../firebase-config";
import {
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
setPersistence,
indexedDBLocalPersistence,
} from "firebase/auth";
import { auth } from "../../../firebase-config";
async function Signup(data) {
var userCredential = await createUserWithEmailAndPassword(auth,data.email,data.password);
if (userCredential.user) {
setPersistence(auth, indexedDBLocalPersistence )
.then(() => {
signInWithEmailAndPassword(auth,data.email,data.password)
.then((res) => {
return true
})
})
} else {
return false
}
var userCredential = await createUserWithEmailAndPassword(
auth,
data.email,
data.password
);
if (userCredential.user) {
setPersistence(auth, indexedDBLocalPersistence).then(() => {
signInWithEmailAndPassword(auth, data.email, data.password).then(
(res) => {
return true;
}
);
});
} else {
return false;
}
}
function Register() {
var router = useRouter();
var { register, control, formState: { errors } } = useForm()
var emailRegex = /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/
var [passwordMismatch, setPasswordMismatch] = useState(false);
const passwordMatch = (data) => {
return data.password === data.passwordCheck;
};
var router = useRouter();
var {
register,
control,
formState: { errors },
} = useForm();
var emailRegex =
/(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/;
var [passwordMismatch, setPasswordMismatch] = useState(false);
const passwordMatch = (data) => {
return data.password === data.passwordCheck;
};
function onSubmit({data}) {
if (passwordMatch(data)) {
setPasswordMismatch(false);
if (Signup(data)) {
router.push("/onboarding");
}
} else{
setPasswordMismatch(true);
return;
}
function onSubmit({ data }) {
if (passwordMatch(data)) {
setPasswordMismatch(false);
if (Signup(data)) {
router.push("/onboarding");
}
} else {
setPasswordMismatch(true);
return;
}
}
return (
return (
<div>
<div className="grid h-screen place-items-center">
<div>
<div className="grid h-screen place-items-center">
<div>
<a href="/"><img src="logos/logo_transparent_inverse.png"/></a>
<span className="text-[36px]">
Chat with friends!
</span>
<div>
<h3 className="text-[24px] mt-[15px]">Register</h3>
<Form onSubmit={onSubmit} encType={'application/json'} control={control}>
<input type="email" {...register("email", {required: true, pattern: emailRegex})} className={errors.email && "err"} placeholder="Enter Email Address"/><br/>
<input type="password" {...register("password", {required: true})} className={errors.password && errors.password.type == 'required' && "err"} placeholder="Enter Password"/><br/>
<input type ="password" {...register("passwordCheck", {required: false})} className ={errors.passwordCheck && errors.passwordCheck.type == 'required' && "err"} placeholder="Re-enter Password"/><br/>
{passwordMismatch && <p className="text-red-500">Passwords do not match</p>}
<button type="submit" className=" m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full"> Register</button><br/>
Have an account? <a href="/login">Log In</a>
</Form>
</div>
</div>
</div>
<a href="/">
<img src="logos/logo_transparent_inverse.png" />
</a>
<span className="text-[36px]">Chat with friends!</span>
<div>
<h3 className="text-[24px] mt-[15px]">Register</h3>
<Form
onSubmit={onSubmit}
encType={"application/json"}
control={control}
>
<input
type="email"
{...register("email", { required: true, pattern: emailRegex })}
className={errors.email && "err"}
placeholder="Enter Email Address"
/>
<br />
<input
type="password"
{...register("password", { required: true })}
className={
errors.password && errors.password.type == "required" && "err"
}
placeholder="Enter Password"
/>
<br />
<input
type="password"
{...register("passwordCheck", { required: false })}
className={
errors.passwordCheck &&
errors.passwordCheck.type == "required" &&
"err"
}
placeholder="Re-enter Password"
/>
<br />
{passwordMismatch && (
<p className="text-red-500">Passwords do not match</p>
)}
<button
type="submit"
className=" m-5 bg-cyan-500 text-white font-bold py-2 px-4 rounded-full"
>
{" "}
Register
</button>
<br />
Have an account? <a href="/login">Log In</a>
</Form>
</div>
</div>
)
</div>
</div>
);
}
export default Register;
+1 -3
View File
@@ -11,9 +11,7 @@ export const metadata = {
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
</body>
<body className={inter.className}>{children}</body>
</html>
);
}
+170 -105
View File
@@ -2,14 +2,15 @@
// System Imports
import { useState, useEffect } from "react";
import { auth, database, storage } from "../../../../firebase-config";
import { ref, onValue, get, update } from "firebase/database";
import { ref as sRef, getDownloadURL } from "firebase/storage";
import {onAuthStateChanged} from "firebase/auth"
import { ref, onValue, get, update } from "firebase/database";
import { ref as sRef, getDownloadURL } from "firebase/storage";
import { onAuthStateChanged } from "firebase/auth";
import { useForm, Form } from "react-hook-form";
// Refactored Component Imports
// Data Structure Imports
import { Interest, ProfileRoom } from "../../../components/app/datatypes";
import { ProfileRoom } from "../../../components/app/profile/ProfileRoom";
import { Interest } from "../../../components/app/profile/Interest";
// Header Import
import { Header } from "../../../components/app/header";
@@ -19,89 +20,89 @@ import { uploadBytes } from "firebase/storage";
function Home({ params }) {
// It's time to document and change these awful variable names
// State variables for app page
const [profileData, setProfileData] = useState(null)
const [isAuthenticated, setAuth] = useState(false)
const [user, setUser] = useState(null)
const [userInterestArray, setUserInterestArray] = useState(null)
const [userRoomsArray, setUserRoomsArray] = useState(null)
const [isOwner, setOwn] = useState(false)
const [isEditing, setEdit] = useState(false)
const [profileData, setProfileData] = useState(null);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [user, setUser] = useState(null);
const [userInterestArray, setUserInterestArray] = useState(null);
const [userRoomsArray, setUserRoomsArray] = useState(null);
const [isOwner, setIsOwner] = useState(false);
const [isEditing, setIsEditing] = useState(false);
var { register, control} = useForm()
var { register, control } = useForm();
// Authentication
useEffect(() => {
onAuthStateChanged(auth, (user) => {
if (user) {
get(ref(database, `users/${user.uid}`))
.then((userData) => {
userData = userData.val()
get(ref(database, `users/${user.uid}`)).then((userData) => {
userData = userData.val();
if (userData) {
if (userData.uid == params.stub) {
setOwn(true)
setIsOwner(true);
}
setUser(userData)
setAuth(true)
setUser(userData);
setIsAuthenticated(true);
} else {
window.location.href = "/onboarding"
window.location.href = "/onboarding";
}
})
});
} else {
setAuth(false)
window.location.href = "/login"
setIsAuthenticated(false);
window.location.href = "/login";
}
})
}, [])
});
}, []);
// Grabs profile user data
useEffect(() => {
onValue(ref(database, "/users/" + params.stub), (snapshot) => {
setProfileData(snapshot.val());
var interests = snapshot.val().interests || null;
interests = interests.split(",");
var interestArray = []
var i = 0
for (var interest in interests) {
if (i < 4)
interestArray.push(<Interest interest={interests[interest]}/>)
i++;
}
setUserInterestArray(interestArray)
var rooms = snapshot.val().rooms;
var roomArray = []
for (var room in rooms) {
roomArray.push(<ProfileRoom room={rooms[room]}/>)
}
setUserRoomsArray(roomArray);
});
},[]);
onValue(ref(database, "/users/" + params.stub), (snapshot) => {
setProfileData(snapshot.val());
var interests = snapshot.val().interests || null;
interests = interests.split(",");
var interestArray = [];
var i = 0;
for (var interest in interests) {
if (i < 4)
interestArray.push(<Interest interest={interests[interest]} />);
i++;
}
setUserInterestArray(interestArray);
var rooms = snapshot.val().rooms;
var roomArray = [];
for (var room in rooms) {
roomArray.push(<ProfileRoom room={rooms[room]} />);
}
setUserRoomsArray(roomArray);
});
}, []);
function save({data}) {
function save({ data }) {
if (data.pfp[0]) {
// image stuff
uploadBytes(sRef(storage, `users/${user.uid}/pfp`), data.pfp[0]).then(() => {
getDownloadURL(sRef(storage, `users/${user.uid}/pfp`)).then((url) => {
data.pfp = url
for (var key in data) {
if (data[key] == "") {
data[key] = profileData[key]
uploadBytes(sRef(storage, `users/${user.uid}/pfp`), data.pfp[0]).then(
() => {
getDownloadURL(sRef(storage, `users/${user.uid}/pfp`)).then((url) => {
data.pfp = url;
for (var key in data) {
if (data[key] == "") {
data[key] = profileData[key];
}
}
}
setEdit(false)
update(ref(database, `users/${user.uid}`), data)
})
})
setIsEditing(false);
update(ref(database, `users/${user.uid}`), data);
});
}
);
} else {
for (var key in data) {
if (data[key] == "") {
data[key] = profileData[key]
data[key] = profileData[key];
}
}
data.pfp = profileData.pfp
setEdit(false)
update(ref(database, `users/${user.uid}`), data)
data.pfp = profileData.pfp;
setIsEditing(false);
update(ref(database, `users/${user.uid}`), data);
}
}
@@ -112,66 +113,130 @@ function Home({ params }) {
{/* Left Side of Page */}
<div className="h-dvh overflow-hidden">
{/* Header */}
<Header user={user}/>
<Header user={user} />
{/* Main Page Section */}
<div className="grid grid-cols-3 mr-2 h-[calc(100%-110px)] pl-5 pr-5 pt-2">
<div className="cols-span-1 bg-white shadow-2xl rounded-xl pt-5">
{!isEditing && (
<div>
<img src={profileData.pfp} width="300px" className="relative mx-auto rounded-2xl overflow-hidden"/>
<img
src={profileData.pfp}
width="300px"
className="relative mx-auto rounded-2xl overflow-hidden"
/>
<div className="font-bold text-[30px]">
{profileData.firstName} {profileData.lastName}
{profileData.firstName} {profileData.lastName}
</div>
<div className="text-[20px]">@{profileData.username}</div>
<div className="pt-5">{profileData.bio}</div>
<div className="grid grid-cols-3 p-3">
{userInterestArray}
{userInterestArray}
</div>
<div className="grid grid-cols-1 auto-cols-min justify-items-center">
{isOwner && ( <a onClick={() => {setEdit(true)}} className="w-[120px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center"> Edit Profile </a> )}
{!isOwner && ( <a className="w-[120px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center"> Add Friend </a> )}
{isOwner && (
<a
onClick={() => {
setIsEditing(true);
}}
className="w-[120px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center"
>
{" "}
Edit Profile{" "}
</a>
)}
{!isOwner && (
<a className="w-[120px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center">
{" "}
Add Friend{" "}
</a>
)}
</div>
</div>
)}
{isEditing && (
<div>
<Form onSubmit={save} encType={'application/json'} control={control}>
<div className="grid grid-cols-2">
<div>
<img src={profileData.pfp} width="150px" className="relative mx-auto rounded-2xl overflow-hidden"/>
Current Profile Picture
</div>
<div className="flex content-center">
<input type="file" {...register("pfp")} className="w-[80%]" accept=".jpg,.png,.jpeg"/>
</div>
<Form
onSubmit={save}
encType={"application/json"}
control={control}
>
<div className="grid grid-cols-2">
<div>
<img
src={profileData.pfp}
width="150px"
className="relative mx-auto rounded-2xl overflow-hidden"
/>
Current Profile Picture
</div>
<div className="grid grid-cols-2 pl-2 w-[90%]">
<div className="pt-5">
<div className="font-bold">First Name</div>
<input className="w-[80%] border-2 border-gray-300 p-2 rounded-lg" type="text" {...register("firstName")} placeholder={profileData.firstName}/>
</div>
<div className="pt-5">
<div className="font-bold">Last Name</div>
<input className="w-[80%] border-2 border-gray-300 p-2 rounded-lg" type="text" {...register("lastName")} placeholder={profileData.lastName}/>
</div>
<div className="pt-5">
<div className="font-bold">Username</div>
<input className="w-[80%] border-2 border-gray-300 p-2 rounded-lg" type="text" {...register("username")} placeholder={profileData.username}/>
</div>
<div className="pt-5">
<div className="font-bold">Interests (Comma Seperated)</div>
<input className="w-[80%] border-2 border-gray-300 p-2 rounded-lg" type="text" {...register("interests")} placeholder={profileData.interests}/>
</div>
<div className="pt-5 col-span-2">
<div className="font-bold">Bio</div>
<textarea className="w-[92%] border-2 border-gray-300 p-2 rounded-lg" {...register("bio")} type="text" placeholder={profileData.bio}/>
</div>
<div className="justify-items-center pt-5 col-span-2">
<button type="submit" className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center"> Save Changes </button>
</div>
<div className="flex content-center">
<input
type="file"
{...register("pfp")}
className="w-[80%]"
accept=".jpg,.png,.jpeg"
/>
</div>
</Form>
</div>
<div className="grid grid-cols-2 pl-2 w-[90%]">
<div className="pt-5">
<div className="font-bold">First Name</div>
<input
className="w-[80%] border-2 border-gray-300 p-2 rounded-lg"
type="text"
{...register("firstName")}
placeholder={profileData.firstName}
/>
</div>
<div className="pt-5">
<div className="font-bold">Last Name</div>
<input
className="w-[80%] border-2 border-gray-300 p-2 rounded-lg"
type="text"
{...register("lastName")}
placeholder={profileData.lastName}
/>
</div>
<div className="pt-5">
<div className="font-bold">Username</div>
<input
className="w-[80%] border-2 border-gray-300 p-2 rounded-lg"
type="text"
{...register("username")}
placeholder={profileData.username}
/>
</div>
<div className="pt-5">
<div className="font-bold">
Interests (Comma Seperated)
</div>
<input
className="w-[80%] border-2 border-gray-300 p-2 rounded-lg"
type="text"
{...register("interests")}
placeholder={profileData.interests}
/>
</div>
<div className="pt-5 col-span-2">
<div className="font-bold">Bio</div>
<textarea
className="w-[92%] border-2 border-gray-300 p-2 rounded-lg"
{...register("bio")}
type="text"
placeholder={profileData.bio}
/>
</div>
<div className="justify-items-center pt-5 col-span-2">
<button
type="submit"
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full text-center"
>
{" "}
Save Changes{" "}
</button>
</div>
</div>
</Form>
</div>
)}
</div>
@@ -184,8 +249,8 @@ function Home({ params }) {
</div>
</div>
)}
</div>
</div>
);
}
export default Home;
export default Home;
+3 -39
View File
@@ -1,4 +1,4 @@
import {Geo} from './map/geo.js';
import { Geo } from "./map/geo.js";
// Colors for Messages
const userColors = [
@@ -122,41 +122,5 @@ export function ChatRoomSidebar({ roomObj, click }) {
);
}
// Interests for Profile
export function Interest({ interest }) {
return (
<div>
<div className="rounded-lg m-2 p-2 shadow-xl">{interest}</div>
</div>
);
}
// Display of Rooms on user profile
export function ProfileRoom({ room }) {
return (
<div className="rounded-lg p-2 shadow-xl bg-white h-[250px] w-[325px]">
<div className="relative z-1 h-[235px] opacity-50">
<Geo
loc={{ latitude: room.latitude, longitude: room.longitude }}
zoom={12}
locMarker={false}
/>
</div>
<div className="relative z-2 top-[-235px] text-left p-2">
<div className="text-2xl font-bold">{room.name}</div>
<div>{room.description}</div>
<div>
Created on {new Date(room.timestamp).toLocaleString(dateOptions)}
</div>
<a
href={
"/app?room=" + room.path + "/" + room.name + "-" + room.timestamp
}
className="absolute z-2 top-[190px] w-[108px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full flex items-center"
>
Open Room
</a>
</div>
</div>
);
}
// This will be removed once dateOptions is no longer used in this file
export { dateOptions };
+146 -137
View File
@@ -1,144 +1,153 @@
import { auth, database } from "../../../firebase-config";
import { ref, set, remove } from "firebase/database";
import {signOut} from "firebase/auth";
import { Popover } from '@headlessui/react'
import { signOut } from "firebase/auth";
import { Popover } from "@headlessui/react";
function logout() {
signOut(auth)
}
function logout() {
signOut(auth);
}
// Closes chat room
function closeChatRoom(roomObj, setChatRoomObj, setMainTab, user) {
var path = roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp;
var payload = {
body: "left",
user: user.username,
isSystem: true,
timestamp: new Date().getTime(),
uid: user.uid
};
set(
ref(
database,
`/rooms/${path}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
remove(ref(database, `/rooms/${path}/users/online/${user.uid}`));
setChatRoomObj(null);
setMainTab("home");
}
// Closes chat room
function closeChatRoom(roomObj, setChatRoomObj, setMainTab, user) {
var path = roomObj.path + "/" + roomObj.name + "-" + roomObj.timestamp;
var payload = {
body: "left",
user: user.username,
isSystem: true,
timestamp: new Date().getTime(),
uid: user.uid,
};
set(
ref(
database,
`/rooms/${path}/chats/${new Date().getTime()}-${user.username}`
),
payload
);
remove(ref(database, `/rooms/${path}/users/online/${user.uid}`));
setChatRoomObj(null);
setMainTab("home");
}
// Adds room to myRooms
function addToMyRooms(chatRoomObj, setIsMyRoom, user) {
set(
ref(
database,
`/users/${user.uid}/rooms/${chatRoomObj.name}-${chatRoomObj.timestamp}`
),
{
name: chatRoomObj.name,
path: chatRoomObj.path,
timestamp: chatRoomObj.timestamp,
description: chatRoomObj.description,
longitude: chatRoomObj.longitude,
latitude: chatRoomObj.latitude,
}
);
var path =
chatRoomObj.path +
"/" +
chatRoomObj.name +
"-" +
chatRoomObj.timestamp;
set(ref(database, `/rooms/${path}/users/all/${user.uid}`), user);
setIsMyRoom(true);
}
// Adds room to myRooms
function addToMyRooms(chatRoomObj, setIsMyRoom, user) {
set(
ref(
database,
`/users/${user.uid}/rooms/${chatRoomObj.name}-${chatRoomObj.timestamp}`
),
{
name: chatRoomObj.name,
path: chatRoomObj.path,
timestamp: chatRoomObj.timestamp,
description: chatRoomObj.description,
longitude: chatRoomObj.longitude,
latitude: chatRoomObj.latitude,
}
);
var path =
chatRoomObj.path + "/" + chatRoomObj.name + "-" + chatRoomObj.timestamp;
set(ref(database, `/rooms/${path}/users/all/${user.uid}`), user);
setIsMyRoom(true);
}
// Deletes saved room from myRooms
function removeFromMyRooms(chatRoomObj, setIsMyRoom, user) {
var path =
chatRoomObj.path +
"/" +
chatRoomObj.name +
"-" +
chatRoomObj.timestamp;
remove(
ref(
database,
`/users/${user.uid}/rooms/${chatRoomObj.name}-${chatRoomObj.timestamp}`
)
);
remove(ref(database, `/rooms/${path}/users/all/${user.uid}`));
setIsMyRoom(false);
}
export function Header({mainTab, isMyRoom, chatRoomObj, setChatRoomObj, setMainTab, setIsMyRoom, user}) {
return (
<div className="flex m-2 rounded-lg h-[63px] bg-white shadow-2xl p-1">
<div className="flex shrink h-[60px]">
<a href="/app">
<img
src="/logos/logo_transparent_inverse.png"
className="h-[60px]"
/>
</a>
</div>
<div className="grow grid grid-rows-1 grid-flow-col auto-cols-max justify-end gap-2 h-[60px] p-2">
{mainTab == "chat" && isMyRoom == false && (
<a
onClick={() => {
addToMyRooms(chatRoomObj, setIsMyRoom, user);
}}
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
>
Add to &quot;My Rooms&quot;
</a>
)}
{mainTab == "chat" && isMyRoom == true && (
<a
onClick={() => {
removeFromMyRooms(chatRoomObj, setIsMyRoom, user);
}}
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
>
Remove from &quot;My Rooms&quot;
</a>
)}
{mainTab == "chat" && (
<a
onClick={() => {
closeChatRoom(chatRoomObj, setChatRoomObj, setMainTab, user);
}}
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
>
Close Chat
</a>
)}
<Popover className="relative">
<Popover.Button as="div">
<div className="mr-5 h-[44px] p-[2px] pr-[15px] cursor-pointer bg-cyan-500 text-white font-bold rounded-full shadow-2xl flex">
<div className="flex items-center pl-1">
{user.firstName}
</div>
<div className="ml-3 rounded-lg">
<img src={user.pfp} width="40px" className="relative mx-auto rounded-xl overflow-hidden"/>
</div>
</div>
</Popover.Button>
<Popover.Panel className="absolute z-10 bg-white mt-[4px] rounded-xl ml-3 shadow-2xl">
<div className="grid grid-cols-1">
<a className="rounded-xl p-4 hover:bg-[#C0C0C0]" href={"/user/"+user.uid}>View Profile</a>
<a className="rounded-xl p-4 hover:bg-[#C0C0C0]" onClick={logout} href="/">Sign Out</a>
</div>
<img src="/solutions.jpg" alt="" />
</Popover.Panel>
</Popover>
</div>
</div>
// Deletes saved room from myRooms
function removeFromMyRooms(chatRoomObj, setIsMyRoom, user) {
var path =
chatRoomObj.path + "/" + chatRoomObj.name + "-" + chatRoomObj.timestamp;
remove(
ref(
database,
`/users/${user.uid}/rooms/${chatRoomObj.name}-${chatRoomObj.timestamp}`
)
}
);
remove(ref(database, `/rooms/${path}/users/all/${user.uid}`));
setIsMyRoom(false);
}
export function Header({
mainTab,
isMyRoom,
chatRoomObj,
setChatRoomObj,
setMainTab,
setIsMyRoom,
user,
}) {
return (
<div className="flex m-2 rounded-lg h-[63px] bg-white shadow-2xl p-1">
<div className="flex shrink h-[60px]">
<a href="/app">
<img src="/logos/logo_transparent_inverse.png" className="h-[60px]" />
</a>
</div>
<div className="grow grid grid-rows-1 grid-flow-col auto-cols-max justify-end gap-2 h-[60px] p-2">
{mainTab == "chat" && isMyRoom == false && (
<a
onClick={() => {
addToMyRooms(chatRoomObj, setIsMyRoom, user);
}}
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
>
Add to &quot;My Rooms&quot;
</a>
)}
{mainTab == "chat" && isMyRoom == true && (
<a
onClick={() => {
removeFromMyRooms(chatRoomObj, setIsMyRoom, user);
}}
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
>
Remove from &quot;My Rooms&quot;
</a>
)}
{mainTab == "chat" && (
<a
onClick={() => {
closeChatRoom(chatRoomObj, setChatRoomObj, setMainTab, user);
}}
className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center"
>
Close Chat
</a>
)}
<Popover className="relative">
<Popover.Button as="div">
<div className="mr-5 h-[44px] p-[2px] pr-[15px] cursor-pointer bg-cyan-500 text-white font-bold rounded-full shadow-2xl flex">
<div className="flex items-center pl-1">{user.firstName}</div>
<div className="ml-3 rounded-lg">
<img
src={user.pfp}
width="40px"
className="relative mx-auto rounded-xl overflow-hidden"
/>
</div>
</div>
</Popover.Button>
<Popover.Panel className="absolute z-10 bg-white mt-[4px] rounded-xl ml-3 shadow-2xl">
<div className="grid grid-cols-1">
<a
className="rounded-xl p-4 hover:bg-[#C0C0C0]"
href={"/user/" + user.uid}
>
View Profile
</a>
<a
className="rounded-xl p-4 hover:bg-[#C0C0C0]"
onClick={logout}
href="/"
>
Sign Out
</a>
</div>
<img src="/solutions.jpg" alt="" />
</Popover.Panel>
</Popover>
</div>
</div>
);
}
@@ -1,31 +1,31 @@
import {Geo} from "../map/geo"
import { Geo } from "../map/geo";
// Module for Welcome Message on main tab landing page
function WelcomeMessage({user}) {
return (
<div className="bg-white rounded-lg m-2 mt-4 text-left p-2 pl-5">
<div>
Welcome, {user.firstName} {user.lastName} ({user.username})
</div>
<div>Lets see what&apos;s happening in your area.</div>
function WelcomeMessage({ user }) {
return (
<div className="bg-white rounded-lg m-2 mt-4 text-left p-2 pl-5">
<div>
Welcome, {user.firstName} {user.lastName} ({user.username})
</div>
);
}
<div>Lets see what&apos;s happening in your area.</div>
</div>
);
}
// Primary App Landing Page
export function MainTabHome({ loc, markers, user }) {
return (
<>
<WelcomeMessage user={user}/>
<div className="h-[calc(100%-110px)] m-5 rounded-lg">
<Geo
loc={loc}
zoom={14}
movable={true}
locMarker={true}
markers={markers}
/>
</div>
</>
);
}
return (
<>
<WelcomeMessage user={user} />
<div className="h-[calc(100%-110px)] m-5 rounded-lg">
<Geo
loc={loc}
zoom={14}
movable={true}
locMarker={true}
markers={markers}
/>
</div>
</>
);
}
+20 -22
View File
@@ -1,27 +1,25 @@
import { Map, Marker, ZoomControl } from "pigeon-maps";
// Map module for main page and chat room sidebar (and eventually user profile)
// Constructs Map and Markers
export function Geo({ loc, zoom, locMarker, markers }) {
if (loc) {
return (
<Map center={[loc.latitude, loc.longitude]} defaultZoom={zoom}>
{markers && markers}
{locMarker && (
<Marker
width={30}
anchor={[loc.latitude, loc.longitude]}
color="red"
/>
)}
{zoom && <ZoomControl />}
</Map>
);
} else {
return (
<Map className="rounded-lg" defaultCenter={[0, 0]} defaultZoom={zoom} />
);
}
}
if (loc) {
return (
<Map center={[loc.latitude, loc.longitude]} defaultZoom={zoom}>
{markers && markers}
{locMarker && (
<Marker
width={30}
anchor={[loc.latitude, loc.longitude]}
color="red"
/>
)}
{zoom && <ZoomControl />}
</Map>
);
} else {
return (
<Map className="rounded-lg" defaultCenter={[0, 0]} defaultZoom={zoom} />
);
}
}
@@ -0,0 +1,9 @@
// Interests for Profile
// Making this its own file since we could do a bit more with this in the future
export function Interest({ interest }) {
return (
<div>
<div className="rounded-lg m-2 p-2 shadow-xl">{interest}</div>
</div>
);
}
@@ -0,0 +1,32 @@
import { Geo } from "../map/geo";
import { dateOptions } from "../datatypes";
// Display of Rooms on user profile
export function ProfileRoom({ room }) {
return (
<div className="rounded-lg p-2 shadow-xl bg-white h-[250px] w-[325px]">
<div className="relative z-1 h-[235px] opacity-50">
<Geo
loc={{ latitude: room.latitude, longitude: room.longitude }}
zoom={12}
locMarker={false}
/>
</div>
<div className="relative z-2 top-[-235px] text-left p-2">
<div className="text-2xl font-bold">{room.name}</div>
<div>{room.description}</div>
<div>
Created on {new Date(room.timestamp).toLocaleString(dateOptions)}
</div>
<a
href={
"/app?room=" + room.path + "/" + room.name + "-" + room.timestamp
}
className="absolute z-2 top-[190px] w-[108px] p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full flex items-center"
>
Open Room
</a>
</div>
</div>
);
}
@@ -1,5 +1,6 @@
import { Geo } from "../map/geo";
// Sidebar when in a Chatrooms
export function Chat_Sidebar({
chatRoomObj,
chatroomOnline,
+121 -114
View File
@@ -2,125 +2,132 @@ import { Form, useForm } from "react-hook-form";
import { database } from "../../../../firebase-config";
import { ref, set } from "firebase/database";
// Sidebar on Home Page, with various functionality (create, nearby, my rooms)
// CreateRoom Module for Sidebar Create Tab
function CreateRoom({ loc }) {
var { register, control, reset, handleSubmit } = useForm();
var { register, control, reset, handleSubmit } = useForm();
function createRoom(data) {
reset();
var path =
String(loc.latitude.toFixed(2)).replace(".", "") +
"/" +
String(loc.longitude.toFixed(2)).replace(".", "");
var timestamp = new Date().getTime();
var payload = {
name: data.name,
description: data.description,
timestamp: timestamp,
latitude: loc.latitude,
longitude: loc.longitude,
path: path,
};
set(ref(database, `/rooms/${path}/${data.name}-${timestamp}`), payload);
}
return (
<div className="overflow-y-auto h-[90%]">
<Form control={control} onSubmit={handleSubmit(createRoom)}>
<input
{...register("name")}
placeholder="Room Name"
className="mt-2"
/>
<input
{...register("description")}
placeholder="Room Description"
className="mt-2"
/>
<br />
<div className="mt-3 mb-2">
Creating room near ({loc.latitude.toFixed(2)},{" "}
{loc.longitude.toFixed(2)})
</div>
<button className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5">
Create
</button>
</Form>
</div>
);
function createRoom(data) {
reset();
var path =
String(loc.latitude.toFixed(2)).replace(".", "") +
"/" +
String(loc.longitude.toFixed(2)).replace(".", "");
var timestamp = new Date().getTime();
var payload = {
name: data.name,
description: data.description,
timestamp: timestamp,
latitude: loc.latitude,
longitude: loc.longitude,
path: path,
};
set(ref(database, `/rooms/${path}/${data.name}-${timestamp}`), payload);
}
export function Home_Sidebar({tab, nearby, loadingNearby, setTab, isRoomLoading, myRooms, loadingLoc, location}) {
return (
<div className="h-dvh">
<div className="bg-white shadow-2xl rounded-lg m-2 h-[98%]">
<div className="p-2">
<div className="p-1 rounded-lg grid grid-cols-3 bg-white">
<div
className={
tab == "nearby"
? "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0] bg-[#D3D3D3]"
: "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0]"
}
onClick={() => {
setTab("nearby");
}}
>
Nearby
</div>
<div
className={
tab == "rooms"
? "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0] bg-[#D3D3D3]"
: "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0]"
}
onClick={() => {
setTab("rooms");
}}
>
My Rooms
</div>
<div
className={
tab == "create"
? "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0] bg-[#D3D3D3]"
: "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0]"
}
onClick={() => {
setTab("create");
}}
>
Create
</div>
</div>
return (
<div className="overflow-y-auto h-[90%]">
<Form control={control} onSubmit={handleSubmit(createRoom)}>
<input {...register("name")} placeholder="Room Name" className="mt-2" />
<input
{...register("description")}
placeholder="Room Description"
className="mt-2"
/>
<br />
<div className="mt-3 mb-2">
Creating room near ({loc.latitude.toFixed(2)},{" "}
{loc.longitude.toFixed(2)})
</div>
<button className="p-2 cursor-pointer bg-cyan-500 text-white font-bold rounded-full mr-5">
Create
</button>
</Form>
</div>
);
}
export function Home_Sidebar({
tab,
nearby,
loadingNearby,
setTab,
isRoomLoading,
myRooms,
loadingLoc,
location,
}) {
return (
<div className="h-dvh">
<div className="bg-white shadow-2xl rounded-lg m-2 h-[98%]">
<div className="p-2">
<div className="p-1 rounded-lg grid grid-cols-3 bg-white">
<div
className={
tab == "nearby"
? "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0] bg-[#D3D3D3]"
: "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0]"
}
onClick={() => {
setTab("nearby");
}}
>
Nearby
</div>
<div
className={
tab == "rooms"
? "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0] bg-[#D3D3D3]"
: "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0]"
}
onClick={() => {
setTab("rooms");
}}
>
My Rooms
</div>
<div
className={
tab == "create"
? "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0] bg-[#D3D3D3]"
: "select-none p-1 cursor-pointer rounded-lg hover:bg-[#C0C0C0]"
}
onClick={() => {
setTab("create");
}}
>
Create
</div>
{tab == "nearby" && (
<div className="overflow-y-auto h-[90%]">
<div>
{!nearby && !loadingNearby && (
<div>
No Nearby Rooms
<br />
Create One?
</div>
)}
{loadingNearby && <div>Loading...</div>}
{nearby}
</div>
</div>
)}
{tab == "rooms" && (
<div className="overflow-y-auto h-[90%]">
<div>
{isRoomLoading && <div>Loading</div>}
{!myRooms && !isRoomLoading && <div>No User Saved Rooms</div>}
{myRooms}
</div>
</div>
)}
{tab == "create" && !loadingLoc && <CreateRoom loc={location} />}
{tab == "create" && loadingLoc && <div>Loading...</div>}
</div>
</div>
)
}
{tab == "nearby" && (
<div className="overflow-y-auto h-[90%]">
<div>
{!nearby && !loadingNearby && (
<div>
No Nearby Rooms
<br />
Create One?
</div>
)}
{loadingNearby && <div>Loading...</div>}
{nearby}
</div>
</div>
)}
{tab == "rooms" && (
<div className="overflow-y-auto h-[90%]">
<div>
{isRoomLoading && <div>Loading</div>}
{!myRooms && !isRoomLoading && <div>No User Saved Rooms</div>}
{myRooms}
</div>
</div>
)}
{tab == "create" && !loadingLoc && <CreateRoom loc={location} />}
{tab == "create" && loadingLoc && <div>Loading...</div>}
</div>
</div>
);
}
@@ -1,7 +1,7 @@
export function Profile_Sidebar() {
return (
<div className="h-dvh">
<div className=" bg-white m-2 h-[98%]">Profile</div>
</div>
)
}
return (
<div className="h-dvh">
<div className=" bg-white m-2 h-[98%]">Profile</div>
</div>
);
}