From eeb6b856e697259b16e2e7bf4fad675bf489d51f Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Sat, 24 Feb 2024 06:35:23 +0000 Subject: [PATCH 1/5] UI Changes, Prepare for Chatrooms --- frontend-next/src/app/api/signout/route.js | 2 +- frontend-next/src/app/app/layout.js | 7 -- frontend-next/src/app/app/page.js | 79 ++++++++++++++++++++-- frontend-next/src/app/app/shared.js | 18 ----- 4 files changed, 74 insertions(+), 32 deletions(-) delete mode 100644 frontend-next/src/app/app/shared.js diff --git a/frontend-next/src/app/api/signout/route.js b/frontend-next/src/app/api/signout/route.js index e33509a..e107f50 100644 --- a/frontend-next/src/app/api/signout/route.js +++ b/frontend-next/src/app/api/signout/route.js @@ -6,5 +6,5 @@ export async function GET(req) { cookies().delete('user') cookies().delete('session') cookies().delete('uid') - return NextResponse.json({}, { status: 200 }); + return NextResponse.redirect(new URL("/",req.url)) } \ No newline at end of file diff --git a/frontend-next/src/app/app/layout.js b/frontend-next/src/app/app/layout.js index 4b40e5e..18a5f84 100644 --- a/frontend-next/src/app/app/layout.js +++ b/frontend-next/src/app/app/layout.js @@ -1,6 +1,5 @@ import { Inter } from "next/font/google"; import "../globals.css"; -import { Header, Sidebar } from "./shared" const inter = Inter({ subsets: ["latin"] }); @@ -13,13 +12,7 @@ export default function RootLayout({ children }) { return ( -
-
-
{children} -
- -
); diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index d3ec30d..4a70000 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -1,6 +1,66 @@ "use client" import { useState, useEffect } from 'react' -import {Map, Marker} from "pigeon-maps" +import {Map, Marker, ZoomControl} from "pigeon-maps" + +function Header() { + return ( +
+ +
+ ) +} + +function Sidebar() { + var nearbyTab = false + return ( +
+
+
+
+
{nearbyTab = true}}>Nearby
+
My Rooms
+
Create
+
+
+ {nearbyTab &&
+ + + + + + + + + + + + + + + + + +
} +
+
+ + ) +} + +function ChatRoomSidebar({roomName}) { + + return ( +
+
+ Icons +
+
+
{roomName}
+
x Members
+
+
+ ) +} function WelcomeMessage() { //TODO: REALLY GROSS WAY TO GET COOKIES, NEED NEW WAY TO STORE USER DATA WITHOUT API CALLS. THIS PAGE HAS TO BE CLIENT SIDE DUE TO MAPS / GEOLOCATION @@ -20,7 +80,7 @@ function WelcomeMessage() { return (
- Welcome, {data.firstName} {data.lastName} + Welcome, {data.firstName} {data.lastName} ({data.username})
Lets see what's happening in your area. @@ -47,6 +107,7 @@ function Geo() { return ( + ) } else { @@ -59,11 +120,17 @@ function Geo() { function Home() { return ( -
- -
- +
+
+
+
+ +
+ +
+
+
) } diff --git a/frontend-next/src/app/app/shared.js b/frontend-next/src/app/app/shared.js deleted file mode 100644 index d9021ae..0000000 --- a/frontend-next/src/app/app/shared.js +++ /dev/null @@ -1,18 +0,0 @@ -export function Header() { - return ( -
- -
- ) -} - -export function Sidebar() { - return ( -
-
- Sidebar -
-
- - ) - } From afd5dbaa9fcbbb025e8563e186abab387a1cd004 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Sun, 25 Feb 2024 03:19:12 +0000 Subject: [PATCH 2/5] Restructure App, Created Chat UI, Ready for Firebase Integration / Backend --- frontend-next/src/app/app/page.js | 124 ++++++++++++++++-------------- 1 file changed, 67 insertions(+), 57 deletions(-) diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index 4a70000..bdec581 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -1,54 +1,9 @@ "use client" import { useState, useEffect } from 'react' import {Map, Marker, ZoomControl} from "pigeon-maps" - -function Header() { - return ( -
- -
- ) -} - -function Sidebar() { - var nearbyTab = false - return ( -
-
-
-
-
{nearbyTab = true}}>Nearby
-
My Rooms
-
Create
-
-
- {nearbyTab &&
- - - - - - - - - - - - - - - - - -
} -
-
- - ) -} +import { Form, useForm } from "react-hook-form"; function ChatRoomSidebar({roomName}) { - return (
@@ -118,23 +73,78 @@ function Geo() { } -function Home() { +function MainTabHome() { return ( -
-
-
-
- -
- -
-
+ <> + +
+ +
+ + ) +} + +function ChatRoom({chatRoom}) { + var { register, control, setError, formState: { errors, isSubmitting, isSubmitted } } = useForm() + return ( +
+
+ Chats Go Here +
+
+
+ + +
-
) } +function Home() { + var [tab, setTab] = useState("nearby") + var [mainTab, setMainTab] = useState("chat") + var [chatRoom, setChatRoom] = useState("NA") + return ( +
+
+ +
+ {mainTab == "home" && } + {mainTab == "chat" && } +
+
+
+
+
+
+
{setTab("nearby")}}>Nearby
+
{setTab("rooms")}}>My Rooms
+
{setTab("create")}}>Create
+
+
+ {tab == "nearby" &&
+ Nearby +
} + {tab == "rooms" &&
+ My Rooms +
} + {tab == "create" &&
+ Create Room +
} +
+
+
+ ) +} export default Home; \ No newline at end of file From 7cd1e9b5da8c83a34fa067c3efabd8f0eaf60713 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Sun, 25 Feb 2024 08:38:40 +0000 Subject: [PATCH 3/5] WIP: Message Fetch Works --- frontend-next/src/app/api/firebase-config.js | 14 ++-- frontend-next/src/app/app/page.js | 76 ++++++++++++++++++-- 2 files changed, 76 insertions(+), 14 deletions(-) diff --git a/frontend-next/src/app/api/firebase-config.js b/frontend-next/src/app/api/firebase-config.js index 5d82756..0d51435 100644 --- a/frontend-next/src/app/api/firebase-config.js +++ b/frontend-next/src/app/api/firebase-config.js @@ -2,13 +2,13 @@ import { initializeApp, getApps, getApp } from "firebase/app"; import { getAuth } from "firebase/auth"; var config = { - apiKey: process.env.FIREBASE_CONFIG_API_KEY, - authDomain: process.env.FIREBASE_CONFIG_AUTH_DOMAIN, - projectId: process.env.FIREBASE_CONFIG_PROJECT_ID, - storageBucket: process.env.FIREBASE_CONFIG_STORAGE_BUCKET, - messagingSenderId: process.env.FIREBASE_CONFIG_MESSAGING_SENDER_ID, - appId: process.env.FIREBASE_CONFIG_APPID, - databaseURL: process.env.FIREBASE_CONFIG_DATABASE_URL, + apiKey: "AIzaSyDbDPjQGt-lIjNPeTG-Q5AECM1m0vtOr2c", + authDomain: "chatmaps-3e7fa.firebaseapp.com", + projectId: "chatmaps-3e7fa", + storageBucket: "chatmaps-3e7fa.appspot.com", + messagingSenderId: "771010649524", + appId: "1:771010649524:web:b6e66d3457820c817b26e1", + databaseURL: "https://chatmaps-3e7fa-default-rtdb.firebaseio.com/", } var app = getApps().length > 0 ? getApp() : initializeApp(config); diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index bdec581..5a4fda1 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -2,15 +2,19 @@ import { useState, useEffect } from 'react' import {Map, Marker, ZoomControl} from "pigeon-maps" import { Form, useForm } from "react-hook-form"; +import { app } from "../api/firebase-config"; +import { getDatabase, ref, onValue, get } from "firebase/database"; +var database = getDatabase(app) -function ChatRoomSidebar({roomName}) { + +function ChatRoomSidebar({roomObj}) { return (
Icons
-
{roomName}
+
{roomObj.name}
x Members
@@ -84,16 +88,40 @@ function MainTabHome() { ) } -function ChatRoom({chatRoom}) { +function Chat({chatObj}) { + return ( +
+ {chatObj.user}: {chatObj.body} +
+ ) +} + +function MainTabChatRoom({chatRoom}) { var { register, control, setError, formState: { errors, isSubmitting, isSubmitted } } = useForm() + const [chats, setData] = useState(null) + const [isLoading, setLoading] = useState(true) + var unsubscribeUpdater + useEffect(() => { + unsubscribeUpdater = onValue(ref(database, "/rooms/1"), (snapshot) => { + var chatsarr = [] + var messages = snapshot.val() + for (var message in messages) { + chatsarr.push() + } + setData(chatsarr) + setLoading(false) + }) + }, []) + if (isLoading) return
Loading
+ if (!chats) return
No Chats
return (
-
- Chats Go Here +
+ {chats}
- +
@@ -101,6 +129,37 @@ function ChatRoom({chatRoom}) { ) } +function MyRooms() { + const [myrooms, setData] = useState(null) + const [isLoading, setLoading] = useState(true) + var unsubscribeUpdater + useEffect(() => { + fetch('/api/user').then((res) => { + res.json().then((user) => { + console.log(user.uid) + get(ref(database,`/users/${user.uid}/rooms`), (snapshot) => { + var json = snapshot.val() + console.log(json) + var roomsArr = [] + for (var room in json) { + console.log(room,json[room]) + roomsArr.push() + } + setData(roomsArr) + setLoading(false) + }) + }) + }) + }, []) + if (isLoading) return
Loading
+ if (!myrooms) return
No Data
+ return ( +
+ {myrooms} +
+ ) +} + function Home() { var [tab, setTab] = useState("nearby") var [mainTab, setMainTab] = useState("chat") @@ -120,7 +179,7 @@ function Home() {
{mainTab == "home" && } - {mainTab == "chat" && } + {mainTab == "chat" && }
@@ -137,6 +196,9 @@ function Home() {
} {tab == "rooms" &&
My Rooms +
+ +
} {tab == "create" &&
Create Room From a7eb9b942b51330ace3c5d506173926a3d087278 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Sun, 25 Feb 2024 23:46:41 +0000 Subject: [PATCH 4/5] Minimal Functional Chatrooms --- frontend-next/src/app/app/page.js | 132 +++++++++++++++++------------- 1 file changed, 76 insertions(+), 56 deletions(-) diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index 5a4fda1..e65d286 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -1,26 +1,45 @@ "use client" -import { useState, useEffect } from 'react' +import { useState, useEffect, createContext, useContext } from 'react' import {Map, Marker, ZoomControl} from "pigeon-maps" import { Form, useForm } from "react-hook-form"; import { app } from "../api/firebase-config"; -import { getDatabase, ref, onValue, get } from "firebase/database"; +import { getDatabase, ref, onValue, get, set} from "firebase/database"; var database = getDatabase(app) - -function ChatRoomSidebar({roomObj}) { +// Data types +function Chat({chatObj}) { + let dateOptions = { + weekday: 'long', + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }; return ( -
-
- Icons +
+
+ {chatObj.user}: {chatObj.body}
-
-
{roomObj.name}
-
x Members
+
+ {new Date(chatObj.timestamp).toLocaleString(dateOptions)}
) } +function ChatRoomSidebar({roomObj, click}) { +return ( +
+
+
{roomObj.name}
+
x Members
+
+
+) +} + + function WelcomeMessage() { //TODO: REALLY GROSS WAY TO GET COOKIES, NEED NEW WAY TO STORE USER DATA WITHOUT API CALLS. THIS PAGE HAS TO BE CLIENT SIDE DUE TO MAPS / GEOLOCATION const [data, setData] = useState(null) @@ -77,6 +96,9 @@ function Geo() { } + + +// Main Tabs function MainTabHome() { return ( <> @@ -88,21 +110,19 @@ function MainTabHome() { ) } -function Chat({chatObj}) { - return ( -
- {chatObj.user}: {chatObj.body} -
- ) -} - -function MainTabChatRoom({chatRoom}) { - var { register, control, setError, formState: { errors, isSubmitting, isSubmitted } } = useForm() +function MainTabChatRoom({room}) { + var { register, control, reset, handleSubmit} = useForm() const [chats, setData] = useState(null) const [isLoading, setLoading] = useState(true) + var user + fetch('/api/user') + .then((res) => res.json()) + .then((data) => { + user = data + }) var unsubscribeUpdater useEffect(() => { - unsubscribeUpdater = onValue(ref(database, "/rooms/1"), (snapshot) => { + unsubscribeUpdater = onValue(ref(database, `/rooms/${room}`), (snapshot) => { var chatsarr = [] var messages = snapshot.val() for (var message in messages) { @@ -112,6 +132,18 @@ function MainTabChatRoom({chatRoom}) { setLoading(false) }) }, []) + + function sendMessage(data) { + reset() + var payload = { + body: data.message, + user: user.username, + timestamp: new Date().getTime() + } + set(ref(database,`/rooms/${room}/${user.username}-${new Date().getTime()}`), payload) + } + + if (isLoading) return
Loading
if (!chats) return
No Chats
return ( @@ -120,8 +152,8 @@ function MainTabChatRoom({chatRoom}) { {chats}
-
- + +
@@ -129,45 +161,31 @@ function MainTabChatRoom({chatRoom}) { ) } -function MyRooms() { - const [myrooms, setData] = useState(null) - const [isLoading, setLoading] = useState(true) - var unsubscribeUpdater +function Home() { + var [tab, setTab] = useState("nearby") + var [mainTab, setMainTab] = useState("home") + var [chatRoom, setChatRoom] = useState("Dev") + + const [myrooms, setRoomData] = useState(null) + const [isRoomLoading, setRoomLoading] = useState(true) useEffect(() => { - fetch('/api/user').then((res) => { - res.json().then((user) => { - console.log(user.uid) - get(ref(database,`/users/${user.uid}/rooms`), (snapshot) => { - var json = snapshot.val() - console.log(json) - var roomsArr = [] - for (var room in json) { - console.log(room,json[room]) - roomsArr.push() - } - setData(roomsArr) - setLoading(false) - }) + fetch('/api/user').then((res) => res.json()) + .then((user) => { + get(ref(database, '/users/'+user.uid+'/rooms')).then((snapshot) => { + var rooms = snapshot.val() + var roomArr = [] + for (var room in rooms) { + roomArr.push( {setChatRoom(rooms[room].name);setMainTab("chat")}}/>) + } + setRoomData(roomArr) + setRoomLoading(false) }) }) }, []) - if (isLoading) return
Loading
- if (!myrooms) return
No Data
- return ( -
- {myrooms} -
- ) -} - -function Home() { - var [tab, setTab] = useState("nearby") - var [mainTab, setMainTab] = useState("chat") - var [chatRoom, setChatRoom] = useState("NA") return (
-
+
@@ -197,7 +215,9 @@ function Home() { {tab == "rooms" &&
My Rooms
- + {isRoomLoading &&
Loading
} + {!myrooms &&
No User Saved Rooms
} + {myrooms}
} {tab == "create" &&
From 60bdf3627483911f178d4f4e17674fb7c89c0ff0 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Mon, 26 Feb 2024 05:40:11 +0000 Subject: [PATCH 5/5] Chatrooms: Nearby Lookup Working --- frontend-next/src/app/app/page.js | 137 +++++++++++++++++++++--------- 1 file changed, 96 insertions(+), 41 deletions(-) diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index e65d286..ad74268 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -17,7 +17,7 @@ function Chat({chatObj}) { minute: '2-digit' }; return ( -
+
{chatObj.user}: {chatObj.body}
@@ -33,7 +33,7 @@ return (
{roomObj.name}
-
x Members
+
{roomObj.description}
) @@ -68,23 +68,11 @@ function WelcomeMessage() { } -function Geo() { - const [isLoading, setLoading] = useState(true) - const [data, setData] = useState(); - useEffect(() => { - if('geolocation' in navigator) { - // Retrieve latitude & longitude coordinates from `navigator.geolocation` Web API - navigator.geolocation.getCurrentPosition(({ coords }) => { - const { latitude, longitude } = coords; - setData(coords) - setLoading(false) - }) - } - }, []); - if (!isLoading) { +function Geo({loc}) { + if (loc) { return ( - - + + ) @@ -99,12 +87,12 @@ function Geo() { // Main Tabs -function MainTabHome() { +function MainTabHome({loc}) { return ( <>
- +
) @@ -114,21 +102,23 @@ function MainTabChatRoom({room}) { var { register, control, reset, handleSubmit} = useForm() const [chats, setData] = useState(null) const [isLoading, setLoading] = useState(true) + var user fetch('/api/user') .then((res) => res.json()) .then((data) => { user = data }) + var unsubscribeUpdater useEffect(() => { - unsubscribeUpdater = onValue(ref(database, `/rooms/${room}`), (snapshot) => { - var chatsarr = [] + unsubscribeUpdater = onValue(ref(database, `/rooms/${room}/chats`), (snapshot) => { + var chatsArr = [] var messages = snapshot.val() for (var message in messages) { - chatsarr.push() + chatsArr.push() } - setData(chatsarr) + setData(chatsArr.reverse()) setLoading(false) }) }, []) @@ -140,7 +130,7 @@ function MainTabChatRoom({room}) { user: user.username, timestamp: new Date().getTime() } - set(ref(database,`/rooms/${room}/${user.username}-${new Date().getTime()}`), payload) + set(ref(database,`/rooms/${room}/chats/${user.username}-${new Date().getTime()}`), payload) } @@ -148,25 +138,57 @@ function MainTabChatRoom({room}) { if (!chats) return
No Chats
return (
-
+
{chats}
-
- - + + +
) } +function CreateRoom({loc}) { + 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 ( +
+
+ +
+
+ Creating room near ({loc.latitude.toFixed(2)}, {loc.longitude.toFixed(2)}) +
+ +
+
+ ) +} + function Home() { var [tab, setTab] = useState("nearby") var [mainTab, setMainTab] = useState("home") var [chatRoom, setChatRoom] = useState("Dev") - const [myrooms, setRoomData] = useState(null) + const [myRooms, setRoomData] = useState(null) const [isRoomLoading, setRoomLoading] = useState(true) useEffect(() => { fetch('/api/user').then((res) => res.json()) @@ -175,7 +197,7 @@ function Home() { var rooms = snapshot.val() var roomArr = [] for (var room in rooms) { - roomArr.push( {setChatRoom(rooms[room].name);setMainTab("chat")}}/>) + roomArr.push( {setChatRoom(rooms[room].path+"/"+rooms[room].name+"-"+rooms[room].timestamp);setMainTab("chat")}}/>) } setRoomData(roomArr) setRoomLoading(false) @@ -183,6 +205,36 @@ function Home() { }) }, []) + + const [location, setLocation] = useState(null); + const [loadingLoc, setLoadingLoc] = useState(true) + const [nearby, setNearby] = useState(null); + const [loadingNearby, setLoadingNearby] = useState(true); + useEffect(() => { + if('geolocation' in navigator) { + // Retrieve latitude & longitude coordinates from `navigator.geolocation` Web API + navigator.geolocation.getCurrentPosition(({ coords }) => { + setLocation(coords) + setLoadingLoc(false) + var nearbyArr = [] + var path = String(coords.latitude.toFixed(2)).replace(".","")+"/"+String(coords.longitude.toFixed(2)).replace(".","") + get(ref(database, `/rooms/${path}`)).then((snapshot) => { + if (snapshot.exists()) { + var data = snapshot.val() + for (var room in data) { + nearbyArr.push( {setChatRoom(data[room].path+"/"+data[room].name+"-"+data[room].timestamp);setMainTab("chat")}}/>) + } + setLoadingNearby(false) + setNearby(nearbyArr) + } else { + setLoadingNearby(false) + } + }) + }) + } + }, []); + + return (
@@ -196,7 +248,8 @@ function Home() {
- {mainTab == "home" && } + {(mainTab == "home" && !loadingLoc) && } + {(mainTab == "home" && loadingLoc) && } {mainTab == "chat" && }
@@ -210,19 +263,21 @@ function Home() {
{tab == "nearby" &&
- Nearby -
} - {tab == "rooms" &&
- My Rooms
- {isRoomLoading &&
Loading
} - {!myrooms &&
No User Saved Rooms
} - {myrooms} + {(!nearby && !loadingNearby) &&
No Nearby Rooms
Create One?
} + {loadingNearby &&
Loading...
} + {nearby}
} - {tab == "create" &&
- Create Room + {tab == "rooms" &&
+
+ {isRoomLoading &&
Loading
} + {(!myRooms && !isRoomLoading) &&
No User Saved Rooms
} + {myRooms} +
} + {(tab == "create" && !loadingLoc) && } + {(tab == "create" && loadingLoc) &&
Loading...
}