Skip to content

Commit f622063

Browse files
Merge pull request #48 from code4rena-dev/develop
Minor Version - Contest Tile Tags
2 parents 3e8eace + 778fd91 commit f622063

File tree

10 files changed

+387
-125
lines changed

10 files changed

+387
-125
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@code4rena/components-library",
3-
"version": "3.0.2",
3+
"version": "3.1.0",
44
"description": "Code4rena's official components library ",
55
"types": "./dist/lib.d.ts",
66
"exports": {

src/lib/ContestTile/CompactTemplate.tsx

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import React, { useCallback, useEffect, useState } from 'react';
22
import clsx from "clsx";
33
import { BountyTileData, ContestSchedule, ContestTileData, ContestTileProps, ContestTileVariant } from "./ContestTile.types";
4-
import { Status } from '../types';
4+
import { Status, TagSize, TagVariant } from '../types';
55
import { ContestStatus } from '../ContestStatus';
66
import { Countdown } from './ContestTile';
77
import { getDates } from '../../utils/time';
8+
import { Tag } from '../Tag';
9+
import { Icon } from '../Icon';
10+
import wolfbotIcon from "../../../public/icons/wolfbot.svg";
811

912
export default function CompactTemplate({
1013
variant,
@@ -19,6 +22,7 @@ export default function CompactTemplate({
1922
"compact--light": variant === ContestTileVariant.COMPACT_LIGHT,
2023
"compact--dark": variant === ContestTileVariant.COMPACT_DARK,
2124
});
25+
const isDarkTile = variant === ContestTileVariant.DARK || variant === ContestTileVariant.COMPACT_DARK;
2226

2327
const tileClasses = clsx({
2428
c4contesttile: true,
@@ -29,11 +33,13 @@ export default function CompactTemplate({
2933
<div id={htmlId ?? undefined} className={clsx(variantClasses, tileClasses)}>
3034
<div className="container--inner compact-content">
3135
{contestData && <IsContest
36+
isDarkTile={isDarkTile}
3237
title={title}
3338
contestData={contestData}
3439
sponsorUrl={sponsorUrl}
3540
sponsorImage={sponsorImage} />}
3641
{bountyData && <IsBounty
42+
isDarkTile={isDarkTile}
3743
title={title}
3844
bountyData={bountyData}
3945
sponsorUrl={sponsorUrl}
@@ -45,14 +51,20 @@ export default function CompactTemplate({
4551
}
4652

4753

48-
const IsContest = ({title, contestData, sponsorUrl, sponsorImage}: {
54+
const IsContest = ({title, isDarkTile = true, contestData, sponsorUrl, sponsorImage}: {
4955
title: string;
56+
isDarkTile: boolean;
5057
contestData: ContestTileData;
5158
sponsorUrl: string | undefined;
5259
sponsorImage: string | undefined;
5360
}) => {
54-
const { startDate, endDate, amount, contestUrl, contestType } = contestData;
61+
const { startDate, endDate, amount, contestUrl, contestType, ecosystem, languages } = contestData;
5562
const [contestTimelineObject, setContestTimelineObject] = useState<ContestSchedule | undefined>();
63+
const [hasBotRace, setHasBotRace] = useState(contestData ? !!contestData.botFindingsRepo : false);
64+
let ecosystemLogoName: string = "";
65+
if (ecosystem && (ecosystem === "Polkadot" || ecosystem === "Ethereum")) {
66+
ecosystemLogoName = `logo-${ecosystem.toLowerCase()}`
67+
}
5668

5769
const updateContestTileStatus = useCallback(() => {
5870
if (contestData) {
@@ -137,16 +149,48 @@ const IsContest = ({title, contestData, sponsorUrl, sponsorImage}: {
137149
</div>
138150
<p className="amount">{amount}</p>
139151
</div>
152+
{((hasBotRace && contestTimelineObject && (contestTimelineObject.botRaceStatus === Status.UPCOMING ||
153+
contestTimelineObject.botRaceStatus === Status.LIVE)) || ecosystem || languages?.length > 0) && <div className="tags">
154+
{hasBotRace && contestTimelineObject &&
155+
(contestTimelineObject.botRaceStatus === Status.UPCOMING ||
156+
contestTimelineObject.botRaceStatus === Status.LIVE) && (
157+
<Tag
158+
variant={isDarkTile ? TagVariant.DEFAULT : TagVariant.WHITE_OUTLINE}
159+
label={contestTimelineObject.botRaceStatus === Status.LIVE ? "Bot Race live" : "1st hour: Bot Race"}
160+
iconLeft={wolfbotIcon}
161+
size={TagSize.NARROW}
162+
/>
163+
)}
164+
{ecosystem && <Tag
165+
variant={isDarkTile ? TagVariant.DEFAULT : TagVariant.WHITE_OUTLINE}
166+
label={ecosystem}
167+
iconLeft={ecosystemLogoName ? <Icon name={ecosystemLogoName} size="small" color="white" /> : undefined}
168+
size={TagSize.NARROW}
169+
/>}
170+
{languages
171+
&& languages.length > 0
172+
&& languages.map((language) => <Tag
173+
variant={isDarkTile ? TagVariant.DEFAULT : TagVariant.WHITE_OUTLINE}
174+
label={language}
175+
size={TagSize.NARROW}
176+
/>
177+
)}
178+
</div>}
140179
</div>
141180
)}
142181

143-
const IsBounty = ({title, bountyData, sponsorUrl, sponsorImage}: {
182+
const IsBounty = ({title, isDarkTile = true, bountyData, sponsorUrl, sponsorImage}: {
144183
title: string;
184+
isDarkTile: boolean;
145185
bountyData: BountyTileData;
146186
sponsorUrl: string | undefined;
147187
sponsorImage: string | undefined;
148188
}) => {
149-
const { amount, bountyUrl } = bountyData;
189+
const { amount, bountyUrl, ecosystem, languages } = bountyData;
190+
let ecosystemLogoName: string = "";
191+
if (ecosystem && (ecosystem === "Polkadot" || ecosystem === "Ethereum")) {
192+
ecosystemLogoName = `logo-${ecosystem.toLowerCase()}`
193+
}
150194

151195
return (
152196
<div className="body--bounty">
@@ -189,5 +233,20 @@ const IsBounty = ({title, bountyData, sponsorUrl, sponsorImage}: {
189233
<strong>Max Bounty</strong>
190234
<p className="amount">{amount}</p>
191235
</div>
236+
{(ecosystem || languages?.length > 0) && <div className="tags">
237+
{ecosystem && <Tag
238+
variant={isDarkTile ? TagVariant.DEFAULT : TagVariant.WHITE_OUTLINE}
239+
label={ecosystem}
240+
iconLeft={ecosystemLogoName ? <Icon name={ecosystemLogoName} size="small" color="white" /> : undefined}
241+
size={TagSize.NARROW}
242+
/>}
243+
{languages
244+
&& languages.length > 0
245+
&& languages.map((language) => <Tag
246+
variant={isDarkTile ? TagVariant.DEFAULT : TagVariant.WHITE_OUTLINE}
247+
label={language}
248+
size={TagSize.NARROW} />
249+
)}
250+
</div>}
192251
</div>
193252
)}

src/lib/ContestTile/ContestTile.scss

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,39 @@
437437
}
438438
}
439439

440+
.tags {
441+
padding: 0.24rem 0.5rem 0.5rem;
442+
display: flex;
443+
flex-direction: row;
444+
gap: 0.5rem;
445+
flex-wrap: wrap;
446+
447+
img {
448+
width: 0.75rem !important;
449+
height: 0.75rem !important;
450+
}
451+
452+
.icon {
453+
svg {
454+
min-width: 1.125rem;
455+
min-height: 1.125rem;
456+
width: 1.125rem;
457+
height: 1.125rem;
458+
}
459+
}
460+
461+
462+
.separator {
463+
height: 26px;
464+
}
465+
466+
p {
467+
padding-top: 5px;
468+
padding-bottom: 5px;
469+
font-size: 0.75rem !important;
470+
}
471+
}
472+
440473
.amount {
441474
margin: 0px;
442475
margin-left: auto;
@@ -506,24 +539,23 @@
506539
display: block;
507540
text-align: center;
508541
}
509-
542+
543+
.tags {
544+
margin-top: 0.5rem;
545+
display: flex;
546+
flex-direction: row;
547+
gap: 0.5rem;
548+
flex-wrap: wrap;
549+
justify-content: center;
550+
}
551+
510552
.title {
511553
margin: 0rem;
512554
color: $color__white;
513555
text-align: center;
514556
font-size: $headline-font-size__xxs;
515557
}
516558

517-
.bot-race-status {
518-
display: flex;
519-
gap: 0.5rem;
520-
margin-top: 0.25rem;
521-
align-items: center;
522-
justify-content: center;
523-
color: $color__white;
524-
font-weight: 700;
525-
}
526-
527559
.description {
528560
margin: $spacing__s 0rem 0rem;
529561
}
@@ -587,7 +619,7 @@
587619
text-align: left;
588620
}
589621

590-
.bot-race-status {
622+
.tags {
591623
justify-content: flex-start;
592624
}
593625
}

src/lib/ContestTile/ContestTile.stories.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { Fragment } from "react";
22
import { ContestTile } from "./ContestTile";
33
import { Meta, StoryObj } from "@storybook/react";
4-
import { ContestTileVariant } from "./ContestTile.types";
4+
import { CodingLanguage, ContestEcosystem, ContestTileVariant } from "./ContestTile.types";
55

66
const meta: Meta<typeof ContestTile> = {
77
component: ContestTile,
@@ -39,9 +39,12 @@ const defaultArgs = {
3939
contestType: "Open Audit",
4040
isUserCertified: false,
4141
contestId: 321,
42+
ecosystem: "Ethereum" as ContestEcosystem,
43+
languages: ["Rust"] as CodingLanguage[],
4244
contestUrl: "https://code4rena.com/audits/2023-07-axelar-network#top",
4345
contestRepo: "https://github.com/code-423n4/2023-07-axelar",
4446
findingsRepo: "https://github.com/code-423n4/2023-07-axelar",
47+
botFindingsRepo: "https://github.com/code-423n4/2023-07-axelar",
4548
amount: "$80,000 USDC",
4649
startDate: "2030-07-12T18:00:00Z",
4750
endDate: "2030-07-21T18:00:00.000Z",
@@ -162,6 +165,8 @@ BountyTile.args = {
162165
startDate: "2023-07-12T18:00:00Z",
163166
repoUrl: "https://github.com/code-423n4/2023-07-axelar",
164167
bountyUrl: "https://code4rena.com/audits/2023-07-axelar-network#top",
168+
ecosystem: "Polkadot" as ContestEcosystem,
169+
languages: ["Rust"] as CodingLanguage[],
165170
},
166171
variant: ContestTileVariant.LIGHT,
167172
sponsorImage: "/logos/apple-touch-icon.png",

src/lib/ContestTile/ContestTile.types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ export enum ContestTileVariant {
88
COMPACT_DARK = "COMPACT_DARK"
99
}
1010

11+
export type ContestEcosystem = "Algorand" | "Aptos" | "Blast" | "Cosmos" | "Ethereum" | "EVM" | "NEAR" | "Polkadot" | "Scroll" | "Sei" | "Solana" | "StarkNet" | "Stellar" | "Sui" | "Other";
12+
13+
export type CodingLanguage = "Cairo" | "GO" | "HUFF" | "Ink" | "Move" | "Noir" | "Other" | "Rain" | "Rust" | "Rust evm" | "Solidity" | "Vyper" | "Yui";
14+
1115
export interface ContestTileProps {
1216
/** An html `id` for the contest tile's wrapping div. */
1317
htmlId?: string;
@@ -38,6 +42,10 @@ export interface BountyTileData {
3842
bountyUrl: string;
3943
/** Absolute url to the bounty's source code. */
4044
repoUrl: string;
45+
/** Ecosystem being deployed to for the current contest. */
46+
ecosystem: ContestEcosystem;
47+
/** Coding language for the current contest. */
48+
languages: CodingLanguage[];
4149
/** Callback function to be triggered on bounty time/status changes. */
4250
updateBountyStatus?: () => void;
4351
}
@@ -57,6 +65,10 @@ export interface ContestTileData {
5765
findingsRepo: string;
5866
/** Absolute url to the contest's findings. */
5967
botFindingsRepo?: string;
68+
/** Ecosystem being deployed to for the current contest. */
69+
ecosystem: ContestEcosystem;
70+
/** Coding language for the current contest. */
71+
languages: CodingLanguage[];
6072
/** Reward pool for the current contest. */
6173
amount: string;
6274
/** Callback function to be triggered on contest time/status changes. */

0 commit comments

Comments
 (0)