From 965db39ad064ec04a79b3a564135c0a8cfa70942 Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Sun, 24 Mar 2024 05:25:07 +0000 Subject: [PATCH 1/6] Profiles IP, Page Created --- frontend-next/package-lock.json | 42 +++++++ frontend-next/package.json | 1 + frontend-next/src/app/app/page.js | 3 +- frontend-next/src/app/user/[stub]/layout.js | 19 +++ frontend-next/src/app/user/[stub]/page.js | 109 ++++++++++++++++++ frontend-next/src/components/app/datatypes.js | 34 ++++-- frontend-next/src/components/app/header.js | 47 +++++--- .../src/components/app/sidebar/chat.js | 2 +- 8 files changed, 228 insertions(+), 29 deletions(-) create mode 100644 frontend-next/src/app/user/[stub]/layout.js create mode 100644 frontend-next/src/app/user/[stub]/page.js diff --git a/frontend-next/package-lock.json b/frontend-next/package-lock.json index be1e38b..e515ae0 100644 --- a/frontend-next/package-lock.json +++ b/frontend-next/package-lock.json @@ -8,6 +8,7 @@ "name": "chatmaps", "version": "0.1.0", "dependencies": { + "@headlessui/react": "^1.7.18", "firebase": "^10.6.0", "next": "^14.1.0", "pigeon-maps": "^0.21.3", @@ -627,6 +628,22 @@ "node": ">=6" } }, + "node_modules/@headlessui/react": { + "version": "1.7.18", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.18.tgz", + "integrity": "sha512-4i5DOrzwN4qSgNsL4Si61VMkUcWbcSKueUV7sFhpHzQcSShdlHENE5+QBntMSRvHt8NyoFO2AGG8si9lq+w4zQ==", + "dependencies": { + "@tanstack/react-virtual": "^3.0.0-beta.60", + "client-only": "^0.0.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1014,6 +1031,31 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/react-virtual": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.2.0.tgz", + "integrity": "sha512-OEdMByf2hEfDa6XDbGlZN8qO6bTjlNKqjM3im9JG+u3mCL8jALy0T/67oDI001raUUPh1Bdmfn4ZvPOV5knpcg==", + "dependencies": { + "@tanstack/virtual-core": "3.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.2.0.tgz", + "integrity": "sha512-P5XgYoAw/vfW65byBbJQCw+cagdXDT/qH6wmABiLt4v4YBT2q2vqCOhihe+D1Nt325F/S/0Tkv6C5z0Lv+VBQQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", diff --git a/frontend-next/package.json b/frontend-next/package.json index 48282de..17528e8 100644 --- a/frontend-next/package.json +++ b/frontend-next/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "@headlessui/react": "^1.7.18", "firebase": "^10.6.0", "next": "^14.1.0", "pigeon-maps": "^0.21.3", diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index 9a6a1da..24ec274 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -69,7 +69,6 @@ function Home() { }) }, []) - // Grabs user data, saves to user, then lists the users saved rooms useEffect(() => { if (user) { @@ -278,7 +277,7 @@ function Home() { )} {mainTab == "chat" && ( - + )} {mainTab == "profile" && ( diff --git a/frontend-next/src/app/user/[stub]/layout.js b/frontend-next/src/app/user/[stub]/layout.js new file mode 100644 index 0000000..ba13310 --- /dev/null +++ b/frontend-next/src/app/user/[stub]/layout.js @@ -0,0 +1,19 @@ +import { Inter } from "next/font/google"; +import "../../globals.css"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata = { + title: "ChatMaps: Home", + description: "ChatMaps: Social Media for College Students", +}; + +export default function RootLayout({ children }) { + return ( + + + {children} + + + ); +} diff --git a/frontend-next/src/app/user/[stub]/page.js b/frontend-next/src/app/user/[stub]/page.js new file mode 100644 index 0000000..29c9b21 --- /dev/null +++ b/frontend-next/src/app/user/[stub]/page.js @@ -0,0 +1,109 @@ +"use client"; +// System Imports +import { useState, useEffect } from "react"; +import { auth, database } from "../../api/firebase-config"; +import { ref, onValue, get } from "firebase/database"; +import {Marker} from "pigeon-maps"; +import {onAuthStateChanged} from "firebase/auth" + +// Refactored Component Imports +// Data Structure Imports + import { Interest } from "../../../components/app/datatypes"; + +// Header Import +import { Header } from "../../../components/app/header"; + +// Contains most everything for the app homepage +function Home({ params }) { + // It's time to document and change these awful variable names + // State variables for app page + const [myRoomsObj, setMyRoomsObj] = useState(null); // My Rooms Object + const [profileData, setProfileData] = useState(null) + const [isAuthenticated, setAuth] = useState(false) + const [user, setUser] = useState(null) + const [userInterestArray, setUserInterestArray] = useState(null) + + const [isOwner, setOwn] = useState(false) + + // Authentication + useEffect(() => { + onAuthStateChanged(auth, (user) => { + if (user) { + get(ref(database, `users/${user.uid}`)) + .then((userData) => { + userData = userData.val() + if (userData) { + if (userData.uid == params.stub) { + setOwn(true) + } + setUser(userData) + setAuth(true) + } else { + window.location.href = "/onboarding" + } + + }) + } else { + setAuth(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() + i++; + } + setUserInterestArray(interestArray) + var rooms = snapshot.val().rooms; + setMyRoomsObj(rooms); + }); + },[]); + + return ( +
+ {isAuthenticated && ( +
+ {/* Left Side of Page */} +
+ {/* Header */} +
+ {/* Main Page Section */} +
+ +
+ +
+ {profileData.firstName} {profileData.lastName} +
+
@{profileData.username}
+
{profileData.bio}
+
+ {userInterestArray} +
+
+ {isOwner && ( Edit Profile )} + {!isOwner && ( Add Friend )} +
+
+
+ Feed +
+
+
+
+ )} +
+ ); +} + +export default Home; \ No newline at end of file diff --git a/frontend-next/src/components/app/datatypes.js b/frontend-next/src/components/app/datatypes.js index 0086abc..4ddd206 100644 --- a/frontend-next/src/components/app/datatypes.js +++ b/frontend-next/src/components/app/datatypes.js @@ -17,6 +17,16 @@ const userColors = [ "#c3cb71", ]; + const generateColor = (user_str) => { + // hashes username for consistent colors, maybe all functionality to pick color later + let hash = 0; + for (let i = 0; i < user_str.length; i++) { + hash = user_str.charCodeAt(i) + (hash * 32 - hash); + } + const index = Math.abs(hash) % userColors.length; + return index; + }; + // Chat Message export function Chat({ chatObj }) { let dateOptions = { @@ -28,16 +38,6 @@ export function Chat({ chatObj }) { minute: "2-digit", }; - const generateColor = (user_str) => { - // hashes username for consistent colors, maybe all functionality to pick color later - let hash = 0; - for (let i = 0; i < user_str.length; i++) { - hash = user_str.charCodeAt(i) + (hash * 32 - hash); - } - const index = Math.abs(hash) % userColors.length; - return index; - }; - return (
@@ -139,4 +139,16 @@ export function Geo({ loc, zoom, locMarker, markers }) { ); } - } \ No newline at end of file + } + + +// Interest for Profile +export function Interest({interest}) { + return ( +
+
+ {interest} +
+
+ ) +} \ No newline at end of file diff --git a/frontend-next/src/components/app/header.js b/frontend-next/src/components/app/header.js index 6e77650..85a69b5 100644 --- a/frontend-next/src/components/app/header.js +++ b/frontend-next/src/components/app/header.js @@ -1,6 +1,8 @@ import { auth, database } from "../../app/api/firebase-config"; import { ref, set, remove } from "firebase/database"; import {signOut} from "firebase/auth"; +import { Popover } from '@headlessui/react' + function logout() { console.log("Fire") @@ -74,22 +76,22 @@ import {signOut} from "firebase/auth"; export function Header({mainTab, isMyRoom, chatRoomObj, setChatRoomObj, setMainTab, setIsMyRoom, user}) { return ( -
-
- +
+ -
+
{mainTab == "chat" && isMyRoom == false && ( { addToMyRooms(chatRoomObj, setIsMyRoom, user); }} - className="p-2 cursor-pointer bg-[#dee0e0] bg-cyan-500 text-white font-bold rounded-full mr-5" + className="p-2 cursor-pointer bg-[#dee0e0] bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center" > Add to "My Rooms" @@ -99,7 +101,7 @@ export function Header({mainTab, isMyRoom, chatRoomObj, setChatRoomObj, setMainT onClick={() => { removeFromMyRooms(chatRoomObj, setIsMyRoom, user); }} - className="p-2 cursor-pointer bg-[#dee0e0] bg-cyan-500 text-white font-bold rounded-full mr-5" + className="p-2 cursor-pointer bg-[#dee0e0] bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center" > Remove from "My Rooms" @@ -109,18 +111,33 @@ export function Header({mainTab, isMyRoom, chatRoomObj, setChatRoomObj, setMainT onClick={() => { closeChatRoom(chatRoomObj, setChatRoomObj, setMainTab, user); }} - className="p-2 cursor-pointer bg-[#dee0e0] bg-cyan-500 text-white font-bold rounded-full mr-5" + className="p-2 cursor-pointer bg-[#dee0e0] bg-cyan-500 text-white font-bold rounded-full mr-5 flex items-center" > Close Chat )} - - Sign Out - + + + +
+
+ Nicholas +
+
+ +
+
+
+ + + + + + +
) diff --git a/frontend-next/src/components/app/sidebar/chat.js b/frontend-next/src/components/app/sidebar/chat.js index d92c55b..01cc6e3 100644 --- a/frontend-next/src/components/app/sidebar/chat.js +++ b/frontend-next/src/components/app/sidebar/chat.js @@ -1,6 +1,6 @@ import { Geo } from "../datatypes"; -export function Chat_Sidebar({chatRoomObj, chatroomOnline, chatroomUsersLoading, chatroomUsers}) { +export function Chat_Sidebar({chatRoomObj, chatroomOnline, chatroomUsersLoading, chatroomUsers, setTab}) { return (
-- 2.52.0 From fdb22a5307f907651030098d27289f3fae11c9cb Mon Sep 17 00:00:00 2001 From: Nicholas Pease Date: Wed, 27 Mar 2024 04:11:37 +0000 Subject: [PATCH 2/6] Progress Commit --- frontend-next/src/app/app/page.js | 23 ++-- frontend-next/src/app/login/page.js | 8 +- frontend-next/src/app/onboarding/page.js | 3 +- frontend-next/src/app/page.js | 3 +- frontend-next/src/app/register/page.js | 15 +-- frontend-next/src/app/user/[stub]/layout.js | 2 +- frontend-next/src/app/user/[stub]/page.js | 106 ++++++++++++++---- frontend-next/src/components/app/datatypes.js | 48 +++++--- frontend-next/src/components/app/header.js | 3 +- .../src/components/app/main_tab/chat.js | 2 +- .../src/components/app/sidebar/home.js | 2 +- .../src/{app/api => }/firebase-config.js | 0 package-lock.json | 98 +++++++++++++++- package.json | 5 + 14 files changed, 245 insertions(+), 73 deletions(-) rename frontend-next/src/{app/api => }/firebase-config.js (100%) create mode 100644 package.json diff --git a/frontend-next/src/app/app/page.js b/frontend-next/src/app/app/page.js index 24ec274..3bd19ae 100644 --- a/frontend-next/src/app/app/page.js +++ b/frontend-next/src/app/app/page.js @@ -1,12 +1,12 @@ "use client"; // System Imports import { useState, useEffect } from "react"; -import { auth, database } from "../api/firebase-config"; +import { auth, database } from "../../firebase-config"; import { ref, onValue, set, remove, get } from "firebase/database"; import { useBeforeunload } from "react-beforeunload"; -import {useRouter} from "next/navigation"; import {Marker} from "pigeon-maps"; -import {onAuthStateChanged, signOut} from "firebase/auth" +import {onAuthStateChanged} from "firebase/auth" +import { useSearchParams } from 'next/navigation' // Refactored Component Imports // Data Structure Imports @@ -45,6 +45,17 @@ function Home() { const [markers, setMarkers] = useState([]); const [isAuthenticated, setAuth] = useState(false) const [user, setUser] = useState(null) + const [usingSearchParams, setUsingSearchParams] = useState(true) + + const searchParams = useSearchParams() + 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()) + }); + } // Authentication useEffect(() => { @@ -53,7 +64,6 @@ function Home() { get(ref(database, `users/${user.uid}`)) .then((userData) => { userData = userData.val() - console.log(userData) if (userData) { setUser(userData) setAuth(true) @@ -140,7 +150,6 @@ function Home() { } },[user]); - // Dont Double Send Leaving Message useEffect(() => { if (myRoomsObj && chatRoomObj) { @@ -196,10 +205,6 @@ function Home() { } // Users who added to "my rooms" - console.log( - snapshot.val().hasOwnProperty("users") && - snapshot.val().users.hasOwnProperty("all") - ); if ( snapshot.val().hasOwnProperty("users") && snapshot.val().users.hasOwnProperty("all") diff --git a/frontend-next/src/app/login/page.js b/frontend-next/src/app/login/page.js index a544c89..a455b92 100644 --- a/frontend-next/src/app/login/page.js +++ b/frontend-next/src/app/login/page.js @@ -4,8 +4,8 @@ import { useRouter } from "next/navigation"; import "../globals.css" // Firebase imports -import {auth} from "../api/firebase-config"; -import { setPersistence, signInWithEmailAndPassword, browserSessionPersistence } from "firebase/auth"; +import {auth} from "../../firebase-config"; +import { setPersistence, signInWithEmailAndPassword, indexedDBLocalPersistence } from "firebase/auth"; function Login() { var router = useRouter(); @@ -13,7 +13,7 @@ function Login() { var { register, control, setError, handleSubmit, formState: { errors, isSubmitting, isSubmitted } } = useForm() function authenticate(data) { - setPersistence(auth, browserSessionPersistence) + setPersistence(auth, indexedDBLocalPersistence) .then(() => { signInWithEmailAndPassword(auth,data.email,data.password) .then((userCredential) => { @@ -45,7 +45,7 @@ function Login() { >

-
+
Have an account? Log In
diff --git a/frontend-next/src/app/user/[stub]/layout.js b/frontend-next/src/app/user/[stub]/layout.js index ba13310..94d85e5 100644 --- a/frontend-next/src/app/user/[stub]/layout.js +++ b/frontend-next/src/app/user/[stub]/layout.js @@ -4,7 +4,7 @@ import "../../globals.css"; const inter = Inter({ subsets: ["latin"] }); export const metadata = { - title: "ChatMaps: Home", + title: "ChatMaps: User Profile", description: "ChatMaps: Social Media for College Students", }; diff --git a/frontend-next/src/app/user/[stub]/page.js b/frontend-next/src/app/user/[stub]/page.js index 29c9b21..0528bb3 100644 --- a/frontend-next/src/app/user/[stub]/page.js +++ b/frontend-next/src/app/user/[stub]/page.js @@ -1,14 +1,15 @@ "use client"; // System Imports import { useState, useEffect } from "react"; -import { auth, database } from "../../api/firebase-config"; -import { ref, onValue, get } from "firebase/database"; +import { auth, database } from "../../../firebase-config"; +import { ref, onValue, get, set, update } from "firebase/database"; import {Marker} from "pigeon-maps"; import {onAuthStateChanged} from "firebase/auth" +import { useForm, Form } from "react-hook-form"; // Refactored Component Imports // Data Structure Imports - import { Interest } from "../../../components/app/datatypes"; + import { Interest, ProfileRoom } from "../../../components/app/datatypes"; // Header Import import { Header } from "../../../components/app/header"; @@ -17,13 +18,15 @@ import { Header } from "../../../components/app/header"; function Home({ params }) { // It's time to document and change these awful variable names // State variables for app page - const [myRoomsObj, setMyRoomsObj] = useState(null); // My Rooms Object 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) + + var { register, control, setError, handleSubmit, formState: { errors, isSubmitting, isSubmitted } } = useForm() // Authentication useEffect(() => { @@ -65,10 +68,25 @@ function Home({ params }) { } setUserInterestArray(interestArray) var rooms = snapshot.val().rooms; - setMyRoomsObj(rooms); + var roomArray = [] + for (var room in rooms) { + roomArray.push() + } + setUserRoomsArray(roomArray); }); },[]); + function save({data}) { + for (var key in data) { + if (data[key] == "") { + data[key] = profileData[key] + } + } + console.log(data) + setEdit(false) + update(ref(database, `users/${user.uid}`), data) + } + return (
{isAuthenticated && ( @@ -80,23 +98,67 @@ function Home({ params }) { {/* Main Page Section */}
-
- -
- {profileData.firstName} {profileData.lastName} -
-
@{profileData.username}
-
{profileData.bio}
-
- {userInterestArray} -
-
- {isOwner && ( Edit Profile )} - {!isOwner && ( Add Friend )} -
+
+ {!isEditing && ( +
+ +
+ {profileData.firstName} {profileData.lastName} +
+
@{profileData.username}
+
{profileData.bio}
+
+ {userInterestArray} +
+ +
+ )} + {isEditing && ( +
+
+
+
+ + Current Profile Picture +
+
+ +
+
+
First Name
+ +
+
+
Last Name
+ +
+
+
Username
+ +
+
+
Interests (Comma Seperated)
+ +
+
+
Bio
+