From 57d30c1845def4e7d7b22df5b498f1c5bd178243 Mon Sep 17 00:00:00 2001 From: Tyler Murphy Date: Wed, 15 Feb 2023 13:32:43 -0500 Subject: [PATCH] followers and following tabs --- public/css/profile.css | 2 +- public/js/profile.js | 92 ++++++++++++++++++++--------------------- src/database/friends.rs | 44 ++++++++++++++++++++ src/types/user.rs | 15 +++++-- 4 files changed, 101 insertions(+), 52 deletions(-) diff --git a/public/css/profile.css b/public/css/profile.css index 112b1bf..54bf4f1 100644 --- a/public/css/profile.css +++ b/public/css/profile.css @@ -119,7 +119,7 @@ body { border-bottom: 3px solid var(--logo) !important; } -#about, #friends { +#about, #friends, #followers, #following { margin-top: 2em; align-self: center; padding: 0; diff --git a/public/js/profile.js b/public/js/profile.js index 4e4f44f..a9990fb 100644 --- a/public/js/profile.js +++ b/public/js/profile.js @@ -3,58 +3,38 @@ import { loadself, loadusers, loadusersposts, updateavatar, updatebanner, logout import { parsePost, parseUser, header } from './components.js' function swap(tab) { - let post_button = document.querySelector("#profilepostbutton"); - let about_button = document.querySelector("#profileaboutbutton"); - let friends_button = document.querySelector("#profilefriendsbutton"); + let buttons = [] + buttons[0] = document.querySelector("#profilepostbutton"); + buttons[1] = document.querySelector("#profileaboutbutton"); + buttons[2] = document.querySelector("#profilefriendsbutton"); + buttons[3] = document.querySelector("#profilefollowersbutton"); + buttons[4] = document.querySelector("#profilefollowingbutton"); - let posts_section = document.querySelector("#posts"); - let about_section = document.querySelector("#about"); - let friends_section = document.querySelector("#friends"); + let sections = [] + sections[0] = document.querySelector("#posts"); + sections[1] = document.querySelector("#about"); + sections[2] = document.querySelector("#friends"); + sections[3] = document.querySelector("#followers"); + sections[4] = document.querySelector("#following"); let load = document.querySelector(".loadp"); - if (tab === 0) { + for (const i in buttons) { + if (i == tab) { + buttons[i].classList.add("selected") + sections[i].classList.remove("hidden") + } else { + buttons[i].classList.remove("selected") + sections[i].classList.add("hidden") + } + } - post_button.classList.add("selected") - about_button.classList.remove("selected") - friends_button.classList.remove("selected") - - posts_section.classList.remove("hidden") - about_section.classList.add("hidden") - friends_section.classList.add("hidden") - - if (load) { + if (load) { + if (tab == 0) { load.classList.remove("hidden") - } - - } else if (tab === 1) { - - post_button.classList.remove("selected") - about_button.classList.add("selected") - friends_button.classList.remove("selected") - - posts_section.classList.add("hidden") - about_section.classList.remove("hidden") - friends_section.classList.add("hidden") - - if (load) { + } else { load.classList.add("hidden") } - - } else if (tab === 2) { - - post_button.classList.remove("selected") - about_button.classList.remove("selected") - friends_button.classList.add("selected") - - posts_section.classList.add("hidden") - about_section.classList.add("hidden") - friends_section.classList.remove("hidden") - - if (load) { - load.classList.add("hidden") - } - } } @@ -116,11 +96,15 @@ async function render() { } } - let friends_arr = (await friends(data.user.user_id)).json - if (friends_arr == undefined) { - friends_arr = [] + let response = (await friends(data.user.user_id)).json + if (response == undefined) { + response = [] } + let friends_arr = response[0]; + let followers = response[1]; + let following = response[2]; + let new_body = body({}, ...header(false, false, data.self.user_id), @@ -190,6 +174,12 @@ async function render() { button({id: 'profilefriendsbutton', onclick: () => swap(2)}, parse('Friends') ), + button({id: 'profilefollowersbutton', onclick: () => swap(3)}, + parse('Followers') + ), + button({id: 'profilefollowingbutton', onclick: () => swap(4)}, + parse('Following') + ), div({style: 'flex: 20'}), isself ? button({class: 'logout', onclick: async () => { const response = await logout() @@ -239,13 +229,19 @@ async function render() { parse('Birthday: ' + parseMonth(data.user.month) + ' ' + data.user.day + ', ' + data.user.year) ), span({class: 'gtext bold'}, - parse('User ID: ' + data.user_id) + parse('User ID: ' + data.user.user_id) ) ) ), div({id: 'friends', class: 'hidden'}, ...friends_arr.map(u => parseUser(u)) ), + div({id: 'followers', class: 'hidden'}, + ...followers.map(u => parseUser(u)) + ), + div({id: 'following', class: 'hidden'}, + ...following.map(u => parseUser(u)) + ), div({id: 'popup', class: 'hidden'}, div({class: 'createpost'}, div({class: 'close', onclick: () => document.getElementById('popup').classList.add('hidden')}), diff --git a/src/database/friends.rs b/src/database/friends.rs index 31434d4..7e23616 100644 --- a/src/database/friends.rs +++ b/src/database/friends.rs @@ -74,6 +74,50 @@ impl Database { Ok(row.into_iter().flatten().collect()) } + #[instrument(skip(self))] + pub fn get_followers(&self, user_id: u64) -> Result, rusqlite::Error> { + tracing::trace!("Retrieving friends"); + let mut stmt = self.0.prepare( + " + SELECT * + FROM users u + WHERE EXISTS ( + SELECT NULL + FROM friends f + WHERE f.follower_id = ? + AND u.user_id = f.followee_id + ) + ", + )?; + let row = stmt.query_map([user_id], |row| { + let row = Self::user_from_row(row, true)?; + Ok(row) + })?; + Ok(row.into_iter().flatten().collect()) + } + + #[instrument(skip(self))] + pub fn get_following(&self, user_id: u64) -> Result, rusqlite::Error> { + tracing::trace!("Retrieving friends"); + let mut stmt = self.0.prepare( + " + SELECT * + FROM users u + WHERE EXISTS ( + SELECT NULL + FROM friends f + WHERE u.user_id = f.follower_id + AND f.followee_id = ? + ) + ", + )?; + let row = stmt.query_map([user_id], |row| { + let row = Self::user_from_row(row, true)?; + Ok(row) + })?; + Ok(row.into_iter().flatten().collect()) + } + #[instrument(skip(self))] pub fn set_following(&self, user_id_1: u64, user_id_2: u64) -> Result { tracing::trace!("Setting following"); diff --git a/src/types/user.rs b/src/types/user.rs index 3c4cd6a..3d7d85a 100644 --- a/src/types/user.rs +++ b/src/types/user.rs @@ -135,10 +135,19 @@ impl User { } #[instrument(skip(db))] - pub fn get_friends(db: &Database, user_id: u64) -> Result> { - let Ok(users) = db.get_friends(user_id) else { + pub fn get_friends(db: &Database, user_id: u64) -> Result<(Vec, Vec, Vec)> { + let Ok(friends) = db.get_friends(user_id) else { return Err(ResponseCode::InternalServerError.text("Failed to fetch friends")) }; - Ok(users) + + let Ok(followers) = db.get_followers(user_id) else { + return Err(ResponseCode::InternalServerError.text("Failed to fetch friends")) + }; + + let Ok(following) = db.get_following(user_id) else { + return Err(ResponseCode::InternalServerError.text("Failed to fetch friends")) + }; + + Ok((friends, followers, following)) } }