Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions components/common/gradient-badge/gradient-badge.view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { ReactNode } from "react";

interface GradientBadgeProps {
color?: "blue" | "purple";
variant?: "outlined" | "filled";
children: ReactNode;
}

export function GradientBadge({
color = "blue",
variant = "outlined",
children,
}: GradientBadgeProps) {
return(
<div className={`gradient-badge-wrapper gradient-badge-wrapper-${color}`}>
<div className={`gradient-badge-content gradient-badge-content-${variant}-${color}`}>
{children}
</div>
</div>
);
}
22 changes: 14 additions & 8 deletions components/common/points/points-badge.view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,22 @@ import { useTranslation } from "next-i18next";

import { PointsIcon } from "assets/icons/points-icon";

import { GradientBadge } from "components/common/gradient-badge/gradient-badge.view";

import { formatNumberToString } from "helpers/formatNumber";

type PointsBadgeProps = {
points: number | string,
variant?: "outlined" | "filled",
size?: "sm" | "md";
size?: "sm" | "md",
isBoosted?: boolean,
}

export function PointsBadge({
points = "0",
variant = "outlined",
size = "md",
isBoosted,
}: PointsBadgeProps) {
const { t } = useTranslation("points");

Expand All @@ -30,19 +34,21 @@ export function PointsBadge({
iconSize: 21.33
}
}[size];
const color = isBoosted ? "purple" : "blue";

return(
<div className="points-badge-wrapper">
<div className={`points-badge-content points-badge-content-${variant}`}>
<span className={`${styleBySize.font} text-white`}>
{pointsLabel}
</span>
<GradientBadge
variant={variant}
color={color}
>
<span className={`${styleBySize.font} text-white`}>
{pointsLabel}
</span>

<PointsIcon
width={styleBySize.iconSize}
height={styleBySize.iconSize}
/>
</div>
</div>
</GradientBadge>
);
}
53 changes: 53 additions & 0 deletions components/pages/points/hero/points-page-hero.view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useTranslation } from "next-i18next";

import { GradientBadge } from "components/common/gradient-badge/gradient-badge.view";
import { PointsBadge } from "components/common/points/points-badge.view";
import If from "components/If";

interface PointsPageHeroProps {
totalPoints: number;
hasBoost?: boolean;
boostValue?: number;
}

export function PointsPageHero({
totalPoints,
hasBoost,
boostValue,
}: PointsPageHeroProps) {
const { t } = useTranslation("points");

return(
<div className={`row py-5 points-hero points-hero${hasBoost ? "-boosted" : ""}`}>
<div className="col">
<h3 className="text-white">{t("your-points")}</h3>

<p className="family-Regular base-medium mt-2 mb-4 text-gray-200">{t("collect-bepro")}</p>

<div className="row align-items-center gy-3 pt-2">
<div className="col-12 col-sm-auto">
<div className="d-flex">
<PointsBadge
points={totalPoints}
/>
</div>
</div>

<If condition={hasBoost}>
<div className="col-12 col-sm-auto">
<div className="d-flex">
<GradientBadge
variant="filled"
color="purple"
>
<span className="xs-medium text-white">{t("booster-active")}</span>
<span className="base-medium text-gradient-purple">{boostValue}x</span>
</GradientBadge>
</div>
</div>
</If>
</div>
</div>
</div>
);
}
12 changes: 11 additions & 1 deletion components/pages/points/points-page.controller.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { PointsPageView } from "components/pages/points/points-page.view";

import { userPointsOfUser } from "x-hooks/use-points-of-user";

export function PointsPage() {
const { totalPoints, pointsBase } = userPointsOfUser();

const boost = pointsBase?.find(base => base?.scalingFactor > 1);

return(
<PointsPageView />
<PointsPageView
totalPoints={totalPoints}
hasBoost={!!boost}
boostValue={boost?.scalingFactor}
/>
);
}
24 changes: 21 additions & 3 deletions components/pages/points/points-page.view.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
import CustomContainer from "components/custom-container";
import { PointsPageHero } from "components/pages/points/hero/points-page-hero.view";
import { CollectedPoints } from "components/points-system/collected-points/collected-points.controller";

