Skip to content

Commit

Permalink
Merge pull request #38 from ai16zpartners/feature/improve-ui
Browse files Browse the repository at this point in the history
 UI Improvements
  • Loading branch information
awidearray authored Nov 15, 2024
2 parents 7b4e84b + f114c57 commit e86d669
Show file tree
Hide file tree
Showing 10 changed files with 293 additions and 155 deletions.
45 changes: 44 additions & 1 deletion src/components/leaderboard/LeaderboardMedals.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,47 @@
.firstPlaceScore {
font-size: 1rem;
}
}
}

/* Add these styles to your existing LeaderboardMedals.module.css file */

@keyframes pulse {

0%,
100% {
opacity: 0.7;
}

50% {
opacity: 0.4;
}
}

.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

.skeletonCircle {
background-color: #242424;
border: 2px solid #3C3C3C;
border-radius: 50%;
}

.skeletonText {
height: 1rem;
width: 80px;
background-color: #242424;
border: 1px solid #3C3C3C;
border-radius: 0.25rem;
margin-top: 0.5rem;
}

.skeletonScore {
height: 1.5rem;
width: 4rem;
background-color: #242424;
border: 1px solid #3C3C3C;
border-radius: 0.75rem;
margin-top: 0.25rem;
}

105 changes: 67 additions & 38 deletions src/components/leaderboard/LeaderboardMedals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,26 @@ import { useDashboard } from '../../hooks/useDashboard';
import type { Partner } from '../../types/dashboard';
import styles from './LeaderboardMedals.module.css';



const SkeletonMedal: FC<{ position: number }> = ({ position }) => {
const isFirstPlace = position === 1;
const size = isFirstPlace ? '120px' : '80px';

return (
<div className={`${styles.medalHolder} ${isFirstPlace ? styles.firstPlace : ''}`}>
<div className={`${styles.imageWrapper} ${isFirstPlace ? styles.firstPlaceImage : ''}`}>
<div className={`${styles.skeletonCircle} animate-pulse`}
style={{
width: size,
height: size,
}}
/>
</div>
</div>
);
};

const LeaderboardMedals: FC = () => {
const { data: dashboardData, isLoading } = useDashboard();
const positions = [2, 1, 3];
Expand Down Expand Up @@ -48,48 +68,57 @@ const LeaderboardMedals: FC = () => {

return (
<div className={styles.container}>
{reorderedTopThree.map((user, index) => {
const isFirstPlace = index === 1;
const medalClass = getMedalClass(index);

return (
<div
key={user?.wallet || index}
className={`${styles.medalHolder} ${isFirstPlace ? styles.firstPlace : ''}`}
>
<div className={`${styles.imageWrapper} ${isFirstPlace ? styles.firstPlaceImage : ''}`}>
<div className={`${styles.medal} ${medalClass}`}>
{positions[index]}
</div>
<div className={`${styles.imageBorder} ${medalClass}`}>
{user?.image ? (
<Image
src={user.image}
alt={user && user.wallet ? truncateAddress(user.wallet) : `Position ${positions[index]}`}
width={isFirstPlace ? 120 : 80}
height={isFirstPlace ? 120 : 80}
className={styles.userImage}
/>) : (
<div
className={`${styles.placeholderImage}`}
style={{ width: index === 1 ? '80px' : '64px', height: index === 1 ? '80px' : '64px' }}
/>
)}
{isLoading || !dashboardData ? (
positions.map((position) => (
<SkeletonMedal key={position} position={position} />
))
) : (

reorderedTopThree.map((user, index) => {
const isFirstPlace = index === 1;
const medalClass = getMedalClass(index);

return (
<div
key={user?.wallet || index}
className={`${styles.medalHolder} ${isFirstPlace ? styles.firstPlace : ''}`}
>
<div className={`${styles.imageWrapper} ${isFirstPlace ? styles.firstPlaceImage : ''}`}>
<div className={`${styles.medal} ${medalClass}`}>
{positions[index]}
</div>
<div className={`${styles.imageBorder} ${medalClass}`}>
{user?.image ? (
<Image
src={user.image}
alt={user && user.wallet ? truncateAddress(user.wallet) : `Position ${positions[index]}`}
width={isFirstPlace ? 120 : 80}
height={isFirstPlace ? 120 : 80}
className={styles.userImage}
/>) : (
<div
className={`${styles.placeholderImage}`}
style={{ width: index === 1 ? '80px' : '64px', height: index === 1 ? '80px' : '64px' }}
/>
)}
</div>
</div>
</div>
<div className={styles.userInfo}>
<span className={styles.name}>
{user?.displayAddress || user?.wallet ? truncateAddress(user.displayAddress || user.wallet) : `Position ${positions[index]}`}
</span>
<div className={`${styles.scoreWrapper} ${medalClass}`}>
<span className={`${styles.score} ${isFirstPlace ? styles.firstPlaceScore : ''}`}>
{user?.trustScore ? user.trustScore.toFixed(2) : '0.00'}
<div className={styles.userInfo}>
<span className={styles.name}>
{user?.displayAddress || user?.wallet ? truncateAddress(user.displayAddress || user.wallet) : `Position ${positions[index]}`}
</span>
<div className={`${styles.scoreWrapper} ${medalClass}`}>
<span className={`${styles.score} ${isFirstPlace ? styles.firstPlaceScore : ''}`}>
{user?.trustScore ? user.trustScore.toFixed(2) : '0.00'}
</span>
</div>
</div>
</div>
</div>
);
})}
);
})

)}

</div>
);
};
Expand Down
21 changes: 20 additions & 1 deletion src/components/leaderboard/LeaderboardPartners.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
.row1 {
background: #2d2d2d;
height: 62px;
transition: all 0.3s ease;
}

.text {
Expand Down Expand Up @@ -362,4 +363,22 @@
.rankWrapper {
padding-right: 12px;
}
}
}


