Individual Contributions - bounswe/bounswe2024group6 GitHub Wiki
Throughout this milestone, I focused on frontend development, design enhancements, and feature implementation to improve the user experience and ensure smooth functionality. My responsibilities included:
- Feature Development:
- Designed and implemented quiz-related components, such as the quiz feed, quiz card, and quiz results page.
- Created functionalities like bookmarking posts, sorting and filtering forum posts, and improving profile page features.
- Developed interactive elements, including user popovers, profile edit pages, and quiz continuation features.
- Connected frontend features with backend APIs, including all profile page features, quiz functionalities, and fixed problems in user interactions like follow/unfollow, bookmark etc.
- Design Enhancements:
- Improved the frontend design for a polished milestone presentation.
- Fixed dark mode display issues across various pages.
- Enhanced user interaction through intuitive navigation and UI adjustments.
- Bug Fixing and Testing:
- Fixed significant issues, such as updating follower counts, missing usernames, non-functional tags, and many more.
- Conducted unit testing for profile pages and other features to ensure code reliability.
- Planning:
- Reviewed and coordinated backend JSON request/response formats for profile, post and quiz-related data. Reported all missing elements and pointed possible future errors.
- Decided on the application tags, documented them and added them in the related fields in the code.
- Listed milestone requirements for reports and participated in demo preparation.
- Participated in milestone planning and demo preparation.
- Created core components like quiz pages, profile pages.
- Enabled bookmarking posts and created a tab to display bookmarked posts on the profile page alongside with created posts.
- Added functionalities like sorting forum posts by date and like count and filtering posts by tags.
- Developed a popover feature for user details in posts.
- Connected frontend features to backend APIs for seamless functionality.
- Improved frontend UI for the milestone presentation, continuously searched for design/applications related issues and fixed many of them.
- Implemented unit tests for profile-related features, including edit and view functionalities.
- Reviewed backend JSON responses for consistency and reliability.
- Finalized application tags and integrated them into the code.
I was responsible for creating quiz related pages, connecting post and profile related pages to backend, and enhancing design overall.
User Card Feature
import React from "react";
import { Avatar, Button, Card, CardBody, CardFooter, CardHeader } from "@nextui-org/react";
import { Suspense, useState, useEffect } from "react";
import axios from "axios";
import { BASE_URL } from "../../lib/baseURL";
import { Profile, ProfileResponse } from "../../types";
import { convertProfileResponseToProfile } from "./utils";
import { AuthActions } from "../../components/auth/utils.tsx";
import { useNavigate, useLocation } from "react-router-dom";
import Cookies from "js-cookie";
type Props = {
username: string;
};
export const UserCard = ({
username,
}: Props) => {
const [isFollowed, setIsFollowed] = React.useState(false);
const { getToken } = AuthActions();
const token = getToken("access");
const [profile, setProfile] = useState<Profile | null>(null);
const [followCount, setFollowCount] = useState(0);
const navigate = useNavigate();
useEffect(() => {
if (username) {
axios
.get(`${BASE_URL}/profile/${username}/`, {
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
})
.then((response) => {
const data: ProfileResponse = response.data;
console.log(data);
const profile = convertProfileResponseToProfile(data);
setIsFollowed(profile.is_followed);
setProfile(profile);
setFollowCount(profile.followers);
})
.catch((error) => {
console.log(error);
});
}
}, [username, token]);
const toggleFollow = () => {
axios
.post(
`${BASE_URL}/profile/${isFollowed ? "unfollow" : "follow"}/`,
{
username: profile?.username,
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
)
.then((response) => {
console.log(response.data);
setFollowCount(response.data.follower_count);
})
.catch((error) => {
console.log(error);
});
setIsFollowed(!isFollowed);
};
return (
<Card shadow="none" className="w-[300px] border-none bg-transparent">
<CardHeader className="justify-between">
<div className="flex gap-3">
<Avatar isBordered radius="full" size="md" src="https://nextui.org/avatars/avatar-1.png" />
<div className="flex flex-col items-start justify-center">
<h4 className="text-small font-semibold leading-none text-default-600">{profile?.username}</h4>
<h5 className="text-small tracking-tight text-default-500">@{profile?.level}</h5>
</div>
</div>
<div className="flex flex-row items-center gap-2">
{profile && profile.username !== Cookies.get("username") &&
<Button
className={isFollowed ? "bg-transparent text-foreground border-default-200" : ""}
color="primary"
radius="full"
size="sm"
variant={isFollowed ? "bordered" : "solid"}
onClick={toggleFollow}
>
{isFollowed ? "Unfollow" : "Follow"}
</Button>}
<Button color="primary" variant="faded" size="sm" radius="full" onClick={() => navigate(`/profile/${username}`)}>
Profile
</Button>
</div>
</CardHeader>
<CardBody className="px-3 py-0">
<p className="text-small pl-px text-default-500">
{profile?.bio || "Hey, new learner here!"}
</p>
</CardBody>
<CardFooter className="gap-3">
<div className="flex gap-1">
<p className="font-semibold text-default-600 text-small">{profile?.following}</p>
<p className=" text-default-500 text-small">Following</p>
</div>
<div className="flex gap-1">
<p className="font-semibold text-default-600 text-small">{followCount}</p>
<p className="text-default-500 text-small">Followers</p>
</div>
</CardFooter>
</Card>
);
};
Connecting Profile To Backend I did all major connections, added sorted posts and bookmarks to the profile.
// All profile related data and sorting posts based on creation date
useEffect(() => {
if (username) {
setIsLoading(true);
axios
.get(`${BASE_URL}/profile/${username}/`, {
headers: {
Authorization: `Bearer ${token}`,
},
})
.then((response) => {
const data: ProfileResponse = response.data;
console.log(data);
const profile = convertProfileResponseToProfile(data);
const sortedVersion = [...profile.posts].sort((a, b) => {
return (
new Date(b.post.created_at).getTime() -
new Date(a.post.created_at).getTime()
);
});
setFollowCount(profile.followers);
setIsFollowing(profile.is_followed);
setSortedPosts(sortedVersion);
setProfile(profile);
})
.catch((error) => {
console.log(error);
})
.finally(() => {
setIsLoading(false);
});
}
}, [username, token]);
// Getting bookmarked posts
useEffect(() => {
if (username === Cookies.get("username")) {
console.log("Fetching bookmarked posts");
axios
.post(
`${BASE_URL}/get_bookmarked_posts/`,
{
username: profile?.username,
},
{
headers: {
Authorization: `Bearer ${token}`,
},
}
)
.then((response) => {
console.log(response);
const bookmarked = response.data.map(convertPostResponseToPost);
setBookmarkedPosts(bookmarked);
})
.catch((error) => {
console.log(error);
});
} else {
console.log("Not fetching bookmarked posts");
}
}, [token]);
Sorting And Filtering Features In Forum
const [sortFilter, setSortFilter] = useState<string>("Most Recent");
const handleSelectionChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setSortFilter(e.target.value);
};
const filteredPosts = posts.filter((post) => {
// Show all posts if no tags are selected
if (selectedTags.length === 0) return true;
// Check if the post has at least one tag from the selectedTags
return post.post.tags.some((tag) => selectedTags.includes(tag));
});
const sortedPosts = [...filteredPosts].sort((a, b) => {
switch (sortFilter) {
case "Most Recent":
return (
new Date(b.post.created_at).getTime() -
new Date(a.post.created_at).getTime()
);
case "Most Liked":
return b.engagement.likes - a.engagement.likes;
default:
return 0;
}
});
const handleTagClick = (tag: string) => {
if (selectedTags.includes(tag)) {
setSelectedTags(selectedTags.filter((t) => t !== tag));
} else {
setSelectedTags([...selectedTags, tag]);
}
};
<div className="flex w-[740px] justify-between items-center mt-4">
<Select
onChange={handleSelectionChange}
placeholder="Sort By"
defaultSelectedKeys={["Most Recent"]}
className="w-44 text-black"
>
{SortFilters.map((sortFilter) => (
<SelectItem key={sortFilter}>{sortFilter}</SelectItem>
))}
</Select>
<div className="flex flex-row gap-2">
<Select
placeholder="Difficulty"
selectionMode="multiple"
className="w-32 text-black"
>
{DifficultyTags.map((tag) => (
<SelectItem onPress={() => handleTagClick(tag)} key={tag}>
{tag}
</SelectItem>
))}
</Select>
<Select
placeholder="Categories"
selectionMode="multiple"
className="w-32 text-black"
>
{Tags.map((tag) => (
<SelectItem onPress={() => handleTagClick(tag)} key={tag}>
{tag}
</SelectItem>
))}
</Select>
</div>
Pull Requests | Link | Action |
---|---|---|
added edit-profile tests | link | assigned |
Design improvements | 1, 2 | assigned |
Fix follower count issue | link | assigned |
added bookmarked posts to profile | link | assigned |
implemented popover user cards | link | assigned |
created edit-profile page, added missing types to Profile | link | assigned |
implemented other/own users' profile views | link | assigned |
Added filtering functionality to forum | link | assigned |
sorted posts in profile and fixed difficulty tag issue | link | assigned |
implemented forum sorting methods | link | assigned |
Fixed the background issue with the profile avatar | link | assigned |
added photo feature to quiz details page | link | assigned |
redesigned quiz component and added photo to it | link | assigned |
feat(frontend): edited compose post and forum tags | link | assigned |
fix(frontend): changed navbar icon's functionality | link | assigned |
feat(frontend): Initial Designs of Quiz Components and Pages | assigned | |
feat(frontend): reorganised profile page and added options to profile icon in navbar | link | assigned |
I reviewed almost all frontend pull requests.