export function PointsPageView() {
interface PointsPageViewProps {
totalPoints: number;
hasBoost?: boolean;
boostValue?: number;
}

export function PointsPageView({
totalPoints,
hasBoost,
boostValue,
}: PointsPageViewProps) {
return(
<CustomContainer>
<h1>Points Page</h1>
<CustomContainer className="pb-5">
<PointsPageHero
totalPoints={totalPoints}
hasBoost={hasBoost}
boostValue={boostValue}
/>

<CollectedPoints />
</CustomContainer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useRouter } from "next/router";

import {CollectedPointsView} from "components/points-system/collected-points/collected-points.view";

import {PointsEvents} from "interfaces/points";
import {PointsEvents, PointsBase} from "interfaces/points";

import useMarketplace from "x-hooks/use-marketplace";
import {userPointsOfUser} from "x-hooks/use-points-of-user";
Expand All @@ -16,22 +16,22 @@ export function CollectedPoints() {
const { collectedPoints, pointsBase, refresh } = userPointsOfUser();

const getCollected = (actionName: string) => collectedPoints?.find(c => c.actionName === actionName);
const getPointStatus = (event: PointsEvents) => {
if (!event)
return "available";
if (!event.pointsCounted)
return "pending";
return "claimed";
};
const getSocialName = (actionName: string) => {
if (actionName?.includes("linkedin"))
return "linkedin";
if (actionName?.includes("github"))
return "github";
if (actionName?.includes("twitter"))
return "x";
const getPointStatus = (rule: PointsBase, event: PointsEvents) => {
if (rule?.counter !== "N") {
if (event?.pointsCounted)
return "collected";
if (event)
return "pending";
}
if (rule?.scalingFactor > 1)
return "boosted";
return "available";
};

const actions = {
"created_task": () => push("/create-task"),
"delegated": () => goToProfilePage("voting-power"),
"locked": () => goToProfilePage("voting-power"),
"created_marketplace": () => push("/new-marketplace"),
"created_deliverable": () => push("/explore"),
"created_proposal": () => push("/explore"),
Expand All @@ -43,40 +43,37 @@ export function CollectedPoints() {
"add_twitter": () => push("/dashboard"),
};

const { onGoing, socials, profile, other } = pointsBase.reduce((acc, curr) => {
const { recurring, available, collected } = pointsBase.reduce((acc, curr) => {
const collected = getCollected(curr.actionName);
const status = getPointStatus(collected);
const pointsPerAction = status === "available" ? curr.pointsPerAction * curr.scalingFactor : collected.pointsWon;
const status = getPointStatus(curr, collected);
const pointsPerAction = status === "available" || status === "boosted"
? curr.pointsPerAction * curr.scalingFactor : collected.pointsWon;
const currUpdated = {
...curr,
status,
pointsPerAction,
onActionClick: actions[curr.actionName],
};

if (["linkedin", "github", "twitter"].some(social => curr.actionName.includes(social)))
acc.socials.push(currUpdated);
else if (["email", "add_about", "add_avatar"].some(e => curr.actionName.includes(e)))
acc.profile.push(currUpdated);
else if (curr.counter === "N")
acc.onGoing.push(curr);
if (curr.counter === "N")
acc.recurring.push(currUpdated);
else if (status === "pending" || status === "collected")
acc.collected.push(currUpdated);
else
acc.other.push(currUpdated);
acc.available.push(currUpdated);

return acc;
}, { onGoing: [], socials: [], profile: [], other: [] });
}, { recurring: [], available: [], collected: [] });

useEffect(() => {
refresh()
}, []);

return(
<CollectedPointsView
onGoing={onGoing}
socials={socials}
profile={profile}
other={other}
getSocialName={getSocialName}
recurring={recurring}
available={available}
collected={collected}
/>
);
}
Loading