@keyframes pulse {

0%,
100% {
opacity: 1;
}

50% {
opacity: .5;
}
}

.animate-pulse {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}

38 changes: 18 additions & 20 deletions src/components/leaderboard/LeaderboardPartners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ interface PartnerWithUser extends Partner {
discordImage?: string;
}

const SkeletonRow = () => (
<div className={`${styles.row1} animate-pulse`}>
<div className={styles.rowChild}>
<div className="w-8 h-8 bg-[#3C3C3C] rounded-full" />

</div>
</div>
);

const LeaderboardPartners: FC = () => {
const { publicKey } = useWallet();
const { data: session } = useSession();
Expand All @@ -29,6 +38,7 @@ const LeaderboardPartners: FC = () => {
const [error, setError] = useState<string | null>(null);
const [retryCount, setRetryCount] = useState(0);
const MAX_RETRIES = 3;
const SKELETON_ROWS = 5;

const formatAddress = useCallback((address: string) => {
if (isMobile) {
Expand Down Expand Up @@ -93,21 +103,6 @@ const LeaderboardPartners: FC = () => {
fetchData();
}, [retryCount, isMobile, formatAddress, publicKey, session]);

const formatHoldings = (value: number): string => {
if (value >= 1000000) {
return `${(value / 1000000).toFixed(2)}M`;
} else if (value >= 1000) {
return `${(value / 1000).toFixed(2)}K`;
}
return value.toFixed(2);
};

const Loader = () => (
<div className="flex justify-center items-center w-full py-8">
<div className="w-8 h-8 border-4 border-[#F98C13] border-t-transparent rounded-full animate-spin" />
</div>
);

const getRankDisplay = (rank: number) => {
switch (rank) {
case 1:
Expand All @@ -134,11 +129,10 @@ const LeaderboardPartners: FC = () => {
}
};


const renderPartnerRow = (partner: PartnerWithUser) => (
<div
key={partner.address}
className={` ${styles.row1} ${partner.isCurrentUser ? styles.currentUserRow : ''}`}
className={`${styles.row1} ${partner.isCurrentUser ? styles.currentUserRow : ''}`}
>
<div className={styles.rowChild}>
<Image
Expand All @@ -154,7 +148,7 @@ const LeaderboardPartners: FC = () => {
</div>
</div>
</div>
<div className='flex items-center'>
<div className="flex items-center">
<div className={styles.textWrapper}>
{partner.trustScore === 0 ? (
<div className={styles.tooltipContainer}>
Expand All @@ -163,7 +157,7 @@ const LeaderboardPartners: FC = () => {
alt="Null trust score"
width={20}
height={20}
className={`invert brightness-0 transition-all duration-300 ${styles.trustScoreImage}`}
className={`invert brightness-0 transition-all duration-300 ${styles.trustScoreImage}`}
/>
<span className={styles.tooltip}>
AI Marc is Calculating Trust
Expand All @@ -185,7 +179,11 @@ const LeaderboardPartners: FC = () => {
return (
<div className={styles.frameParent}>
{isLoading ? (
<Loader />
<>
{[...Array(SKELETON_ROWS)].map((_, index) => (
<SkeletonRow key={index} />
))}
</>
) : error ? (
<div className={styles.errorMessage}>
Error loading partners. Retrying... ({retryCount}/{MAX_RETRIES})
Expand Down
3 changes: 2 additions & 1 deletion src/components/profile/ProfileData.module.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.container {
width: 100%;
display: flex;
justify-content: flex-start;
justify-content: center;
padding: 14px 24px;
max-width: 800px;
margin: 0 auto;
Expand All @@ -10,6 +10,7 @@
.profileContainer {
display: flex;
align-items: center;
flex-direction: column;
gap: 16px;
}

Expand Down
9 changes: 2 additions & 7 deletions src/components/profile/ProfileData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import styles from "./ProfileData.module.css";
export const ProfileData: FC = () => {
const { data: session } = useSession();

const handleSignOut = () => {
signOut({ callbackUrl: "/" });
};


// Helper function to determine the user role
const getUserRole = () => {
Expand Down Expand Up @@ -38,11 +36,8 @@ export const ProfileData: FC = () => {
<h1 className={styles.userName}>
{session?.user?.name || "Anonymous"}
</h1>
<span className={styles.userRole}>{getUserRole()}</span>
<span className={`hidden ${styles.userRole}`}>{getUserRole()}</span>
</div>
<button onClick={handleSignOut} className={styles.signOutButton}>
Sign Out
</button>
</div>
</div>
);
Expand Down
Loading

0 comments on commit e86d669

Please sign in to comment.