followers and following tabs

This commit is contained in:
Tyler Murphy 2023-02-15 13:32:43 -05:00
parent a8b6798dfe
commit 57d30c1845
4 changed files with 101 additions and 52 deletions

View file

@ -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;

View file

@ -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) {
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")
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")
}
}
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')}),

View file

@ -74,6 +74,50 @@ impl Database {
Ok(row.into_iter().flatten().collect())
}
#[instrument(skip(self))]
pub fn get_followers(&self, user_id: u64) -> Result<Vec<User>, 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<Vec<User>, 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<bool, rusqlite::Error> {
tracing::trace!("Setting following");

View file

@ -135,10 +135,19 @@ impl User {
}
#[instrument(skip(db))]
pub fn get_friends(db: &Database, user_id: u64) -> Result<Vec<Self>> {
let Ok(users) = db.get_friends(user_id) else {
pub fn get_friends(db: &Database, user_id: u64) -> Result<(Vec<Self>, Vec<Self>, Vec<Self>)> {
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))
}
}