/ja progress
This commit is contained in:
102
components/ProfileCard/ProfileCard.module.scss
Normal file
102
components/ProfileCard/ProfileCard.module.scss
Normal file
@@ -0,0 +1,102 @@
|
||||
.profile {
|
||||
margin: 2rem 0;
|
||||
background: var(--black1);
|
||||
border-radius: 8px;
|
||||
box-shadow: var(--shadow0);
|
||||
article {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 1.5rem 1.5rem 1rem 1.5rem;
|
||||
gap: 1rem;
|
||||
background-color: var(--black2);
|
||||
border-radius: 8px 8px 0 0;
|
||||
@media screen and (max-width: 400px) {
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
img {
|
||||
border-radius: 50%;
|
||||
height: 128px;
|
||||
width: 128px;
|
||||
@media screen and (max-width: 600px) {
|
||||
height: 64px;
|
||||
width: 64px;
|
||||
}
|
||||
}
|
||||
.inner {
|
||||
width: 100%;
|
||||
header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
p {
|
||||
font-family: var(--fonts-bold);
|
||||
span {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.badges {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
margin: 8px 0;
|
||||
.badge {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
width: initial;
|
||||
gap: 8px;
|
||||
padding: 4px 8px;
|
||||
background: rgba(white, 0.1);
|
||||
border-radius: 4px;
|
||||
.dot {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background-color: #fb636b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.xpinfo {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background: var(--black2);
|
||||
color: #ababab;
|
||||
padding: 0 14px;
|
||||
}
|
||||
.xpbar {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 10px;
|
||||
background: rgba(white, 0.025);
|
||||
.xpinner {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 99%;
|
||||
background: #fb636b;
|
||||
opacity: 75%;
|
||||
}
|
||||
}
|
||||
footer {
|
||||
min-height: 16px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
section {
|
||||
width: 50%;
|
||||
padding: 2rem;
|
||||
@media screen and (max-width: 800px) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
113
components/ProfileCard/ProfileCard.tsx
Normal file
113
components/ProfileCard/ProfileCard.tsx
Normal file
@@ -0,0 +1,113 @@
|
||||
import styles from "./ProfileCard.module.scss";
|
||||
|
||||
type UserProfileCardProps = {
|
||||
username: string;
|
||||
description?: string;
|
||||
picture?: string | null;
|
||||
isAdmin?: boolean;
|
||||
isDeveloper?: boolean;
|
||||
experience?: {
|
||||
level: number;
|
||||
tilNextLevel?: number;
|
||||
looseXP?: number;
|
||||
};
|
||||
badges?: {
|
||||
badgeName: string;
|
||||
badgeDesc?: string;
|
||||
badgeMerit?: string;
|
||||
badgeImage?: string;
|
||||
}[];
|
||||
accentColor?: string;
|
||||
};
|
||||
|
||||
let placeholderPicture = "https://placewaifu.com/image/128?greyscale&blur";
|
||||
|
||||
const ProfileCard = (user: UserProfileCardProps) => {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.profile}>
|
||||
<article>
|
||||
<img src={user.picture || placeholderPicture} alt={user.username} />
|
||||
<div className={styles.inner}>
|
||||
<header>
|
||||
<h1>{user.username}</h1>
|
||||
<p>
|
||||
{user.experience?.level && (
|
||||
<>
|
||||
{"LVL "}
|
||||
<span>{user.experience.level}</span>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</header>
|
||||
<p>{user.description}</p>
|
||||
<div className={styles.badges}>
|
||||
{user.isAdmin && (
|
||||
<div className={styles.badge}>
|
||||
<div
|
||||
className={styles.dot}
|
||||
style={{ background: user.accentColor }}
|
||||
/>
|
||||
Admin
|
||||
</div>
|
||||
)}
|
||||
{user.isDeveloper && (
|
||||
<div className={styles.badge}>
|
||||
<div
|
||||
className={styles.dot}
|
||||
style={{ background: user.accentColor }}
|
||||
/>
|
||||
DEV
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{user.experience?.looseXP && user.experience.tilNextLevel && (
|
||||
<div className={styles.xpinfo}>
|
||||
<p>XP: {user.experience.looseXP}</p>
|
||||
<p>XP until next level: {user.experience.tilNextLevel} </p>
|
||||
</div>
|
||||
)}
|
||||
{user.experience?.looseXP && user.experience.tilNextLevel && (
|
||||
<div className={styles.xpbar}>
|
||||
<div
|
||||
className={styles.xpinner}
|
||||
style={{
|
||||
background: user.accentColor,
|
||||
width:
|
||||
(
|
||||
(user.experience.looseXP /
|
||||
(user.experience.looseXP +
|
||||
user.experience.tilNextLevel)) *
|
||||
100
|
||||
).toString() + "%",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<footer>
|
||||
{user.badges
|
||||
?.slice(0, 1)
|
||||
.map(
|
||||
(el: {
|
||||
badgeName: string;
|
||||
badgeDesc?: string;
|
||||
badgeMerit?: string;
|
||||
badgeImage?: string;
|
||||
}) => {
|
||||
return (
|
||||
<section>
|
||||
<h3>{el.badgeName}</h3>
|
||||
<p>{el.badgeDesc}</p>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
)}
|
||||
</footer>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { ProfileCard };
|
||||
Reference in New Issue
Block a user