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:
@@ -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
@@ -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;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
body {
|
||||
background-color: aliceblue;
|
||||
text-align: center;
|
||||
text-wrap:pretty;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
button {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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 "My Rooms"
|
||||
</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 "My Rooms"
|
||||
</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 "My Rooms"
|
||||
</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 "My Rooms"
|
||||
</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'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'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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user