diff --git a/src/components/StandardNav.jsx b/src/components/StandardNav.jsx index f1ed8312..5df00fb2 100644 --- a/src/components/StandardNav.jsx +++ b/src/components/StandardNav.jsx @@ -1,5 +1,5 @@ import { Fragment, useEffect, useState } from 'react'; -import { Disclosure, Menu, Transition } from '@headlessui/react'; +import { Disclosure, Menu, Popover, Transition } from '@headlessui/react'; import { Bars3Icon, XMarkIcon, @@ -57,17 +57,13 @@ export function StandardNav(props) { } // if user signed out redirect - // if env is NEXT_PUBLIC_APP_AUTH_DOMAIN=ctfguide-dev.firebaseapp.com the logo should say CTFGuide Developer not CTFGuide Beta - - useEffect(() => { if (!localStorage.getItem('dismissStatus')) { setShowBanner(true); } - if ( process.env.NEXT_PUBLIC_APP_AUTH_DOMAIN === 'ctfguide-dev.firebaseapp.com' ) { @@ -89,32 +85,28 @@ export function StandardNav(props) { return; } - - if (localStorage.getItem("pfp")) { - setPfp(localStorage.getItem("pfp")); - } + if (localStorage.getItem("pfp")) { + setPfp(localStorage.getItem("pfp")); + } - - - - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + username + '/pfp'; - const result = await request(endPoint, "GET", null); - if (result) { - setPfp(result) - } else { - setPfp(`https://robohash.org/${username}.png?set=set1&size=150x150`) - } - - } catch (err) { - console.log('failed to get profile picture') - } - }; - fetchData(); + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + username + '/pfp'; + const result = await request(endPoint, "GET", null); + if (result) { + setPfp(result) + } else { + setPfp(`https://robohash.org/${username}.png?set=set1&size=150x150`) + } + + } catch (err) { + console.log('failed to get profile picture') + } + }; + fetchData(); }, [username]); - useEffect(() => { + useEffect(() => { const fetchNotification = async () => { const endPoint = process.env.NEXT_PUBLIC_API_URL + '/account/notifications'; const result = await request(endPoint, 'GET', null); @@ -149,7 +141,7 @@ export function StandardNav(props) { receivedTime: noti + ' ago', detailPage: '/events', image: - 'https://cutshort-data.s3.amazonaws.com/cloudfront/public/companies/5809d1d8af3059ed5b346ed1/logo-1615367026425-logo-v6.png', + 'https://cutshort-data.s3.amazonaws.com/cloudfront/public/companies/5809d1d8af3059ed5b346ed1/logo-1615367026425-logo-v6.png', }; }) ); @@ -158,7 +150,6 @@ export function StandardNav(props) { fetchNotification(); }, []); - function dismissStatus() { localStorage.setItem('dismissStatus', true); setShowBanner(false); @@ -169,21 +160,21 @@ export function StandardNav(props) { const url = `${process.env.NEXT_PUBLIC_API_URL}/notification`; const data = await request(url, 'GET', null); console.log(data); - if(data.success) { + if (data.success) { setNotifications(data.body); console.log(data); } else { setNotifications(["Unable to get notification, try again"]); } - } catch(err) { + } catch (err) { console.log(err); } } return ( <> - + {({ open }) => ( <>
@@ -207,206 +198,185 @@ export function StandardNav(props) {
- + {isAdmin ? : }
- {/* Current: "border-blue-500 text-white", Default: "border-transparent text-gray-300 hover:font-bold" */} + {/* Current: "border-blue-500 text-white", Default: "border-transparent text-gray-300 hover:text-white" */} Dashboard Learn Classes Practice Create - - Live - - - - EDU - + {/* */} + {/* Live */} + {/* */} + {/**/} + {/* */} + {/* EDU */} + {/* */} {isAdmin && (

CTFGUIDE INTERNAL

)}
- { !guestAllowed && + {!guestAllowed &&
-
-

- {points} -

-
-
-

- 0 -

-
-
- {/* Profile dropdown */} - -
- - Open user menu - - -
- - - - {({ active }) => ( - */} + {/*

*/} + {/* {points} */} + {/*

*/} + {/*
*/} + {/*
*/} + {/*

*/} + {/* 0 */} + {/*

*/} + {/*
*/} +
+ {/* Profile dropdown */} + +
+ + Open user menu + + +
+ + +
+ - Your Profile{' '} - )} - - - {({ active }) => ( - +
+
+ - Settings{' '} - )} - - - {({ active }) => ( - - Feedback{' '} - - )} - - - {({ active }) => ( - - Report{' '} - - )} - - - {({ active }) => ( - - Sign out{' '} - - )} - - - - + Settings + +
+ + + +
- } - +
- {/* Current: "bg-blue-50 border-blue-500 text-blue-700", Default: "border-transparent text-gray-300 hover:font-bold" */} + {/* Current: "bg-blue-50 border-blue-500 text-blue-700", Default: "border-transparent text-gray-300 hover:text-white" */} - Your Profile + Profile )} - + {isAdmin && (

CTFGuide is running in development mode.

- )} + ) + } - {!['/groups', '/assignments', '/submissions'].some(path => router.pathname.includes(path) || !showBanner) && ( -
-

Limited feature availability for GP. View entire site status here. Dismiss

-
- )} + { + !['/groups', '/assignments', '/submissions'].some(path => router.pathname.includes(path) || !showBanner) && ( +
+

Limited feature availability for GP. View entire site status here. Dismiss

+
+ ) + } ); } diff --git a/src/components/dashboard/DashboardHeader.jsx b/src/components/dashboard/DashboardHeader.jsx index 2a59ad95..6a313d47 100644 --- a/src/components/dashboard/DashboardHeader.jsx +++ b/src/components/dashboard/DashboardHeader.jsx @@ -19,12 +19,12 @@ export function DashboardHeader() { useEffect(() => { try { - request(`${process.env.NEXT_PUBLIC_API_URL}/account`, 'GET', null) + request(`${process.env.NEXT_PUBLIC_API_URL}/account`, 'GET', null) .then((data) => { setUsername(data.username); setLocation(data.location); localStorage.setItem("username", data.username) - + setJoin(data.createdAt.substring(0, 10)); if (data.githubUrl) { setGithub(`https://github.com/${data.githubUrl}`); @@ -41,28 +41,28 @@ export function DashboardHeader() { }, []); // get user's profile picture - useEffect(() => { - if (!username) { - return; - } - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + username + '/pfp'; - const result = await request(endPoint, "GET", null); - console.log(result) - if (result) { - setPfp(result) - localStorage("pfp", result) - } else { - setPfp(`https://robohash.org/${username}.png?set=set1&size=150x150`) - } + useEffect(() => { + if (!username) { + return; + } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + username + '/pfp'; + const result = await request(endPoint, "GET", null); + console.log(result) + if (result) { + setPfp(result) + localStorage("pfp", result) + } else { + setPfp(`https://robohash.org/${username}.png?set=set1&size=150x150`) + } - } catch (err) { - console.log('failed to get profile picture') - } - }; - fetchData(); - }, [username]); + } catch (err) { + console.log('failed to get profile picture') + } + }; + fetchData(); + }, [username]); function createPopupWin(pageURL, pageTitle, popupWinWidth, popupWinHeight) { @@ -114,7 +114,7 @@ export function DashboardHeader() { )}

- {' '} + {' '} {location || ( )} @@ -144,19 +144,15 @@ export function DashboardHeader() { )}

-
{ - createPopupWin('../terminal', 'CTFGuide Terminal', 1200, 650); - - }} className="hidden cursor-pointer ml-2 mt-8 mb-0 rounded-lg px-10 py-1 flex items-center space-x-1 duration-4000 bg-neutral-800 transition ease-in-out hover:bg-neutral-800/40" > -

Terminal

+

Terminal

@@ -10,22 +12,10 @@ export function Suggest() {
- +
- - - - ); diff --git a/src/components/design/CardDecorator.jsx b/src/components/design/CardDecorator.jsx new file mode 100644 index 00000000..275f1332 --- /dev/null +++ b/src/components/design/CardDecorator.jsx @@ -0,0 +1,17 @@ +/** + * @param props {import("react").HTMLAttributes & {position?: 'top' | 'left'}} + */ +export function CardDecorator({ className = '', position = 'top', ...props }) { + const getCardStyle = (pos) => { + if (pos == 'top') { + return 'card-decorator-top'; + } else if (pos == 'left') { + return 'card-decorator-left'; + } else { + console.error('Invalid card position.') + } + } + return ( +
+ ); +} diff --git a/src/components/practice/PracticeNav.jsx b/src/components/practice/PracticeNav.jsx index ddf9d4b0..ba1df44f 100644 --- a/src/components/practice/PracticeNav.jsx +++ b/src/components/practice/PracticeNav.jsx @@ -5,11 +5,11 @@ export function PracticeNav() { return ( <>

- +
  • - Join our community! - + Join our community! +
  • diff --git a/src/components/practice/community.jsx b/src/components/practice/community.jsx index 50ab5dae..534d7be0 100644 --- a/src/components/practice/community.jsx +++ b/src/components/practice/community.jsx @@ -1,5 +1,6 @@ import { useState, useEffect } from 'react'; import Challenge from '../challenge/ChallengeComponent'; +import ChallengeCard from '../profile/ChallengeCard'; export function Community({ challenges }) { const [difficulty, setDifficulty] = useState('all'); @@ -38,12 +39,10 @@ export function Community({ challenges }) { setFilter(event.target.value); }; - - return ( <> -
    -
    +
    +
    -
    +
    -
    +
    -
    -

    Community Challenges

    -
    - {results.length > 0 - ? results - .filter((challenge) => { - if ( - difficulty.toLowerCase() !== 'all' && - challenge.difficulty.toLowerCase() !== difficulty.toLowerCase() - ) { - return false; - } - if ( - filter !== '' && - challenge.category.includes(filter.toLowerCase()) - ) { - return true; - } - if ( - filter !== '' && - !( - challenge.title - .toLowerCase() - .includes(filter.toLowerCase()) || - challenge.content - .toLowerCase() - .includes(filter.toLowerCase()) - ) - ) { - return false; - } - return true; - }) - .map((challenge, index) => ( - - )) - : challenges - .filter((challenge) => { - if ( - difficulty.toLowerCase() !== 'all' && - challenge.difficulty.toLowerCase() !== difficulty.toLowerCase() - ) { - return false; - } - if ( - filter !== '' && - challenge.category.includes(filter.toLowerCase()) - ) { - return true; - } - if ( - filter !== '' && - !( - challenge.title - .toLowerCase() - .includes(filter.toLowerCase()) || - challenge.content - .toLowerCase() - .includes(filter.toLowerCase()) - ) - ) { - return false; - } +
    +

    Community Challenges

    +
    + {challenges && (results.length > 0 ? results : challenges) + .filter((challenge) => { + if ( + difficulty.toLowerCase() !== 'all' && + challenge.difficulty.toLowerCase() !== difficulty.toLowerCase() + ) { + return false; + } + if ( + filter !== '' && + challenge.category.includes(filter.toLowerCase()) + ) { return true; - }) - .map((challenge, index) => ( - - ))} + } + if ( + filter !== '' && + !( + challenge.title + .toLowerCase() + .includes(filter.toLowerCase()) || + challenge.content + .toLowerCase() + .includes(filter.toLowerCase()) + ) + ) { + return false; + } + return true; + }) + .map((challenge) => ( + + )) + }
    diff --git a/src/components/profile/ChallengeCard.jsx b/src/components/profile/ChallengeCard.jsx index fd854a28..b936e694 100644 --- a/src/components/profile/ChallengeCard.jsx +++ b/src/components/profile/ChallengeCard.jsx @@ -1,76 +1,59 @@ import React from 'react'; import { Tooltip } from 'react-tooltip'; - -const ChallengeCard = ({ id, title, category, difficulty, createdAt, creator, views, likes }) => { - - const baseUrl = process.env.NEXT_PUBLIC_FRONTEND_URL; - - let color; - const colors = ['blue-600', 'green-600', 'orange-600', 'red-600', 'purple-400']; - - if (!difficulty) difficulty = 'BEGINNER'; - - if (difficulty === 'BEGINNER') { - color = colors[0]; - } else if (difficulty === 'EASY') { - color = colors[1]; - } else if (difficulty === 'MEDIUM') { - color = colors[2]; - } else if (difficulty === 'HARD') { - color = colors[3]; - } else if (difficulty === 'INSANE') { - color = colors[4]; - } else { - color = colors[0]; - } - - - return ( -
    - -
    -
    - -
    -
    +import { CardDecorator } from '../design/CardDecorator'; +import Link from 'next/link'; + +/** + * @param {import('react').HTMLAttributes & { challenge: {id: string, title: string, category: string, difficulty: string, createdAt: string, creator: string, views: number, likes: number} }} props + * */ +const ChallengeCard = (_props) => { + const { challenge, ...props } = _props; + const { id, title, category, difficulty, createdAt, creator, views, upvotes } = challenge; + const baseUrl = process.env.NEXT_PUBLIC_FRONTEND_URL; + const dateFormatted = new Date(createdAt) + .toLocaleDateString('en-US', { + month: '2-digit', + day: '2-digit', + year: 'numeric', + }); + + const colorBG = { + 'BEGINNER': 'group-hover:bg-blue-500', + 'EASY': 'group-hover:bg-green-500', + 'MEDIUM': 'group-hover:bg-orange-500', + 'HARD': 'group-hover:bg-red-500', + 'INSANE': 'group-hover:bg-purple-500', + }; + const colorText = { + 'BEGINNER': 'bg-blue-500 text-blue-50', + 'EASY': 'bg-green-500 text-green-50', + 'MEDIUM': 'bg-orange-500 text-orange-50', + 'HARD': 'bg-red-500 text-red-50', + 'INSANE': 'bg-purple-500 text-purple-50', + }; + + return ( + + +
    +

    {title}

    +

    Created by {creator}

    +

    {difficulty?.toLowerCase()}

    +
    +

    + + {dateFormatted} +

    +

    + + {views} + + {upvotes} +

    - ) +
    + + ) }; -export default ChallengeCard; \ No newline at end of file +export default ChallengeCard; diff --git a/src/pages/dashboard.jsx b/src/pages/dashboard.jsx index 6a89c69d..10a19127 100644 --- a/src/pages/dashboard.jsx +++ b/src/pages/dashboard.jsx @@ -2,33 +2,21 @@ import Head from 'next/head'; import { Footer } from '@/components/Footer'; import { StandardNav } from '@/components/StandardNav'; import { DashboardHeader } from '@/components/dashboard/DashboardHeader'; -import { Stats } from '@/components/dashboard/Stats'; -import { Performance } from '@/components/dashboard/Performance'; +import { CardDecorator } from '@/components/design/CardDecorator' import { useEffect } from 'react'; import { useState } from 'react'; -import { SideNavContent } from '@/components/dashboard/SideNavContents'; -import { QuickSettings } from '@/components/dashboard/QuickSetttings'; -import { Suggest } from '@/components/dashboard/Suggest'; -import { YourChallenges } from '@/components/dashboard/YourChallenges'; -import { Likes } from '@/components/dashboard/Likes'; -import { Badges } from '@/components/dashboard/Badges'; -import { useRouter } from 'next/router'; - -import Skeleton from 'react-loading-skeleton'; -import 'react-loading-skeleton/dist/skeleton.css'; -import { onAuthStateChanged, getAuth, verifyIdToken } from 'firebase/auth'; +import { ArrowLeftIcon, CheckCircleIcon, XCircleIcon } from '@heroicons/react/24/solid'; +import request from '@/utils/request'; +import ChallengeCard from '@/components/profile/ChallengeCard'; export default function Dashboard() { - - const router = useRouter(); - const auth = getAuth(); - - const [likes, setLikes] = useState([]); + const [likes, setLikes] = useState(null); const [badges, setbadges] = useState([]); const [challenges, setchallenges] = useState([]); useEffect(() => { + const user = localStorage.getItem('username'); // verify id token if not logout const fetchBadges = async () => { try { @@ -37,33 +25,31 @@ export default function Dashboard() { ); const data = await response.json(); setbadges(data); - } catch {} + } catch { } }; fetchBadges(); setbadges([]); + const fetchChallenges = async () => { try { - const response = await fetch( - `${localStorage.getItem('userChallengesUrl')}` - ); - const data = await response.json(); - setchallenges(data); - } catch (error) {} + const pinnedChallengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes'; + const pinnedChallengeResult = await request(pinnedChallengeEndPoint, "GET", null); + setchallenges(pinnedChallengeResult); + } catch (error) { } }; fetchChallenges(); setchallenges([]); const fetchData = async () => { try { - const response = await fetch(`${localStorage.getItem('userLikesUrl')}`); - const data = await response.json(); - console.log(data); - setLikes(data); - likes.map((like) => console.log(like.challenge.id)); - } catch (error) {} + const pinnedChallengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes'; + const pinnedChallengeResult = await request(pinnedChallengeEndPoint, "GET", null); + setLikes(pinnedChallengeResult); + } catch (error) { + console.error("Failed to fetch pinnedChallengeResults: ", error) + } }; fetchData(); - setLikes([]); }, []); return ( @@ -79,76 +65,97 @@ export default function Dashboard() { url('https://fonts.googleapis.com/css2?family=Poppins&display=swap'); - - @@ -620,18 +621,18 @@ const handleClick = () => { } alt="photo" /> - + - +
    @@ -1057,121 +1058,121 @@ const handleClick = () => {
    - {/* PROFILE PICTURE POP-UP */} - - - handlePopupClose()}> - - - -
    { - handlePopupClose() - localStorage.setItem("22-18-update", false) - }} - className="fixed inset-0 bg-gray-900 bg-opacity-75 transition-opacity" /> - -
    - -
    + {/* PROFILE PICTURE POP-UP */} + + + handlePopupClose()}> + + + +
    { + handlePopupClose() + localStorage.setItem("22-18-update", false) + }} + className="fixed inset-0 bg-gray-900 bg-opacity-75 transition-opacity" /> + +
    + +
    +
    +
    +

    Change Profile Picture

    +
    +
    +
    + +

    + Current Profile Picture +

    +
    +
    + {/* INPUT BOX */} +
    +
    - + ) : ( +
    + + + +

    Click here or Drag an Image!

    +
    + )} + +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    -
    -
    - +
    +
    +
    +
    +
    + @@ -1401,37 +1402,37 @@ const handleClick = () => { >
    @@ -1525,37 +1526,37 @@ const handleClick = () => { >
    diff --git a/src/pages/users/[user].jsx b/src/pages/users/[user].jsx index 477330ad..ccb8b7a7 100644 --- a/src/pages/users/[user].jsx +++ b/src/pages/users/[user].jsx @@ -35,1284 +35,1270 @@ import { Fragment } from 'react'; import request from "@/utils/request"; const shades = [ - 'ml-1 h-5 w-5 bg-neutral-900', - 'ml-1 h-5 w-5 bg-blue-100', - 'ml-1 h-5 w-5 bg-blue-200', - 'ml-1 h-5 w-5 bg-blue-300', - 'ml-1 h-5 w-5 bg-blue-400', - 'ml-1 h-5 w-5 bg-blue-500', - 'ml-1 h-5 w-5 bg-blue-600', - 'ml-1 h-5 w-5 bg-blue-700', - 'ml-1 h-5 w-5 bg-blue-800', - 'ml-1 h-5 w-5 bg-blue-900', + 'ml-1 h-5 w-5 bg-neutral-900', + 'ml-1 h-5 w-5 bg-blue-100', + 'ml-1 h-5 w-5 bg-blue-200', + 'ml-1 h-5 w-5 bg-blue-300', + 'ml-1 h-5 w-5 bg-blue-400', + 'ml-1 h-5 w-5 bg-blue-500', + 'ml-1 h-5 w-5 bg-blue-600', + 'ml-1 h-5 w-5 bg-blue-700', + 'ml-1 h-5 w-5 bg-blue-800', + 'ml-1 h-5 w-5 bg-blue-900', ]; export default function Users() { - const router = useRouter(); - const { user } = router.query; + let invalidUser = null; + const user = localStorage.getItem('username'); + const [ownUser, setOwnUser] = useState(false); + const [location, setLocation] = useState(null); + const [username, setUsername] = useState(null); - let invalidUser = null; - const [ownUser, setOwnUser] = useState(false); + const [bio, setBio] = useState(null); - const [location, setLocation] = useState(null); - const [username, setUsername] = useState(null); + const [followerCount, setFollowerCount] = useState(0); + const [followingCount, setFollowingCount] = useState(0); + const [followedUser, setFollowedUser] = useState(null); + const [followerList, setFollowerList] = useState(null); + const [userData, setUserData] = useState(null); - const [bio, setBio] = useState(null); + const [activity, setActivity] = useState([]); - const [followerCount, setFollowerCount] = useState(0); - const [followingCount, setFollowingCount] = useState(0); - const [followedUser, setFollowedUser] = useState(null); - const [followerList, setFollowerList] = useState(null); - const [userData, setUserData] = useState(null); + const [friendedUser, setFriendedUser] = useState(null); + const [pendingRequest, setPendingRequest] = useState(null); + const [friendList, setFriendList] = useState(null); - const [activity, setActivity] = useState([]); + const [createdChallenges, setCreatedChallenges] = useState(null); + const [pinnedChallenges, setPinnedChallenges] = useState(null); + const [completedChallenges, setCompletedChallenges] = useState(null); - const [friendedUser, setFriendedUser] = useState(null); - const [pendingRequest, setPendingRequest] = useState(null); - const [friendList, setFriendList] = useState(null); - const [createdChallenges, setCreatedChallenges] = useState(null); - const [pinnedChallenges, setPinnedChallenges] = useState(null); - const [completedChallenges, setCompletedChallenges] = useState(null); + const [createDate, setCreateDate] = useState(null); + const [rank, setRank] = useState(null); + const [email, setEmail] = useState(null); - const [createDate, setCreateDate] = useState(null); - const [rank, setRank] = useState(null); - const [email, setEmail] = useState(null); + const [openBio, setOpenBio] = useState(false); + const [bioBanner, bannerState] = useState(false); + const [tempBio, setTempBio] = useState(""); + const [badges, setbadges] = useState(null); - const [openBio, setOpenBio] = useState(false); - const [bioBanner, bannerState] = useState(false); - const [tempBio, setTempBio] = useState(""); + const [selectedBanner, setSelectedBanner] = useState(null); + const [isBannerPopupOpen, setIsBannerPopupOpen] = useState(false); + const [banner, setBanner] = useState('https://images.unsplash.com/photo-1633259584604-afdc243122ea?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80'); - const [badges, setbadges] = useState(null); + const [selectedImage, setSelectedImage] = useState(null); + const [isPopupOpen, setIsPopupOpen] = useState(false); + const [pfp, setPfp] = useState(process.env.NEXT_PUBLIC_FRONTEND_URL + `ConfusedKana.png`); + const [isLoggedIn, setIsLoggedIn] = useState(null); - const [selectedBanner, setSelectedBanner] = useState(null); - const [isBannerPopupOpen, setIsBannerPopupOpen] = useState(false); - const [banner, setBanner] = useState('https://images.unsplash.com/photo-1633259584604-afdc243122ea?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1770&q=80'); + const handleImageChange = (event) => { + const file = event.target.files[0]; + setSelectedImage(file); + } - const [selectedImage, setSelectedImage] = useState(null); - const [isPopupOpen, setIsPopupOpen] = useState(false); - const [pfp, setPfp] = useState(process.env.NEXT_PUBLIC_FRONTEND_URL + `ConfusedKana.png`); - const [isLoggedIn, setIsLoggedIn] = useState(null); - const handleImageChange = (event) => { - const file = event.target.files[0]; - setSelectedImage(file); + const handleSaveChanges = async () => { + if (!selectedImage) { + console.log("No image selected"); + setIsPopupOpen(false) + return; } - const handleSaveChanges = async () => { - if (!selectedImage) { - console.log("No image selected"); - setIsPopupOpen(false) - return; + // upload to firebase storage + try { + const storage = getStorage(); + const metadata = { + contentType: 'image/jpeg', + }; + + + const storageRef = ref(storage, `${email}/pictures/pfp`); + const uploadTask = uploadBytesResumable(storageRef, selectedImage, metadata) + + + uploadTask.on('state_changed', + (snapshot) => { + // progress function + const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); + console.log('Upload is ' + progress + '% done'); + switch (snapshot.state) { + case 'paused': + console.log('Upload is paused'); + break; + case 'running': + console.log('Upload is running'); + break; + } + }, + (error) => { + switch (error.code) { + case 'storage/unauthorized': + console.log('User does not have permission to access the object'); + break; + case 'storage/canceled': + console.log('User canceled the upload'); + break; + case 'storage/unknown': + console.log('Unknown error occurred, inspect error.serverResponse'); + break; + } + }, + async () => { + const imageUrl = await getDownloadURL(uploadTask.snapshot.ref) + console.log(imageUrl) + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/updatePfp'; + const body = { imageUrl } + const response = await request(endPoint, "POST", body); + console.log("Here is the result: ", response) + if (response.success) { + console.log("profile picture uploaded successfully"); + } else { + console.log("Failed to upload profile picture"); + } + window.location.reload(); } + ); + setIsPopupOpen(false); - // upload to firebase storage - try { - const storage = getStorage(); - const metadata = { - contentType: 'image/jpeg', - }; + } catch (err) { + console.log(err); + console.log("An error occured while uploading profile picture"); + } + } - const storageRef = ref(storage, `${email}/pictures/pfp`); - const uploadTask = uploadBytesResumable(storageRef, selectedImage, metadata) + const handleBannerChange = (event) => { + const file = event.target.files[0]; + setSelectedBanner(file); + } - uploadTask.on('state_changed', - (snapshot) => { - // progress function - const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); - console.log('Upload is ' + progress + '% done'); - switch (snapshot.state) { - case 'paused': - console.log('Upload is paused'); - break; - case 'running': - console.log('Upload is running'); - break; - } - }, - (error) => { - switch (error.code) { - case 'storage/unauthorized': - console.log('User does not have permission to access the object'); - break; - case 'storage/canceled': - console.log('User canceled the upload'); - break; - case 'storage/unknown': - console.log('Unknown error occurred, inspect error.serverResponse'); - break; - } - }, - async () => { - const imageUrl = await getDownloadURL(uploadTask.snapshot.ref) - console.log(imageUrl) - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/updatePfp'; - const body = { imageUrl } - const response = await request(endPoint, "POST", body); - console.log("Here is the result: ", response) - if (response.success) { - console.log("profile picture uploaded successfully"); - } else { - console.log("Failed to upload profile picture"); - } - window.location.reload(); - } - ); - setIsPopupOpen(false); + const handleBannerSave = async () => { + if (!selectedBanner) { + console.log("No image selected"); + setIsBannerPopupOpen(false) + return; + } - } catch (err) { - console.log(err); - console.log("An error occured while uploading profile picture"); + // upload to firebase storage + try { + const storage = getStorage(); + const metadata = { + contentType: 'image/jpeg', + }; + + const storageRef = ref(storage, `${email}/pictures/banner`); + const uploadTask = uploadBytesResumable(storageRef, selectedBanner, metadata) + + + uploadTask.on('state_changed', + (snapshot) => { + // progress function + const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); + console.log('Upload is ' + progress + '% done'); + switch (snapshot.state) { + case 'paused': + console.log('Upload is paused'); + break; + case 'running': + console.log('Upload is running'); + break; + } + }, + (error) => { + switch (error.code) { + case 'storage/unauthorized': + console.log('User does not have permission to access the object'); + break; + case 'storage/canceled': + console.log('User canceled the upload'); + break; + case 'storage/unknown': + console.log('Unknown error occurred, inspect error.serverResponse'); + break; + } + }, + + async () => { + const imageUrl = await getDownloadURL(uploadTask.snapshot.ref) + console.log(imageUrl) + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/updateBanner'; + const body = { imageUrl }; + const result = await request(endPoint, "POST", body); + console.log(result) + if (result.success) { + console.log("Banner uploaded successfully"); + } else { + console.log("Failed to upload Banner"); + } + window.location.reload(); } + ); + setIsBannerPopupOpen(false); + + + } catch (err) { + console.log(err); + console.log("An error occured while uploading banner"); + } + } + + // Friend useEffect + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/friends/' + user + '/friendList'; + const result = await request(endPoint, "GET", null); + const isFriend = result.friends.some((friend) => friend == localStorage.getItem('username')); + setFriendedUser(isFriend); + const endPoint2 = process.env.NEXT_PUBLIC_API_URL + '/friends/' + 'sentRequests'; + const result2 = await request(endPoint2, "GET", null); + const isPending = result2.some((friend) => friend.recipient.username == user); + setPendingRequest(isPending); + } catch (err) { + invalidUser = true; + } + }; + fetchData(); + }, [user]); + + // check to see if user is logged in + useEffect(() => { + try { + fetch(`${process.env.NEXT_PUBLIC_API_URL}/account`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: 'Bearer ' + localStorage.getItem('idToken'), + }, + }) + .then((response) => response.json()) + .then((data) => { + if (data.error || !data.username) { + console.log("debug| user not logged in :("); + setIsLoggedIn(false); + } else { + setIsLoggedIn(true); + } + }) + .catch((err) => { + console.log(err); + console.log("debug| user not logged in :(") + setIsLoggedIn(false); + }) + } catch { } + }, []); - const handleBannerChange = (event) => { - const file = event.target.files[0]; - setSelectedBanner(file); + // Follower useEffect + useEffect(() => { + if (!user) { + return; } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/followers/' + user + '/followers'; + const result = await request(endPoint, "GET", null); + const isFollower = result.followers.some(followers => followers.username == localStorage.getItem('username')); - const handleBannerSave = async () => { - if (!selectedBanner) { - console.log("No image selected"); - setIsBannerPopupOpen(false) - return; - } + setFollowerCount(result.followers.length); + setFollowedUser(isFollower); - // upload to firebase storage - try { - const storage = getStorage(); - const metadata = { - contentType: 'image/jpeg', - }; - - const storageRef = ref(storage, `${email}/pictures/banner`); - const uploadTask = uploadBytesResumable(storageRef, selectedBanner, metadata) - - - uploadTask.on('state_changed', - (snapshot) => { - // progress function - const progress = Math.round((snapshot.bytesTransferred / snapshot.totalBytes) * 100); - console.log('Upload is ' + progress + '% done'); - switch (snapshot.state) { - case 'paused': - console.log('Upload is paused'); - break; - case 'running': - console.log('Upload is running'); - break; - } - }, - (error) => { - switch (error.code) { - case 'storage/unauthorized': - console.log('User does not have permission to access the object'); - break; - case 'storage/canceled': - console.log('User canceled the upload'); - break; - case 'storage/unknown': - console.log('Unknown error occurred, inspect error.serverResponse'); - break; - } - }, - - async () => { - const imageUrl = await getDownloadURL(uploadTask.snapshot.ref) - console.log(imageUrl) - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/updateBanner'; - const body = { imageUrl }; - const result = await request(endPoint, "POST", body); - console.log(result) - if (result.success) { - console.log("Banner uploaded successfully"); - } else { - console.log("Failed to upload Banner"); - } - window.location.reload(); - } - ); - setIsBannerPopupOpen(false); + } catch (err) { + invalidUser = true; + } + }; + const fetchFollowing = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/followers/' + user + '/following'; + const result = await request(endPoint, "GET", null); + console.log("Following " + result) - } catch (err) { - console.log(err); - console.log("An error occured while uploading banner"); - } - } + setFollowerCount(result.following.length); - // Friend useEffect - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/friends/' + user + '/friendList'; - const result = await request(endPoint, "GET", null); - const isFriend = result.friends.some((friend) => friend == localStorage.getItem('username')); - setFriendedUser(isFriend); - const endPoint2 = process.env.NEXT_PUBLIC_API_URL + '/friends/' + 'sentRequests'; - const result2 = await request(endPoint2, "GET", null); - const isPending = result2.some((friend) => friend.recipient.username == user); - setPendingRequest(isPending); - } catch (err) { - invalidUser = true; - } - }; - fetchData(); - }, [user]); - - // check to see if user is logged in - useEffect(() => { - try { - fetch(`${process.env.NEXT_PUBLIC_API_URL}/account`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - Authorization: 'Bearer ' + localStorage.getItem('idToken'), - }, - }) - .then((response) => response.json()) - .then((data) => { - if (data.error || !data.username) { - console.log("debug| user not logged in :("); - setIsLoggedIn(false); - } else { - setIsLoggedIn(true); - } - }) - .catch((err) => { - console.log(err); - console.log("debug| user not logged in :(") - setIsLoggedIn(false); - }) - } catch { - } - }, []); - - // Follower useEffect - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/followers/' + user + '/followers'; - const result = await request(endPoint, "GET", null); + } catch (err) { + invalidUser = true; + } + }; + fetchData(); + fetchFollowing(); + }, [user]); - const isFollower = result.followers.some(followers => followers.username == localStorage.getItem('username')); - setFollowerCount(result.followers.length); - setFollowedUser(isFollower); + // Challenge useEffect + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/completedChallenges'; + const result = await request(endPoint, "GET", null); + setCompletedChallenges(result); + console.log("Completed Challenges Length: " + result.completedBeginnerChallenges.length) + } catch (err) { + console.log(err); + } + } + fetchData(); + }, [user]) - } catch (err) { - invalidUser = true; - } - }; - const fetchFollowing = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/followers/' + user + '/following'; - const result = await request(endPoint, "GET", null); - console.log("Following " + result) + // Created Challenge useEffect + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const challengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/challenges'; + const challengeResult = await request(challengeEndPoint, "GET", null); + if (!challengeResult) { + setCreatedChallenges(null); + return; + } + const publicChallenges = challengeResult.filter(challenge => challenge.private === false); + publicChallenges.length !== 0 ? setCreatedChallenges(publicChallenges) : setCreatedChallenges(null); + } catch (err) { + console.log(err); + } + } + fetchData(); + }, [user]); - setFollowerCount(result.following.length); + // Pinned Challenge useEffect + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const pinnedChallengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes'; + const pinnedChallengeResult = await request(pinnedChallengeEndPoint, "GET", null); + setPinnedChallenges(pinnedChallengeResult?.length == 0 ? null : pinnedChallengeResult); + console.log(pinnedChallengeResult) + console.log("CHALLENGE INFO" + publicChallenges[0]) + } catch (err) { + console.log(err); + } + } + fetchData(); + }, [user]); - } catch (err) { - invalidUser = true; - } - }; - fetchData(); - fetchFollowing(); - }, [user]); + // Get and store user data + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user; + const result = await request(endPoint, "GET", null); - // Challenge useEffect - useEffect(() => { - if (!user) { - return; + if (!result.username) { + // return window.location.href = '/404'; } - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/completedChallenges'; - const result = await request(endPoint, "GET", null); - setCompletedChallenges(result); - console.log("Completed Challenges Length: " + result.completedBeginnerChallenges.length) - } catch (err) { - console.log(err); - } + setUsername(result.username); + setCreateDate(result.createdAt); + setRank(result.leaderboardNum); + setEmail(result.email); + setUserData(result); + console.log("USERDATA: " + result) + result.username == localStorage.getItem('username') ? setOwnUser(true) : setOwnUser(false); + result.location === '????' ? setLocation(null) : setLocation(result.location); + result.bio ? setBio(result.bio) : setBio(null); + result.bio ? setTempBio(result.bio) : setTempBio(""); + + + + // Fetch Badges + if (result.badgesNum !== 0 || result.badgesNum !== null) { + const badgeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/badges'; + const badgeResult = await request(badgeEndPoint, "GET", null); + console.log('BADGES: ' + badgeResult) + badgeResult.length !== 0 ? setbadges(badgeResult) : setbadges(null); } - fetchData(); - }, [user]) + } catch (err) { + invalidUser = true; + console.log("this happened") + } + }; + fetchData(); + }, [user]); - // Created Challenge useEffect - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - const challengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/challenges'; - const challengeResult = await request(challengeEndPoint, "GET", null); - if (!challengeResult) { - setCreatedChallenges(null); - return; - } - const publicChallenges = challengeResult.filter(challenge => challenge.private === false); - publicChallenges.length !== 0 ? setCreatedChallenges(publicChallenges) : setCreatedChallenges(null); - } catch (err) { - console.log(err); - } + // get user's profile picture + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/pfp'; + const result = await request(endPoint, "GET", null); + console.log(result) + if (result) { + setPfp(result) + } else { + setPfp(`https://robohash.org/${localStorage.getItem('username')}.png?set=set1&size=150x150`) } - fetchData(); - }, [user]); + } catch (err) { + console.log('failed to get profile picture') + } + }; + fetchData(); + }, [user]); - // Pinned Challenge useEffect - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - const pinnedChallengeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/likes'; - const pinnedChallengeResult = await request(pinnedChallengeEndPoint, "GET", null); - pinnedChallengeResult.length !== 0 ? setPinnedChallenges(pinnedChallengeResult) : setPinnedChallenges(null); - console.log("CHALLENGE INFO" + publicChallenges[0]) - } catch (err) { - console.log(err); - } - } - fetchData(); - }, [user]); - // Get and store user data - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user; - const result = await request(endPoint, "GET", null); - - if (!result.username) { - // return window.location.href = '/404'; - } - setUsername(result.username); - setCreateDate(result.createdAt); - setRank(result.leaderboardNum); - setEmail(result.email); - setUserData(result); - console.log("USERDATA: " + result) - result.username == localStorage.getItem('username') ? setOwnUser(true) : setOwnUser(false); - result.location === '????' ? setLocation(null) : setLocation(result.location); - result.bio ? setBio(result.bio) : setBio(null); - result.bio ? setTempBio(result.bio) : setTempBio(""); - - - - // Fetch Badges - if (result.badgesNum !== 0 || result.badgesNum !== null) { - const badgeEndPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/badges'; - const badgeResult = await request(badgeEndPoint, "GET", null); - console.log('BADGES: ' + badgeResult) - badgeResult.length !== 0 ? setbadges(badgeResult) : setbadges(null); - } - - } catch (err) { - invalidUser = true; - console.log("this happened") - } - }; - fetchData(); - }, [user]); - - - // get user's profile picture - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/pfp'; - const result = await request(endPoint, "GET", null); - console.log(result) - if (result) { - setPfp(result) - } else { - setPfp(`https://robohash.org/${localStorage.getItem('username')}.png?set=set1&size=150x150`) - } - - } catch (err) { - console.log('failed to get profile picture') - } - }; - fetchData(); - }, [user]); - - - // get user's banner - useEffect(() => { - if (!user) { - return; - } - const fetchData = async () => { - try { - const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/banner'; - const result = await request(endPoint, "GET", null); - console.log(result) - if (result) { - if (result !== "https://images.unsplash.com/photo-1500964757637-c85e8a162699?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3903&q=80") { - setBanner(result) + // get user's banner + useEffect(() => { + if (!user) { + return; + } + const fetchData = async () => { + try { + const endPoint = process.env.NEXT_PUBLIC_API_URL + '/users/' + user + '/banner'; + const result = await request(endPoint, "GET", null); + console.log(result) + if (result) { + if (result !== "https://images.unsplash.com/photo-1500964757637-c85e8a162699?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3903&q=80") { + setBanner(result) - } - - } else { - setBanner('https://images.unsplash.com/photo-1500964757637-c85e8a162699?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3903&q=80') - } + } - } catch (err) { - console.log('failed to get banner') - } - }; - fetchData(); - }, [user]); + } else { + setBanner('https://images.unsplash.com/photo-1500964757637-c85e8a162699?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=3903&q=80') + } + } catch (err) { + console.log('failed to get banner') + } + }; + fetchData(); + }, [user]); - function openTheBio() { - setOpenBio(true); - } + function openTheBio() { + setOpenBio(true); + } - function closeBannerAndBio() { - bannerState(false); - setOpenBio(false); - } + function closeBannerAndBio() { + bannerState(false); + setOpenBio(false); + } - const openBanner = (event) => { - bannerState(true); - setTempBio(event.target.value); - }; + const openBanner = (event) => { + bannerState(true); + setTempBio(event.target.value); + }; - async function saveBio() { - setBio(document.getElementById('bio').value); - closeBannerAndBio(); - const body = { - bio: document.getElementById('bio').value - } - const data = await request(`${process.env.NEXT_PUBLIC_API_URL}/account`, "PUT", body); - if (!data) { - console.log("Failed to save the bio"); - } - setBio(body.bio); - window.location.reload(); + + async function saveBio() { + setBio(document.getElementById('bio').value); + closeBannerAndBio(); + const body = { + bio: document.getElementById('bio').value + } + const data = await request(`${process.env.NEXT_PUBLIC_API_URL}/account`, "PUT", body); + if (!data) { + console.log("Failed to save the bio"); } + setBio(body.bio); + window.location.reload(); + } - const followUser = async () => { - const endPoint = process.env.NEXT_PUBLIC_API_URL + `/followers/${user}/follow`; - const result = await request(endPoint, "POST", {}); - if (result) { - setFollowerCount(prevCount => prevCount + 1); - setFollowedUser(true); - } - console.log(result); + const followUser = async () => { + const endPoint = process.env.NEXT_PUBLIC_API_URL + `/followers/${user}/follow`; + const result = await request(endPoint, "POST", {}); + if (result) { + setFollowerCount(prevCount => prevCount + 1); + setFollowedUser(true); } + console.log(result); + } - const unfollowUser = async () => { - const endPoint = process.env.NEXT_PUBLIC_API_URL + `/followers/${user}/unfollow`; - const result = await request(endPoint, "DELETE", null); - if (result) { - setFollowerCount(prevCount => prevCount - 1); - setFollowedUser(false); - } - console.log(result); + const unfollowUser = async () => { + const endPoint = process.env.NEXT_PUBLIC_API_URL + `/followers/${user}/unfollow`; + const result = await request(endPoint, "DELETE", null); + if (result) { + setFollowerCount(prevCount => prevCount - 1); + setFollowedUser(false); } + console.log(result); + } - // const friendUser = async () => { - // const endPoint = process.env.NEXT_PUBLIC_API_URL + `/friends/${username}/sendRequest`; - // const result = await request(endPoint, "POST", {}); - // setPendingRequest(true); - // console.log(result); - // } + // const friendUser = async () => { + // const endPoint = process.env.NEXT_PUBLIC_API_URL + `/friends/${username}/sendRequest`; + // const result = await request(endPoint, "POST", {}); + // setPendingRequest(true); + // console.log(result); + // } - // const unFriendUser = async () => { - // const endPoint = process.env.NEXT_PUBLIC_API_URL + `/friends/${username}/unadd`; - // const result = await request(endPoint, "DELETE", null); - // console.log(result); - // setFriendedUser(false); - // } + // const unFriendUser = async () => { + // const endPoint = process.env.NEXT_PUBLIC_API_URL + `/friends/${username}/unadd`; + // const result = await request(endPoint, "DELETE", null); + // console.log(result); + // setFriendedUser(false); + // } - const handlePopupOpen = () => { - setIsPopupOpen(true); - } + const handlePopupOpen = () => { + setIsPopupOpen(true); + } - const handlePopupClose = () => { - setIsPopupOpen(false); - } + const handlePopupClose = () => { + setIsPopupOpen(false); + } - const handleBannerPopupOpen = () => { - setIsBannerPopupOpen(true); - } + const handleBannerPopupOpen = () => { + setIsBannerPopupOpen(true); + } - const handleBannerPopupClose = () => { - setIsBannerPopupOpen(false); - } + const handleBannerPopupClose = () => { + setIsBannerPopupOpen(false); + } + + const handleClick = () => { + + } - const handleClick = () => { + const getActivity = async () => { + try { + console.log("ACTIVITY FLAG : ") + const url = `${process.env.NEXT_PUBLIC_API_URL}/activity/${userData.username}`; + const response = await request(url, 'GET'); + const data = await response; + if (data.success) { + let arr = data.body; + setActivity(arr); + } + console.log(data); + } catch (err) { + console.log(err); } + }; - const getActivity = async () => { - try { - console.log("ACTIVITY FLAG : ") - - const url = `${process.env.NEXT_PUBLIC_API_URL}/activity/${userData.username}`; - const response = await request(url, 'GET'); - const data = await response; - if (data.success) { - let arr = data.body; - setActivity(arr); - } - console.log(data); - } catch (err) { - console.log(err); + useEffect(() => { + if (userData) { + getActivity(); + } + }, [userData]); + + + return ( + <> + + {username}'s Profile - CTFGuide + + + + +
    + {/* PROFILE PICTURE POP-UP */} + {ownUser && + + handlePopupClose()}> + + + +
    { + handlePopupClose() + localStorage.setItem("22-18-update", false) + }} + className="fixed inset-0 bg-gray-900 bg-opacity-75 transition-opacity" /> + +
    + +
    +
    +
    +

    Change Profile Picture

    +
    +
    +
    + +

    + Current Profile Picture +

    +
    +
    + {/* INPUT BOX */} +
    + +
    + +
    +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    } - }; - useEffect(() => { - if (userData) { - getActivity(); - } - }, [userData]); - - - return ( - <> - - {username}'s Profile - CTFGuide - - - - -
    - {/* PROFILE PICTURE POP-UP */} - {ownUser && - - handlePopupClose()}> - - - -
    { - handlePopupClose() - localStorage.setItem("22-18-update", false) - }} - className="fixed inset-0 bg-gray-900 bg-opacity-75 transition-opacity" /> - -
    - + handleBannerPopupClose()}> + + + +
    { + handleBannerPopupClose() + localStorage.setItem("22-18-update", false) + }} + className="fixed inset-0 bg-gray-900 bg-opacity-75 transition-opacity" /> + +
    + +
    +
    +

    Change Banner

    +
    + {/* CURRENT BANNER */} +
    +
    +
    +

    + Current Banner +

    +
    + {/* INPUT BOX */} +
    +
    - - } - - {/* BANNER POP-UP */} - {ownUser && - - handleBannerPopupClose()}> - - - -
    { - handleBannerPopupClose() - localStorage.setItem("22-18-update", false) - }} - className="fixed inset-0 bg-gray-900 bg-opacity-75 transition-opacity" /> - -
    - +

    + New Banner +

    +
    + ) : ( +
    + -
    -
    -

    Change Banner

    -
    - {/* CURRENT BANNER */} -
    -
    -
    -

    - Current Banner -

    -
    - {/* INPUT BOX */} -
    - -
    - -
    -
    -
    - -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - } - - - {/* BANNER */} -
    -
    -
    -
    - {ownUser && - - } + + +

    Click here or Drag an Image!

    +
    + )} + +
    + +
    +
    +
    + +
    +
    +
    +
    -
    - {/* NAME CARD */} -
    - -
    -
    - {/* Profile Picture */} -
    - {(username && ( - handlePopupOpen()} - className="h-40 w-40 rounded-full hover:bg-[#212121] sm:h-30 sm:w-30" - src={pfp} - alt="" - /> - )) || ( - - )} -
    +
    + +
    +
    +
    + } + -
    -
    -
    - {/* TOP LINE */} -
    -

    - {username || ( - - )} -

    - {/*

    + {/* BANNER */} +
    +
    +
    +
    + {ownUser && + + } +
    +
    +
    + {/* NAME CARD */} +
    + +
    +
    + {/* Profile Picture */} +
    + {(username && ( + handlePopupOpen()} + className="h-40 w-40 rounded-full hover:bg-[#212121] sm:h-30 sm:w-30" + src={pfp} + alt="" + /> + )) || ( + + )} +
    + +
    +
    +
    + {/* TOP LINE */} +
    +

    + {username || ( + + )} +

    + {/*

    #{rank}

    */} - {!ownUser && (!followedUser ? ( - - ) : ( - - ))} - -
    - - {/* BOTTOM LINE */} -
    - {location && -
    -

    - {' '} - {location} -

    -
    - } - {/*
    + {!ownUser && (!followedUser ? ( + + ) : ( + + ))} + +
    + + {/* BOTTOM LINE */} +
    + {location && +
    +

    + {' '} + {location} +

    +
    + } + {/*

    {' '} 1.2k

    */} -
    +
    -

    - {/* {' '} +

    + {/* {' '} ADMIN */} -

    - +

    -
    -
    -
    -
    -
    -
    -
    - {/* Social Stats */} -
    -
    -

    - Followers: -

    -

    - {followerCount} -

    -
    - -
    -

    - Following: -

    -

    - {followingCount} -

    -
    -
    -
    -
    -
    +
    +
    +

    +
    +
    + {/* Social Stats */} +
    +
    +

    + Followers: +

    +

    + {followerCount} +

    +
    - {/* ACTUAL CONTENT AREA */} -
    -
    - {/* LEFT SIDE CONTENT */} -
    -
    - -
    -

    - Streak Chart -

    -
    - - - {/* STREAK CHART */} -
    -
    - {['', '', '', '', ''].map((e, idx) => { - idx = idx * 7; - return ( -
    - {['', '', '', '', '', '', ''].map((e, j) => ( -
    - ))} -
    - ); - })} -
    -
    - - -
    -
    +
    +

    + Following: +

    +

    + {followingCount} +

    +
    +
    +
    +
    + +
    +
    +
    + + {/* ACTUAL CONTENT AREA */} +
    +
    + {/* LEFT SIDE CONTENT */} +
    +
    + +
    +

    + Streak Chart +

    +
    - {/* MIDDLE */} -
    -
    -
    -
    -

    - Bio -

    -
    - {ownUser ? ((!openBio && ownUser) && -
    - -
    - ) || ( -
    - -
    - ) : (
    )} -
    -
    -
    - {((openBio && ownUser) && -
    - -
    - ) || ( -
    - - {bio === null || bio === "" ? "No Bio Set..." : bio} - -
    - )} -
    -
    -
    -
    + {/* STREAK CHART */} +
    +
    + {['', '', '', '', ''].map((e, idx) => { + idx = idx * 7; + return ( +
    + {['', '', '', '', '', '', ''].map((e, j) => ( +
    -
    -
    -

    - Challenge Completion -

    -
    - {completedChallenges && - - } -
    -
    -
    + className={`${shades[activity[idx + j]]} mt-1`} + >
    + ))}
    + ); + })} +
    +
    +
    +
    + + {/* MIDDLE */} +
    +
    +
    +
    +

    + Bio +

    +
    + {ownUser ? ((!openBio && ownUser) && +
    +
    - {/* BADGE */} -
    -
    - {/* Badge Content */} -
    -

    Badges

    -
    - {badges && badges.length > 0 ? ( - badges.map((badge) => ( - - )) - ) : ( -
    - {ownUser && } - -

    No Badges Yet...

    -
    - )} -
    -
    -
    -
    - {/* Created Challenges */} -
    - {/* CHALLENGE */} -
    -
    -

    Created Challenges

    -
    - {(createdChallenges && createdChallenges.map((challenge) => ( - - ))) || ( -
    - {ownUser && - - } - - -

    - No Challenges Created Yet... -

    - -
    - )} -
    -
    -
    - -
    - - {/* Pinned Challenges */} - < div > - {/* CHALLENGE */} -
    -
    -

    Liked Challenges

    -
    - {pinnedChallenges && Array.isArray(pinnedChallenges) && pinnedChallenges.map((challenge) => ( - - )) - || ( -
    - {ownUser && - - } - - -

    - No Challenges Liked Yet... -

    - -
    - )} -
    -
    -
    -
    - -
    - {/* Join Date */} -
    - {/* Badge Content */} -
    - {createDate && ( -

    CTFGuide Member since {createDate.slice(0, 10)}

    - )} -
    + ) || ( +
    + +
    + ) : (
    )} +
    +
    +
    + {((openBio && ownUser) && +
    + +
    + ) || ( +
    + + {bio === null || bio === "" ? "No Bio Set..." : bio} +
    -
    -
    + )} +
    +
    -
    -
    - { - bioBanner && ( +
    +
    + + {/* RIGHT SIDE CONTENT */} +
    +
    +
    +

    + Challenge Completion +

    +
    + {completedChallenges && + + } +
    +
    +
    +
    + + +
+ {/* BADGE */} +
+
+ {/* Badge Content */} +
+

Badges

+
+ {badges && badges.length > 0 ? ( + badges.map((badge) => ( + + )) + ) : ( - ) - } - - ); + )} +
+
+
+
+ {/* Created Challenges */} +
+ {/* CHALLENGE */} +
+
+

Created Challenges

+
+ {(createdChallenges && createdChallenges.map((challenge) => ( + + ))) || ( +
+ {ownUser && + + } + + +

+ No Challenges Created Yet... +

+ +
+ )} +
+
+
+ +
+ + {/* Pinned Challenges */} + < div > + {/* CHALLENGE */} +
+
+

Liked Challenges

+
+ {pinnedChallenges && Array.isArray(pinnedChallenges) && pinnedChallenges.map((challenge) => ( + + )) + || ( +
+ {ownUser && + + } + + +

+ No Challenges Liked Yet... +

+ +
+ )} +
+
+
+
+ +
+ {/* Join Date */} +
+ {/* Badge Content */} +
+ {createDate && ( +

CTFGuide Member since {createDate.slice(0, 10)}

+ )} +
+
+
+
+ + +