Skip to content

Commit

Permalink
feat: add featured projects (#526)
Browse files Browse the repository at this point in the history
  • Loading branch information
LuizAsFight authored Sep 14, 2024
1 parent f80bcd2 commit 2ed0a23
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button, Flex, Input, Separator } from '@fuels/ui';
import { Button, Flex, Input, Separator, Switch, Text } from '@fuels/ui';
import { IconSearch } from '@tabler/icons-react';
import { PageTitle } from 'app-commons';
import { tv } from 'tailwind-variants';
Expand All @@ -7,10 +7,14 @@ export function EcosystemHeader({
disabled,
search,
onSearchChange,
onBuildingHiddenChange,
isBuildingHidden,
}: {
disabled?: boolean;
search?: string;
isBuildingHidden?: boolean;
onSearchChange?: (value: string) => void;
onBuildingHiddenChange?: (value: boolean) => void;
}) {
const classes = styles();

Expand Down Expand Up @@ -39,7 +43,16 @@ export function EcosystemHeader({
<IconSearch size={16} />
</Input.Slot>
</Input>
<Flex justify="end">
<Flex justify="between" flexBasis={'100%'}>
<label className={classes.switchLiveOnlyWrapper()}>
<Switch
defaultChecked={!isBuildingHidden}
mr="2"
onCheckedChange={onBuildingHiddenChange}
/>
{/* Show "Live" only */}
<Text color="gray">Show "Live" only</Text>
</label>
<Button
as="a"
href="https://airtable.com/appEO4t5bVydYgzCk/pagiUOEi5aqbtQK0T/form"
Expand All @@ -60,5 +73,7 @@ const styles = tv({
slots: {
searchBar: 'flex-col sm:justify-between sm:flex-row',
searchBarInput: 'w-full sm:w-[350px] h-[44px]',
switchLiveOnlyWrapper:
'flex flex-row items-center justify-between mr-2 ml-1',
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ export const ProjectItem: ProjectItemComponent = ({
status,
github,
isLive,
isFeatured,
}: ProjectItemProps) => {
const classes = styles();
const classes = styles({ isFeatured });

const onCardPress = () => {
window.open(url, '_blank');
Expand All @@ -57,6 +58,7 @@ export const ProjectItem: ProjectItemComponent = ({
})}
className={classes.card()}
onClick={onCardPress}
variant={isFeatured || isLive ? 'classic' : 'ghost'}
>
<Card.Body className={classes.body()}>
<ProjecImage name={name} image={image} />
Expand Down Expand Up @@ -137,7 +139,7 @@ export const ProjectItem: ProjectItemComponent = ({
</HStack>
</VStack>
</Card.Body>
<Card.Footer>
<Card.Footer className={classes.footer()}>
{status?.map((s, index) => (
<Badge
key={index}
Expand All @@ -149,6 +151,16 @@ export const ProjectItem: ProjectItemComponent = ({
{s}
</Badge>
))}
{isFeatured ? (
<Badge
color="yellow"
size="1"
className={classes.tag()}
variant="surface"
>
Featured
</Badge>
) : null}
{isLive ? (
<Badge
color="green"
Expand Down Expand Up @@ -178,7 +190,8 @@ const styles = tv({
card: [
'cursor-pointer gap-2',
'transition-all duration-200 ease-in-out',
'hover:border-1 hover:border-brand hover:scale-105',
'border-none border-brand',
'hover:border hover:border-solid hover:scale-105',
],
details: 'flex flex-col justify-between flex-1',
link: 'underline p-0 pointer-events-none text-sm',
Expand All @@ -194,6 +207,14 @@ const styles = tv({
textProjectName: 'text-heading',
textDescription: 'text-sm',
socialButton: 'bg-transparent',
footer: 'items-end',
},
variants: {
isFeatured: {
true: {
card: 'border border-solid border-yellow-7 hover:border-yellow-8 hover:border-2',
},
},
},
});

Expand Down
6 changes: 6 additions & 0 deletions packages/app-portal/src/systems/Ecosystem/data/projects.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
},
{
"isLive": false,
"isFeatured": true,
"name": "Fluid Protocol",
"url": "https://fluidprotocol.xyz/",
"tags": ["DeFi"],
Expand Down Expand Up @@ -243,6 +244,7 @@
},
{
"isLive": false,
"isFeatured": true,
"name": "Griffy",
"url": "https://griffy.app/",
"tags": ["Prediction Market"],
Expand Down Expand Up @@ -309,6 +311,7 @@
},
{
"isLive": true,
"isFeatured": true,
"name": "Mira Exchange",
"url": "https://mira.ly/",
"tags": ["DeFi"],
Expand Down Expand Up @@ -441,6 +444,7 @@
},
{
"isLive": true,
"isFeatured": true,
"name": "Spark",
"url": "https://sprk.fi/",
"tags": ["DeFi"],
Expand Down Expand Up @@ -485,6 +489,7 @@
},
{
"isLive": true,
"isFeatured": true,
"name": "Swaylend",
"url": "https://swaylend.com/",
"tags": ["DeFi"],
Expand All @@ -507,6 +512,7 @@
},
{
"isLive": false,
"isFeatured": true,
"name": "Thunder",
"url": "https://beta.thundernft.market/",
"tags": ["Marketplace", "NFT"],
Expand Down
28 changes: 27 additions & 1 deletion packages/app-portal/src/systems/Ecosystem/hooks/useEcosystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
import type { Project } from '../types';

const sortProjects = (a: Project, b: Project) => {
if (a.isFeatured && !b.isFeatured) return -1;
if (!a.isFeatured && b.isFeatured) return 1;
if (a.isLive && !b.isLive) return -1;
if (!a.isLive && b.isLive) return 1;

Expand All @@ -17,7 +19,16 @@ const sortProjects = (a: Project, b: Project) => {

const selectors = {
filteredProjects: (state: EcosystemMachineState) => {
const { projects = [], search, filter } = state.context;
const {
projects: _projects = [],
search,
filter,
isBuildingHidden,
} = state.context;

const projects = isBuildingHidden
? _projects
: _projects.filter((project) => project.isLive);

if (search) {
const filtered = projects.filter((project) => {
Expand All @@ -38,6 +49,8 @@ const selectors = {
tags: (state: EcosystemMachineState) => state.context?.tags,
filter: (state: EcosystemMachineState) => state.context?.filter,
search: (state: EcosystemMachineState) => state.context?.search,
isBuildingHidden: (state: EcosystemMachineState) =>
state.context?.isBuildingHidden,
isLoading: (state: EcosystemMachineState) => state.hasTag('isLoading'),
};

Expand All @@ -50,6 +63,10 @@ export function useEcosystem() {
const filter = store.useSelector(Services.ecosystem, selectors.filter);
const search = store.useSelector(Services.ecosystem, selectors.search);
const isLoading = store.useSelector(Services.ecosystem, selectors.isLoading);
const isBuildingHidden = store.useSelector(
Services.ecosystem,
selectors.isBuildingHidden,
);

useEffect(() => {
store.send(Services.ecosystem, {
Expand All @@ -70,16 +87,25 @@ export function useEcosystem() {
store.send(Services.ecosystem, { type: 'CLEAR_FILTER', input: null });
};

const toggleIsBuildingHidden = () => {
store.send(Services.ecosystem, {
type: 'TOGGLE_IS_BUILDING_HIDDEN',
input: null,
});
};

return {
filteredProjects,
tags,
filter,
search,
isLoading,
isBuildingHidden,
handlers: {
filterProjects,
searchProjects,
clearFilters,
toggleIsBuildingHidden,
},
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type MachineContext = {
search: string;
tags: string[];
filter: string;
isBuildingHidden: boolean;
};

type MachineServices = {
Expand Down Expand Up @@ -55,6 +56,10 @@ type EcosystemMachineEvents =
| {
type: 'CLEAR_FILTER';
input: null;
}
| {
type: 'TOGGLE_IS_BUILDING_HIDDEN';
input: null;
};

const initialState: MachineContext = {
Expand All @@ -63,6 +68,7 @@ const initialState: MachineContext = {
search: '',
tags: [],
filter: '',
isBuildingHidden: true,
};

export function sortAtoZ(a: string, b: string) {
Expand Down Expand Up @@ -103,6 +109,9 @@ export const ecosystemMachine = createMachine(
CLEAR_FILTER: {
actions: ['clearFilter'],
},
TOGGLE_IS_BUILDING_HIDDEN: {
actions: ['toggleIsBuildingHidden'],
},
},
},
fetching: {
Expand Down Expand Up @@ -165,6 +174,10 @@ export const ecosystemMachine = createMachine(
search: '',
filter: '',
})),
toggleIsBuildingHidden: assign((ctx) => ({
...ctx,
isBuildingHidden: !ctx.isBuildingHidden,
})),
},
},
);
Expand Down
18 changes: 15 additions & 3 deletions packages/app-portal/src/systems/Ecosystem/pages/Ecosystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ import { useEcosystem } from '../hooks/useEcosystem';

export function Ecosystem() {
const classes = styles();
const { tags, isLoading, filter, search, handlers, filteredProjects } =
useEcosystem();
const {
tags,
isLoading,
filter,
search,
handlers,
filteredProjects,
isBuildingHidden,
} = useEcosystem();

const handleSearch = (query: string) => {
handlers.searchProjects({ query });
Expand All @@ -24,7 +31,12 @@ export function Ecosystem() {

return (
<VStack gap="6" flexGrow="1" className={classes.content()}>
<EcosystemHeader search={search} onSearchChange={handleSearch} />
<EcosystemHeader
search={search}
onSearchChange={handleSearch}
onBuildingHiddenChange={handlers.toggleIsBuildingHidden}
isBuildingHidden={isBuildingHidden}
/>
<EcosystemTags
tags={tags}
activeTag={filter}
Expand Down
1 change: 1 addition & 0 deletions packages/app-portal/src/systems/Ecosystem/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export type Project = {
discord?: string;
status?: string[];
isLive?: boolean;
isFeatured?: boolean;
};

0 comments on commit 2ed0a23

Please sign in to comment.