From b316e52fa05bb86f90568288e461bedfd4ed840f Mon Sep 17 00:00:00 2001 From: Ahmadkhattak1 Date: Wed, 13 May 2026 11:13:45 +0500 Subject: [PATCH 1/2] Bounty: dead code cleanup and formatting --- src/App.tsx | 47 +-- src/common/components/Navbar.tsx | 15 +- src/common/hooks/useBodyScroll.ts | 8 +- src/common/hooks/useFetch.ts | 4 - src/common/utils.ts | 93 +++-- .../Onboarding/Authentication/index.tsx | 22 +- src/pages/profile/Onboarding/index.tsx | 2 +- src/pages/profile/components/DataQuality.tsx | 364 ++++++++++-------- .../profile/components/LeaderBoardBanner.tsx | 65 ++-- src/pages/profile/components/Leaderboard.tsx | 120 +++--- .../profile/components/LeaderboardRow.tsx | 104 +++-- src/pages/profile/components/MyData.tsx | 95 ++--- .../profile/components/PointsAndData.tsx | 27 +- src/pages/profile/components/Privacy.tsx | 39 +- src/pages/profile/components/ReferalTable.tsx | 38 +- src/pages/profile/components/Referrals.tsx | 118 +++--- src/pages/profile/components/Snapshot.tsx | 94 +++-- .../mileStones/ActionableMileStone.tsx | 35 +- .../mileStones/CircularProgress.tsx | 20 +- .../components/mileStones/Milestones.tsx | 52 ++- .../mileStones/ProgressMilestone.tsx | 26 +- src/pages/profile/index.tsx | 250 +++++++----- .../Onboarding/Authentication/index.tsx | 22 +- .../signup/Onboarding/Common/MediaBanner.tsx | 13 +- .../Onboarding/Particle/LoginButton.tsx | 49 +-- src/pages/signup/Onboarding/index.tsx | 2 +- src/pages/signup/index.tsx | 20 +- tailwind.config.js | 28 +- 28 files changed, 908 insertions(+), 864 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index bc1de80..8966205 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,12 +5,11 @@ import SignUp from './pages/signup' import { UserData } from './common/constants/SignupData' import Profile from './pages/profile' - import { MyData } from './pages/profile/components/MyData' import useFetch from './common/hooks/useFetch' function App(): ReactElement { const emptyStringArray: string[] = [] - const [isLoading, setIsLoading] = useState(true); + const [isLoading, setIsLoading] = useState(true) const [isLoggedIn, setIsLoggedIn] = useState(false) const [user, setUser] = useState({ about: '', @@ -30,13 +29,13 @@ function App(): ReactElement { token: '' }) const GET_USER_API = 'user/get-user/{address}' - const { fetchData: fetchUser, data: userDataFromDB } = useFetch() + const { fetchData: fetchUser } = useFetch() useEffect(() => { - const token = localStorage.getItem('token'); - setIsLoggedIn(!!token); // Update isLoggedIn based on token presence - setIsLoading(false); // Mark loading as complete - }, []); + const token = localStorage.getItem('token') + setIsLoggedIn(!!token) // Update isLoggedIn based on token presence + setIsLoading(false) // Mark loading as complete + }, []) function makeUserUpdationUrl(address_string: string): string { const address = localStorage.getItem('address') || '' @@ -56,12 +55,16 @@ function App(): ReactElement { } } }) - setIsLoggedIn(!!token); // Set isLoggedIn based on token presence - setIsLoading(false); // Indicate loading is complete + setIsLoggedIn(!!token) // Set isLoggedIn based on token presence + setIsLoading(false) // Indicate loading is complete }, []) // Empty dependency array: run only on initial render if (isLoading) { - return
; + return ( +
+
+
+ ) } return ( @@ -89,35 +92,19 @@ function App(): ReactElement { ) } /> - - } - /> + } /> } /> - } - /> + } /> - {isLoggedIn && } />} + {isLoggedIn && } />} {isLoggedIn ? ( - } - /> + } /> ) : ( } /> )} - ) } diff --git a/src/common/components/Navbar.tsx b/src/common/components/Navbar.tsx index 04213ed..e5da6d1 100644 --- a/src/common/components/Navbar.tsx +++ b/src/common/components/Navbar.tsx @@ -1,4 +1,4 @@ -import { useLocation, useNavigate } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom' import { ReactComponent as Logo } from '../../assets/images/nameLogo.svg' export enum PAGE_NAMES { @@ -7,18 +7,19 @@ export enum PAGE_NAMES { } interface NavbarProps { - userAddress: string; + userAddress: string page: PAGE_NAMES } const Navbar = ({ userAddress, page }: NavbarProps) => { - const navigate = useNavigate(); + const navigate = useNavigate() const getButtonClasses = (isActive: boolean) => - `py-2 px-4 rounded-lg font-medium transition duration-300 ${isActive - ? 'bg-gray-800 text-white' - : 'bg-[#f8f9fc] text-gray-700 hover:bg-gray-700 hover:text-white' - }`; + `py-2 px-4 rounded-lg font-medium transition duration-300 ${ + isActive + ? 'bg-gray-800 text-white' + : 'bg-[#f8f9fc] text-gray-700 hover:bg-gray-700 hover:text-white' + }` return (
diff --git a/src/common/hooks/useBodyScroll.ts b/src/common/hooks/useBodyScroll.ts index 77b705e..2f1e426 100644 --- a/src/common/hooks/useBodyScroll.ts +++ b/src/common/hooks/useBodyScroll.ts @@ -1,11 +1,13 @@ -import React, { useEffect, useRef } from 'react' +import { useEffect, useRef } from 'react' const useBodyScroll = (isOpen: boolean) => { - const bodyRef = useRef(document.querySelector('body')) + const bodyRef = useRef(document.body) useEffect(() => { const updatePageScroll = () => { - bodyRef.current!.style.overflow = isOpen ? 'hidden' : '' + if (bodyRef.current) { + bodyRef.current.style.overflow = isOpen ? 'hidden' : '' + } } updatePageScroll() diff --git a/src/common/hooks/useFetch.ts b/src/common/hooks/useFetch.ts index 641cd5f..ee04029 100644 --- a/src/common/hooks/useFetch.ts +++ b/src/common/hooks/useFetch.ts @@ -1,6 +1,5 @@ import { Method } from 'axios' import { useEffect, useState } from 'react' -import { useNavigate } from 'react-router-dom' type Options = { method?: Method @@ -35,9 +34,6 @@ export enum FetchStatus { } function useFetch(url?: string, options?: Options): FetchResponse { - - const navigate = useNavigate() - const [data, setData] = useState(null) const [status, setStatus] = useState(FetchStatus.IDLE) const [error, setError] = useState(null) diff --git a/src/common/utils.ts b/src/common/utils.ts index f8eea03..576afe0 100644 --- a/src/common/utils.ts +++ b/src/common/utils.ts @@ -20,29 +20,32 @@ export function replaceSlugInURL(url: string, slug?: string) { } // Constant for milliseconds in a day -const MILLISECONDS_IN_A_DAY = 1000 * 3600 * 24; +const MILLISECONDS_IN_A_DAY = 1000 * 3600 * 24 -export function getDaysAgo(date: string | number, currentTimestamp: number = Date.now()): string { - const givenDate = new Date(date); - const differenceInTime = currentTimestamp - givenDate.getTime(); // date is already a timestamp - const differenceInDays = Math.floor(differenceInTime / MILLISECONDS_IN_A_DAY); +export function getDaysAgo( + date: string | number, + currentTimestamp: number = Date.now() +): string { + const givenDate = new Date(date) + const differenceInTime = currentTimestamp - givenDate.getTime() // date is already a timestamp + const differenceInDays = Math.floor(differenceInTime / MILLISECONDS_IN_A_DAY) if (differenceInDays === 0) { - return 'Today'; + return 'Today' } else if (differenceInDays === 1) { - return '1 day ago'; + return '1 day ago' } else if (differenceInDays <= 30) { - return `${differenceInDays} days ago`; + return `${differenceInDays} days ago` } else { return givenDate.toLocaleDateString('default', { month: 'long', day: 'numeric', - year: 'numeric', - }); + year: 'numeric' + }) } } -export function getDateAndMonth (date: number | undefined) { +export function getDateAndMonth(date: number | undefined) { if (date) { const givenDate = new Date(date * 1000) return `${givenDate.getDate()} ${givenDate.toLocaleString('default', { @@ -52,54 +55,46 @@ export function getDateAndMonth (date: number | undefined) { } export const extractThumbNailURL = (videoURL: string) => { - let videoId: string | undefined; - if (videoURL.includes("youtu.be")) { - // Handle the shortened youtu.be URLs - videoId = videoURL.split("youtu.be/")[1]?.split("?")[0]; - } else if (videoURL.includes("youtube.com")) { - // Handle the standard youtube.com URLs - videoId = videoURL.split("v=")[1]?.split("&")[0]; - } - const thumbUrl = videoId ? `https://img.youtube.com/vi/${videoId}/hqdefault.jpg` : ''; - return thumbUrl; -} - -// Helper function to extract the video ID from a YouTube URL -const extractVideoId = (url: string): string | undefined => { - let videoId: string | undefined; - - if (url.includes("youtu.be")) { - videoId = url.split("youtu.be/")[1]?.split("?")[0]; - } else if (url.includes("youtube.com/watch")) { - videoId = url.split("v=")[1]?.split("&")[0]; + let videoId: string | undefined + if (videoURL.includes('youtu.be')) { + // Handle the shortened youtu.be URLs + videoId = videoURL.split('youtu.be/')[1]?.split('?')[0] + } else if (videoURL.includes('youtube.com')) { + // Handle the standard youtube.com URLs + videoId = videoURL.split('v=')[1]?.split('&')[0] } - - return videoId; -}; + const thumbUrl = videoId + ? `https://img.youtube.com/vi/${videoId}/hqdefault.jpg` + : '' + return thumbUrl +} export function parseUrl(url: string): string { try { // Ensure the URL starts with http:// or https:// - const formattedUrl = url.startsWith('http://') || url.startsWith('https://') ? url : `http://${url}`; + const formattedUrl = + url.startsWith('http://') || url.startsWith('https://') + ? url + : `http://${url}` // Parse the URL - const { hostname } = new URL(formattedUrl); - const hostParts = hostname.split('.'); - const n = hostParts.length; + const { hostname } = new URL(formattedUrl) + const hostParts = hostname.split('.') + const n = hostParts.length // Determine the domain - if (n < 2) return hostname; // If there are less than 2 parts, return the hostname as is + if (n < 2) return hostname // If there are less than 2 parts, return the hostname as is return n === 4 || (n === 3 && hostParts[n - 2].length <= 3) ? `${hostParts[n - 3]}.${hostParts[n - 2]}.${hostParts[n - 1]}` - : `${hostParts[n - 2]}.${hostParts[n - 1]}`; + : `${hostParts[n - 2]}.${hostParts[n - 1]}` } catch (error) { - console.error('Invalid URL:', url, error); - return ''; // Return an empty string or handle as needed + console.error('Invalid URL:', url, error) + return '' // Return an empty string or handle as needed } } -export function formatDate (date: number): string { +export function formatDate(date: number): string { const formattedDate = new Date(date) // Convert epoch to milliseconds const day = String(formattedDate.getDate()).padStart(2, '0') // Ensure two digits for day @@ -112,18 +107,18 @@ export function formatDate (date: number): string { // text = '1234567890', maxLength = 8 => output: '12...890' export function truncateText(text: string, maxLength: number) { - const textLength = text.length; + const textLength = text.length if (textLength > maxLength) { // Calculate the number of characters to show from the start - const charsToShowFromStart = maxLength - 8; + const charsToShowFromStart = maxLength - 8 // Get the start and end parts of the string - const startPart = text.substring(0, charsToShowFromStart); - const endPart = text.substring(textLength - 5); + const startPart = text.substring(0, charsToShowFromStart) + const endPart = text.substring(textLength - 5) - return `${startPart}...${endPart}`; + return `${startPart}...${endPart}` } - return text; + return text } diff --git a/src/pages/profile/Onboarding/Authentication/index.tsx b/src/pages/profile/Onboarding/Authentication/index.tsx index ceef2b9..df56d78 100644 --- a/src/pages/profile/Onboarding/Authentication/index.tsx +++ b/src/pages/profile/Onboarding/Authentication/index.tsx @@ -3,8 +3,6 @@ import { ReactComponent as Kleo } from '../../../../assets/images/kleoLogo.svg' import { ReactComponent as Tick } from '../../../../assets/images/check.svg' import { ReactComponent as AlertIcon } from '../../../../assets/images/alert.svg' import { useNavigate } from 'react-router-dom' -import { UserData } from '../../../../common/constants/SignupData' -import useFetch from '../../../../common/hooks/useFetch' import Alert from '../../../../common/components/Alerts' enum PluginState { @@ -13,14 +11,11 @@ enum PluginState { INSTALLED } -export default function Onboarding({ handleLogin, user, setUser }: any) { +export default function Onboarding() { const [pluginState, setPluginState] = useState(PluginState.CHECKING) const [login, setLogin] = useState(false) const navigate = useNavigate() - const { fetchData: fetchCreateAndFetchUserData, data: userFromDB } = - useFetch() - useEffect(() => { if (pluginState === PluginState.CHECKING) { setTimeout(() => { @@ -63,9 +58,11 @@ export default function Onboarding({ handleLogin, user, setUser }: any) { target="_blank" > VANA DLP - aimed + {' '} + aimed
- at using chrome extension to help you own a piece of AI models. + at using chrome extension to help you own a piece of AI + models.

@@ -128,10 +125,11 @@ export default function Onboarding({ handleLogin, user, setUser }: any) { {/* Sign In button - disabled if plugin is not installed */} + +
+ + +
- -
- {referralData.length === 0 ? -
- -
-

No referrals Yet

-

Share the link with your friends, and when they sign up on KLEO you will earn XPs.

+
+ {referralData.length === 0 ? ( +
+ +
+

+ No referrals Yet +

+

+ Share the link with your friends, and when they sign up on + KLEO you will earn XPs. +

+
-
- : -
- -
- } + ) : ( +
+ +
+ )} +
-
} + )} ) } diff --git a/src/pages/profile/components/Snapshot.tsx b/src/pages/profile/components/Snapshot.tsx index 1a66d91..f50efc6 100644 --- a/src/pages/profile/components/Snapshot.tsx +++ b/src/pages/profile/components/Snapshot.tsx @@ -1,18 +1,27 @@ -import React from "react"; -import KleoMate from "../../../assets/dashboard/KleoMate.jsx"; +import React from 'react' +import KleoMate from '../../../assets/dashboard/KleoMate.jsx' interface SnapShotCardprops { - title: string; - description: string; - buttonColor: string; - backgroundColor: string; - textColor: string; - iconColor: string; - iconBgColor: string; - link: string; + title: string + description: string + buttonColor: string + backgroundColor: string + textColor: string + iconColor: string + iconBgColor: string + link: string } -const Card = ({ title, description, buttonColor, backgroundColor, textColor, iconColor, iconBgColor, link }: SnapShotCardprops) => { +const Card = ({ + title, + description, + buttonColor, + backgroundColor, + textColor, + iconColor, + iconBgColor, + link +}: SnapShotCardprops) => { return (
View Proposal
- ); -}; + ) +} const Snapshot = () => { const cardsData = [ { - title: "400 KLEO XP Points", + title: '400 KLEO XP Points', description: - "Kleo rewards early users with 400 XP points for joining before October 31st.", - buttonColor: "#FFFFFF", - backgroundColor: "#293056", - textColor: "white", - iconColor: "white", - iconBgColor: "#475467", - link: "https://snapshot.org/#/kleo-network.eth/proposal/0x5a0dc6208832a804d14e30b409458460f99fd41381231d4e9ec35d6f11444808" + 'Kleo rewards early users with 400 XP points for joining before October 31st.', + buttonColor: '#FFFFFF', + backgroundColor: '#293056', + textColor: 'white', + iconColor: 'white', + iconBgColor: '#475467', + link: 'https://snapshot.org/#/kleo-network.eth/proposal/0x5a0dc6208832a804d14e30b409458460f99fd41381231d4e9ec35d6f11444808' }, { - title: "Removal of PII", + title: 'Removal of PII', description: "This proposal seeks authorization for Kleo Network's founder to access and remove PII from 580 users' data using Azure OAI APIs in a TEE environment", - buttonColor: "#7F56D9", - backgroundColor: "#F9FAFB", - textColor: "#000", - iconColor: "#363F72", - iconBgColor: "#F9FAFB", - link: "https://snapshot.org/#/kleo-network.eth/proposal/0xfb2d8b419e81f4bb6af50d9960313366180c33c94d7b787ce7537ad40fda3d98" + buttonColor: '#7F56D9', + backgroundColor: '#F9FAFB', + textColor: '#000', + iconColor: '#363F72', + iconBgColor: '#F9FAFB', + link: 'https://snapshot.org/#/kleo-network.eth/proposal/0xfb2d8b419e81f4bb6af50d9960313366180c33c94d7b787ce7537ad40fda3d98' }, { - title: "Kleo x POL Meme Contest", + title: 'Kleo x POL Meme Contest', description: - "Kleo launches meme contest with 1,000 POL prize pool for data ownership awareness.", - buttonColor: "#FFFFFF", - backgroundColor: "#293056", - textColor: "white", - iconColor: "white", - iconBgColor: "#475467", - link: "https://snapshot.org/#/kleo-network.eth/proposal/0xd22dd94e31d7f101d1b04ef403f806f73139f06defc4b3343fa97d013990a533" + 'Kleo launches meme contest with 1,000 POL prize pool for data ownership awareness.', + buttonColor: '#FFFFFF', + backgroundColor: '#293056', + textColor: 'white', + iconColor: 'white', + iconBgColor: '#475467', + link: 'https://snapshot.org/#/kleo-network.eth/proposal/0xd22dd94e31d7f101d1b04ef403f806f73139f06defc4b3343fa97d013990a533' } - ]; + ] return (
@@ -87,7 +99,7 @@ const Snapshot = () => { ))}
- ); -}; + ) +} -export default Snapshot; +export default Snapshot diff --git a/src/pages/profile/components/mileStones/ActionableMileStone.tsx b/src/pages/profile/components/mileStones/ActionableMileStone.tsx index 33c01fa..9149238 100644 --- a/src/pages/profile/components/mileStones/ActionableMileStone.tsx +++ b/src/pages/profile/components/mileStones/ActionableMileStone.tsx @@ -1,18 +1,27 @@ interface ActionableMileStoneProps { - label: string; - icon: string; - onClick: () => void; - xp: number; - completed: boolean; + label: string + icon: string + onClick: () => void + xp: number + completed: boolean } -const ActionableMileStone = ({ completed, icon, label, onClick, xp }: ActionableMileStoneProps) => { +const ActionableMileStone = ({ + completed, + icon, + label, + onClick, + xp +}: ActionableMileStoneProps) => { const handleOnClick = () => { - onClick(); + onClick() } return ( -
  • @@ -22,12 +31,14 @@ const ActionableMileStone = ({ completed, icon, label, onClick, xp }: Actionable +{xp} XP {/* Green circle with white checkmark */} - {completed && - - } + {completed && ( + + ✓ + + )}
  • ) } -export default ActionableMileStone; \ No newline at end of file +export default ActionableMileStone diff --git a/src/pages/profile/components/mileStones/CircularProgress.tsx b/src/pages/profile/components/mileStones/CircularProgress.tsx index e6ff03a..eef5571 100644 --- a/src/pages/profile/components/mileStones/CircularProgress.tsx +++ b/src/pages/profile/components/mileStones/CircularProgress.tsx @@ -1,21 +1,21 @@ -import { useMemo } from "react"; +import { useMemo } from 'react' interface CircularProgressProps { - percentage: number; - radius?: number; // Allow radius to be customizable with a default - strokeWidth?: number; // Allow stroke width to be customizable + percentage: number + radius?: number // Allow radius to be customizable with a default + strokeWidth?: number // Allow stroke width to be customizable } const CircularProgress: React.FC = ({ percentage, radius = 45, - strokeWidth = 10, + strokeWidth = 10 }) => { - const circumference = useMemo(() => 2 * Math.PI * radius, [radius]); + const circumference = useMemo(() => 2 * Math.PI * radius, [radius]) const strokeDashoffset = useMemo( () => circumference - (percentage / 100) * circumference, [circumference, percentage] - ); + ) return ( = ({ {Math.round(percentage)}% - ); -}; + ) +} -export default CircularProgress; \ No newline at end of file +export default CircularProgress diff --git a/src/pages/profile/components/mileStones/Milestones.tsx b/src/pages/profile/components/mileStones/Milestones.tsx index 6a1ffcb..6ac6a38 100644 --- a/src/pages/profile/components/mileStones/Milestones.tsx +++ b/src/pages/profile/components/mileStones/Milestones.tsx @@ -1,7 +1,6 @@ -import ActionableMileStone from "./ActionableMileStone"; -import XLogoImage from '../../../../assets/dashboard/XLogo.png'; -import ProgressMilestone from "./ProgressMilestone"; -import { useCallback, useMemo } from "react"; +import ActionableMileStone from './ActionableMileStone' +import XLogoImage from '../../../../assets/dashboard/XLogo.png' +import ProgressMilestone from './ProgressMilestone' interface MilestonesProps { mileStones: Record @@ -17,31 +16,37 @@ interface MilestonesProps { */ } -const Milestones = ({ mileStones, handleShareGraph, isGraphAvailable }: MilestonesProps) => { +const Milestones = ({ + mileStones, + handleShareGraph, + isGraphAvailable +}: MilestonesProps) => { const handleFollowClick = () => { - window.open('https://x.com/kleo_network', '_blank'); - }; + window.open('https://x.com/kleo_network', '_blank') + } const handleShareGraphClick = () => { - console.log('Sharing graph.'); - handleShareGraph(); + console.log('Sharing graph.') + handleShareGraph() } const convertDataSizeToPercentage = (value: number) => { - const dataOwnedMB = value / (1024 * 1024); // Convert bytes to MB - const progress = Math.min((dataOwnedMB / 200) * 100, 100).toFixed(1); // Cap progress at 100% - return { value: dataOwnedMB, progress: parseFloat(progress) }; - }; + const dataOwnedMB = value / (1024 * 1024) // Convert bytes to MB + const progress = Math.min((dataOwnedMB / 200) * 100, 100).toFixed(1) // Cap progress at 100% + return { value: dataOwnedMB, progress: parseFloat(progress) } + } const convertReferredCountsToPercentage = (value: number) => { - const progress = Math.min((value / 10) * 100, 100).toFixed(1); // Cap progress at 100% - return { value, progress: parseFloat(progress) }; - }; + const progress = Math.min((value / 10) * 100, 100).toFixed(1) // Cap progress at 100% + return { value, progress: parseFloat(progress) } + } return (

    Milestones

    -

    Keep up with the team to receive rewards!

    +

    + Keep up with the team to receive rewards! +

      {/* Twitter milestones */} @@ -65,12 +70,19 @@ const Milestones = ({ mileStones, handleShareGraph, isGraphAvailable }: Mileston {/* Progress-based milestones */}
    @@ -78,4 +90,4 @@ const Milestones = ({ mileStones, handleShareGraph, isGraphAvailable }: Mileston ) } -export default Milestones; \ No newline at end of file +export default Milestones diff --git a/src/pages/profile/components/mileStones/ProgressMilestone.tsx b/src/pages/profile/components/mileStones/ProgressMilestone.tsx index 4f475d1..66e3b2c 100644 --- a/src/pages/profile/components/mileStones/ProgressMilestone.tsx +++ b/src/pages/profile/components/mileStones/ProgressMilestone.tsx @@ -1,17 +1,19 @@ -import CircularProgress from "./CircularProgress"; +import CircularProgress from './CircularProgress' interface ProgressMilestoneProps { - label: string; - progress: number; - xp: number; + label: string + progress: number + xp: number } const ProgressMilestone = ({ label, progress, xp }: ProgressMilestoneProps) => { - const isCompleted = progress === 100; + const isCompleted = progress === 100 return (
  • @@ -20,12 +22,14 @@ const ProgressMilestone = ({ label, progress, xp }: ProgressMilestoneProps) => { +{xp} XP {/* Green circle with white checkmark */} - {isCompleted && - - } + {isCompleted && ( + + ✓ + + )}
  • - ); + ) } -export default ProgressMilestone; \ No newline at end of file +export default ProgressMilestone diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx index 5e805d6..8e2bfe4 100644 --- a/src/pages/profile/index.tsx +++ b/src/pages/profile/index.tsx @@ -18,27 +18,27 @@ import Privacy from './components/Privacy' import LeaderBoardBanner from './components/LeaderBoardBanner' import Navbar, { PAGE_NAMES } from '../../common/components/Navbar' import { Method } from 'axios' -import { useNavigate, useParams } from 'react-router-dom'; +import { useNavigate, useParams } from 'react-router-dom' import useFetch from '../../common/hooks/useFetch' interface UserGraphResponse { - processing?: boolean; - data?: GraphLabelItem[]; + processing?: boolean + data?: GraphLabelItem[] error?: string } interface GraphLabelItem { - label: string; - percentage: number; + label: string + percentage: number } interface UploadResponse { - url?: string; - error?: string; + url?: string + error?: string // Add other fields as needed } -type CanvasSource = HTMLCanvasElement | HTMLImageElement; +type CanvasSource = HTMLCanvasElement | HTMLImageElement ChartJS.register( RadialLinearScale, @@ -51,41 +51,43 @@ ChartJS.register( function Profile() { // --------------- Validate UserAddress Logic --------------- // - const { address: urlAddress } = useParams<{ address: string }>(); // Extract the address from the URL - const [userAddress, setUserAddress] = useState(localStorage.getItem('address')); - const [isKleoConnectReady, setIsKleoConnectReady] = useState(false); - const navigate = useNavigate(); + const { address: urlAddress } = useParams<{ address: string }>() // Extract the address from the URL + const [userAddress, setUserAddress] = useState( + localStorage.getItem('address') + ) + const [isKleoConnectReady, setIsKleoConnectReady] = useState(false) + const navigate = useNavigate() useEffect(() => { const checkKleoConnect = () => { // Poll for the availability of window.kleoConnect if ((window as any).kleoConnect) { - setIsKleoConnectReady(true); - console.log('kleoConnect is ready:', (window as any).kleoConnect); + setIsKleoConnectReady(true) + console.log('kleoConnect is ready:', (window as any).kleoConnect) // Assign signIn method if not already assigned if (!(window as any).signIn) { - (window as any).signIn = (window as any).kleoConnect.signIn; + ;(window as any).signIn = (window as any).kleoConnect.signIn } } else { - console.log('Waiting for kleoConnect...'); - setTimeout(checkKleoConnect, 100); // Poll every 100ms + console.log('Waiting for kleoConnect...') + setTimeout(checkKleoConnect, 100) // Poll every 100ms } - }; + } - checkKleoConnect(); // Start polling - }, []); + checkKleoConnect() // Start polling + }, []) useEffect(() => { - if (!isKleoConnectReady) return; // Wait until kleoConnect is ready + if (!isKleoConnectReady) return // Wait until kleoConnect is ready const validateAddresses = async () => { try { - const localStorageAddress = localStorage.getItem('address'); + const localStorageAddress = localStorage.getItem('address') // Call signIn to get the address from the extension - const result = await (window as any).signIn(); - const extensionAddress = result.address; + const result = await (window as any).signIn() + const extensionAddress = result.address // Check if all three addresses match if ( @@ -93,148 +95,153 @@ function Profile() { urlAddress !== extensionAddress || localStorageAddress !== extensionAddress ) { - navigate('/signup/0'); // Redirect to signup if addresses don't match + navigate('/signup/0') // Redirect to signup if addresses don't match } else { - setUserAddress(localStorageAddress); + setUserAddress(localStorageAddress) } } catch (error) { - console.error('Error during signIn or address check:', error); - navigate('/signup/0'); // Redirect on error + console.error('Error during signIn or address check:', error) + navigate('/signup/0') // Redirect on error } - }; + } - validateAddresses(); // Call the validation function - }, [isKleoConnectReady, urlAddress]); // Re-run when URL changes + validateAddresses() // Call the validation function + }, [isKleoConnectReady, urlAddress]) // Re-run when URL changes // --------------- END: Validate UserAddress Logic --------------- // - const GET_USER_PATH = `user/get-user/${userAddress}`; - const UPLOAD_IMGUR_ENDPOINT = 'user/upload_activity_chart'; - const GET_USER_GRAPH = `user/get-user-graph/${userAddress || ''}`; + const GET_USER_PATH = `user/get-user/${userAddress}` + const UPLOAD_IMGUR_ENDPOINT = 'user/upload_activity_chart' + const GET_USER_GRAPH = `user/get-user-graph/${userAddress || ''}` // const GET_USER_GRAPH = `user/get-user-graph/${'0xC0cFAB5AFc7a951c510eA20DDD1eCCA31731e574'}`; // State for storing the user data - const [userData, setUserData] = useState(null); - const { data, status, error, fetchData } = useFetch(GET_USER_PATH, { + const [userData, setUserData] = useState(null) + useFetch(GET_USER_PATH, { onSuccessfulFetch: (fetchedData) => { - console.log('Fetched User Data:', fetchedData); - setUserData(fetchedData); - }, - }); - const { fetchData: fetchUserGraph, error: graphError } = useFetch(); - const [graphData, setGraphData] = useState([]); - const [isProcessing, setIsProcessing] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const [highestKleoPoints, setHighestKleoPoints] = useState(0); - const { fetchData: uploadImageFetch } = useFetch(); + console.log('Fetched User Data:', fetchedData) + setUserData(fetchedData) + } + }) + const { fetchData: fetchUserGraph, error: graphError } = + useFetch() + const [graphData, setGraphData] = useState([]) + const [isProcessing, setIsProcessing] = useState(false) + const [isLoading, setIsLoading] = useState(false) + const [highestKleoPoints, setHighestKleoPoints] = useState(0) + const { fetchData: uploadImageFetch } = useFetch() // Define the ref with the type of an HTMLDivElement - const milestonesRef = useRef(null); - const [milestonesHeight, setMilestonesHeight] = useState(0); + const milestonesRef = useRef(null) + const [milestonesHeight, setMilestonesHeight] = useState(0) // ------------ Start : Share Graph on Twitter ------------ // const createCanvasWithWhiteBackground = (canvas: CanvasSource): string => { - const tempCanvas = document.createElement('canvas') as HTMLCanvasElement; - tempCanvas.width = canvas.width; - tempCanvas.height = canvas.height; - const tempCtx = tempCanvas.getContext('2d'); + const tempCanvas = document.createElement('canvas') as HTMLCanvasElement + tempCanvas.width = canvas.width + tempCanvas.height = canvas.height + const tempCtx = tempCanvas.getContext('2d') if (tempCtx) { - tempCtx.fillStyle = 'white'; - tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height); - tempCtx.drawImage(canvas, 0, 0); + tempCtx.fillStyle = 'white' + tempCtx.fillRect(0, 0, tempCanvas.width, tempCanvas.height) + tempCtx.drawImage(canvas, 0, 0) } - return tempCanvas.toDataURL('image/png', 1).split(',')[1]; // Return base64 image data - }; + return tempCanvas.toDataURL('image/png', 1).split(',')[1] // Return base64 image data + } const constructTweetText = (imageUrl: string): string => { const top3Activities = graphData .slice(0, 3) - .map((activity: { label: any; }) => activity.label) - .join(", "); - return `Check out my Activity! My top 3 activities are ${top3Activities}. My current kleo points are ${userData.kleo_points || 0}. -Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`; - }; + .map((activity: { label: any }) => activity.label) + .join(', ') + return `Check out my Activity! My top 3 activities are ${top3Activities}. My current kleo points are ${ + userData.kleo_points || 0 + }. +Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}` + } const handleShareGraphClick = async () => { try { - const canvas = document.getElementsByTagName('canvas')[0]; - const imageData = createCanvasWithWhiteBackground(canvas); + const canvas = document.getElementsByTagName('canvas')[0] + const imageData = createCanvasWithWhiteBackground(canvas) const options = { method: 'POST' as Method, headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/json' }, body: JSON.stringify({ image: imageData }), onSuccessfulFetch: (data: UploadResponse) => { if (data && data.url) { - const imageUrlWithoutExtension = data.url?.replace('.png', ''); + const imageUrlWithoutExtension = data.url?.replace('.png', '') - const tweetText = constructTweetText(imageUrlWithoutExtension); + const tweetText = constructTweetText(imageUrlWithoutExtension) - const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(tweetText)}`; - window.open(twitterUrl, '_blank'); + const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent( + tweetText + )}` + window.open(twitterUrl, '_blank') } else { - console.error('Failed to upload image.'); + console.error('Failed to upload image.') } } - }; + } - uploadImageFetch(UPLOAD_IMGUR_ENDPOINT, options); + uploadImageFetch(UPLOAD_IMGUR_ENDPOINT, options) } catch (error) { - console.error('Error uploading image:', error); + console.error('Error uploading image:', error) } - }; + } // ------------ End : Share Graph on Twitter ------------ // useEffect(() => { const updateHeight = () => { if (milestonesRef.current) { - setMilestonesHeight(milestonesRef.current.clientHeight); + setMilestonesHeight(milestonesRef.current.clientHeight) } - }; + } - updateHeight(); + updateHeight() // Add event listener for resizing in case window size changes - window.addEventListener('resize', updateHeight); + window.addEventListener('resize', updateHeight) // Clean up the event listener on unmount return () => { - window.removeEventListener('resize', updateHeight); - }; - }, []); + window.removeEventListener('resize', updateHeight) + } + }, []) // Make API call when Address changes. useEffect(() => { if (!isLoading) { - setIsLoading(true); + setIsLoading(true) fetchUserGraph(GET_USER_GRAPH, { onSuccessfulFetch(data) { if (data?.error) { - setIsProcessing(true); + setIsProcessing(true) } else if (data?.processing) { - setIsProcessing(true); + setIsProcessing(true) } else { - setIsProcessing(false); + setIsProcessing(false) if (graphData) { - setGraphData(data?.data); - console.log('Data : ', data); + setGraphData(data?.data) + console.log('Data : ', data) } } - setIsLoading(false); - }, - }); + setIsLoading(false) + } + }) } - }, []); + }, []) // Listening to error if any errors set all flags accordingly. useEffect(() => { if (graphError) { - setIsProcessing(true); - setIsLoading(false); - setGraphData(null); + setIsProcessing(true) + setIsLoading(false) + setGraphData(null) } }, [graphError]) @@ -243,19 +250,31 @@ Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`; {/* Main Content */}
    - {/* Layout for >xl */}
    {/* First Row: PointsAndDataCard (wide) | DataQuality (medium) | Milestones (narrow) */}
    - +
    - +
    - +
    @@ -269,7 +288,10 @@ Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`;
    - +
    {/* Third Row: Privacy | LeaderBoardBanner */} @@ -288,10 +310,19 @@ Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`; {/* First Row: PointsAndDataCard and DataQuality */}
    - +
    - +
    @@ -299,7 +330,11 @@ Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`;
    {/* Milestones Column */}
    - +
    {/* Leaderboard Column with Scroll */} @@ -307,7 +342,10 @@ Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`; className="overflow-y-auto" style={{ maxHeight: milestonesHeight }} > - +
    @@ -331,11 +369,9 @@ Create your profile and get Kleo points! @kleo_network #KLEO ${imageUrl}`; - - ); + ) } -export default Profile; - +export default Profile diff --git a/src/pages/signup/Onboarding/Authentication/index.tsx b/src/pages/signup/Onboarding/Authentication/index.tsx index ceef2b9..df56d78 100644 --- a/src/pages/signup/Onboarding/Authentication/index.tsx +++ b/src/pages/signup/Onboarding/Authentication/index.tsx @@ -3,8 +3,6 @@ import { ReactComponent as Kleo } from '../../../../assets/images/kleoLogo.svg' import { ReactComponent as Tick } from '../../../../assets/images/check.svg' import { ReactComponent as AlertIcon } from '../../../../assets/images/alert.svg' import { useNavigate } from 'react-router-dom' -import { UserData } from '../../../../common/constants/SignupData' -import useFetch from '../../../../common/hooks/useFetch' import Alert from '../../../../common/components/Alerts' enum PluginState { @@ -13,14 +11,11 @@ enum PluginState { INSTALLED } -export default function Onboarding({ handleLogin, user, setUser }: any) { +export default function Onboarding() { const [pluginState, setPluginState] = useState(PluginState.CHECKING) const [login, setLogin] = useState(false) const navigate = useNavigate() - const { fetchData: fetchCreateAndFetchUserData, data: userFromDB } = - useFetch() - useEffect(() => { if (pluginState === PluginState.CHECKING) { setTimeout(() => { @@ -63,9 +58,11 @@ export default function Onboarding({ handleLogin, user, setUser }: any) { target="_blank" > VANA DLP - aimed + {' '} + aimed
    - at using chrome extension to help you own a piece of AI models. + at using chrome extension to help you own a piece of AI + models.

    @@ -128,10 +125,11 @@ export default function Onboarding({ handleLogin, user, setUser }: any) { {/* Sign In button - disabled if plugin is not installed */}