Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: sync actual grant details #99

Merged
merged 3 commits into from
Aug 16, 2024
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
122 changes: 41 additions & 81 deletions src/grants/components/grant-card/grant-card.tsx
Original file line number Diff line number Diff line change
@@ -1,84 +1,35 @@
import { Avatar } from '@nextui-org/react';

import { PaperbillIcon } from '@/shared/components/icons/paperbill-icon';
import { cn } from '@/shared/utils/cn';

import { GRANT_TEST_IDS } from '@/grants/core/constants';
import { Grant } from '@/grants/core/schemas';
import {
DetailItemProps,
DetailItems,
} from '@/grants/components/ui/base/detail-item';
import { DetailValueAmount } from '@/grants/components/ui/base/detail-value-amount';
import { DetailValueAvatars } from '@/grants/components/ui/base/detail-value-avatars';
import { DetailValueTags } from '@/grants/components/ui/base/detail-value-tags';
import { DetailValueTexts } from '@/grants/components/ui/base/detail-value-text';
import { getGrantCardData } from '@/grants/utils/get-grant-card-data';
import { DetailItems } from '@/grants/components/ui/base/detail-item';
import { Title } from '@/grants/components/ui/base/title';
import { WebLinks } from '@/grants/components/ui/base/web-links';

const createTopItems = ({
granteesCount,
networks,
ecosystem,
totalFunds,
totalDisbursedFunds,
}: Grant): DetailItemProps[] => [
{ icon: <PaperbillIcon />, label: 'Grantees', value: granteesCount },
{ label: 'Networks', value: <DetailValueAvatars items={networks} /> },
{ label: 'Ecosystem', value: ecosystem },
{ label: 'Total Funds', value: <DetailValueAmount amount={totalFunds} /> },
{
label: 'Total Disbursed Funds',
value: <DetailValueAmount amount={totalDisbursedFunds} />,
},
];

const createMidItems = ({ summary, categories, type }: Grant) => [
{ value: summary },
{
label: 'Categories',
value: (
<DetailValueTexts
items={categories}
classNames={{
root: 'text-[#B1FFB1]',
text: 'border border-[#B1FFB1]',
}}
/>
),
},
{
label: 'Type',
value: (
<DetailValueTexts
items={[type]}
classNames={{
root: 'text-[#60BCFF]',
text: 'border border-[#60BCFF]',
}}
/>
),
},
];

const createLowerItems = ({ reputations }: Grant): DetailItemProps[] => [
{
label: 'Reputations',
value: <DetailValueTags items={reputations} />,
},
];

interface Props {
grant: Grant;
}

export const GrantCard = ({ grant }: Props) => {
// TODO: JOB-678

const { id, name, logo, url, discord, twitter } = grant;

const topItems = createTopItems(grant);
const midItems = createMidItems(grant);
const lowerItems = createLowerItems(grant);
const {
id,
logo,
name,
url,
discord,
twitter,
topItems,
hasTopItems,
midItems,
lowerItems,
hasLowerItems,
hasWebLinks,
} = getGrantCardData(grant);

return (
<div
Expand All @@ -89,29 +40,38 @@ export const GrantCard = ({ grant }: Props) => {
<div className="flex grow flex-col gap-4 lg:pr-24">
<Title className="text-2xl font-bold lg:text-32">{name}</Title>
<div className="flex flex-wrap gap-4">
<WebLinks links={{ url, discord, twitter }} />
<DetailItems
items={topItems}
classNames={{ container: 'gap-x-4 gap-y-1.5', root: 'text-13' }}
/>
{hasWebLinks && <WebLinks links={{ url, discord, twitter }} />}

{hasTopItems && (
<DetailItems
items={topItems}
classNames={{ container: 'gap-x-4 gap-y-1.5', root: 'text-13' }}
/>
)}
</div>

<DetailItems
items={midItems}
classNames={{
label: 'w-full pb-2 md:pb-0 md:w-auto lg:w-full lg:pb-2',
root: 'w-full md:w-auto first:text-white/75 lg:first:border-0 lg:first:py-0 lg:items-start lg:first:max-w-xl lg:flex-col lg:items-start',
container:
'gap-y-4 md:gap-x-6 lg:border-y md:border-t md:border-divider/25 md:pt-4 lg:grow lg:py-4 lg:border-divider/10 lg:w-full',
container: cn(
'gap-y-4 md:gap-x-6 md:border-divider/25 lg:w-full lg:grow lg:border-divider/10 lg:py-4',
{ 'md:border-t md:pt-4': hasTopItems },
),
}}
/>
<div className="border-t border-divider/10 pt-4 lg:border-none lg:pt-0">
<DetailItems
items={lowerItems}
classNames={{
label: 'hidden md:flex',
}}
/>
</div>

{hasLowerItems && (
<div className="border-t border-divider/10 pt-4 lg:border-none lg:pt-0">
<DetailItems
items={lowerItems}
classNames={{
label: 'hidden md:flex',
}}
/>
</div>
)}
</div>

<div className="hidden flex-col gap-4 lg:flex">
Expand Down
121 changes: 25 additions & 96 deletions src/grants/components/grant-list/grant-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,114 +3,41 @@ import Link from 'next/link';
import { Avatar, Button } from '@nextui-org/react';

import { cn } from '@/shared/utils/cn';
import { conditionalItem } from '@/shared/utils/conditional-item';
import { PaperbillIcon } from '@/shared/components/icons/paperbill-icon';

import { GRANT_TEST_IDS } from '@/grants/core/constants';
import { Grant } from '@/grants/core/schemas';
import {
DetailItemProps,
DetailItems,
} from '@/grants/components/ui/base/detail-item';
import { DetailValueAmount } from '@/grants/components/ui/base/detail-value-amount';
import { DetailValueAvatars } from '@/grants/components/ui/base/detail-value-avatars';
import { DetailValueTags } from '@/grants/components/ui/base/detail-value-tags';
import { DetailValueTexts } from '@/grants/components/ui/base/detail-value-text';
import { getGrantCardData } from '@/grants/utils/get-grant-card-data';
import { DetailItems } from '@/grants/components/ui/base/detail-item';
import { Title } from '@/grants/components/ui/base/title';
import { WebLinks } from '@/grants/components/ui/base/web-links/web-links';
import { CaretRightIcon } from '@/grants/components/ui/icons/caret-right-icon';

const createTopItems = ({
granteesCount,
networks,
ecosystem,
totalFunds,
totalDisbursedFunds,
}: Grant): DetailItemProps[] => [
...conditionalItem(granteesCount > 0, {
icon: <PaperbillIcon />,
label: 'Grantees:',
value: granteesCount,
}),
...conditionalItem(networks.length > 0, {
label: 'Networks:',
value: <DetailValueAvatars items={networks} />,
}),
...conditionalItem(!!ecosystem, { label: 'Ecosystem:', value: ecosystem }),
...conditionalItem(totalFunds > 0, {
label: 'Total Funds:',
value: <DetailValueAmount amount={totalFunds} />,
}),
...conditionalItem(totalDisbursedFunds > 0, {
label: 'Total Disbursed Funds:',
value: <DetailValueAmount amount={totalDisbursedFunds} />,
}),
];

const createMidItems = ({
summary,
categories,
type,
}: Grant): DetailItemProps[] => [
...conditionalItem(!!summary, { label: 'Summary:', value: summary }),
...conditionalItem(categories.length > 0, {
label: 'Categories',
value: (
<DetailValueTexts
items={categories}
classNames={{
root: 'text-[#B1FFB1]',
text: 'border border-[#B1FFB1]',
}}
/>
),
}),
...conditionalItem(!!type, {
label: 'Type',
value: (
<DetailValueTexts
items={[type]}
classNames={{
root: 'text-[#60BCFF]',
text: 'border border-[#60BCFF]',
}}
/>
),
}),
];

const createLowerItems = ({ reputations }: Grant): DetailItemProps[] => [
...conditionalItem(reputations.length > 0, {
label: 'Reputations',
value: <DetailValueTags items={reputations} />,
}),
];

interface Props {
grant: Grant;
}

export const GrantListItem = ({ grant }: Props) => {
// TODO: JOB-679

const { id, name, logo, url, discord, twitter } = grant;

const href = `/grants/${id}`;

const topItems = createTopItems(grant);
const hasTopItems = topItems.length > 0;

const midItems = createMidItems(grant);

const lowerItems = createLowerItems(grant);
const hasLowerItems = lowerItems.length > 0;

const hasWebLinks = !!url || !!discord || !!twitter;
const {
id,
logo,
name,
url,
discord,
twitter,
topItems,
hasTopItems,
midItems,
lowerItems,
hasLowerItems,
hasWebLinks,
} = getGrantCardData(grant);

return (
<Link
prefetch
href={href}
href={`/grants/${id}`}
className="flex flex-wrap items-center justify-between rounded-2xl bg-gradient-to-r from-[#191919] to-[#0D0D0D] p-4 text-13 text-white transition-all duration-300 md:p-5 lg:flex-nowrap"
data-uuid={id}
data-testid={GRANT_TEST_IDS.GRANT_ITEM}
Expand Down Expand Up @@ -156,12 +83,14 @@ export const GrantListItem = ({ grant }: Props) => {
}}
/>

<DetailItems
items={lowerItems}
classNames={{
label: 'pb-2 md:pb-0',
}}
/>
{hasLowerItems && (
<DetailItems
items={lowerItems}
classNames={{
label: 'pb-2 md:pb-0',
}}
/>
)}
</div>
</div>
<div className="flex w-full items-center justify-end gap-4 pt-6 lg:max-w-[180px] lg:pt-0">
Expand Down
3 changes: 1 addition & 2 deletions src/grants/core/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ export const GRANT_TEST_IDS = {
} as const;

export const GRANT_QUERY_URLS = {
GRANT_DETAILS: `${MW_URL}/grants/details`,
GRANT_LIST: `${MW_URL}/grants`,
BASE: `${MW_URL}/grants`,
GRANTEE_DETAILS: `${MW_URL}/grantees/details`,
GRANTEE_LIST: `${MW_URL}/grantees/list`,
GRANTEE_PROJECT: `${MW_URL}/grantees/project`,
Expand Down
2 changes: 1 addition & 1 deletion src/grants/data/get-grant-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { dtoToGrant } from '@/grants/utils/dto-to-grant';

export const getGrantDetails = async (grantId: string): Promise<Grant> => {
const response = await mwGET({
url: `${GRANT_QUERY_URLS.GRANT_DETAILS}/${grantId}`,
url: `${GRANT_QUERY_URLS.BASE}/${grantId}`,
label: 'getGrant',
responseSchema: grantDetailsDtoSchema,
options: { next: { revalidate: 3600 } },
Expand Down
2 changes: 1 addition & 1 deletion src/grants/data/get-grant-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const getGrantList = async (
searchParams = '',
): Promise<GrantInfiniteListPage> => {
const url = createUrlWithSearchParams(
`${GRANT_QUERY_URLS.GRANT_LIST}?page=${page}&limit=${PAGE_SIZE}`,
`${GRANT_QUERY_URLS.BASE}?page=${page}&limit=${PAGE_SIZE}`,
searchParams,
);

Expand Down
2 changes: 1 addition & 1 deletion src/grants/data/get-grantees-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const getGranteesList = async ({

return mwGET({
url,
label: 'getGrantList',
label: 'getGranteeList',
responseSchema: granteeListQueryPageSchema,
options: { next: { revalidate: 60 * 60 } },
});
Expand Down
2 changes: 1 addition & 1 deletion src/grants/testutils/mock-grant-list-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export const mockGrantListQuery = (
) =>
mockInfiniteListQuery(
{
url: GRANT_QUERY_URLS.GRANT_LIST,
url: GRANT_QUERY_URLS.BASE,
data: Array.from({ length: 10 }).map(() => fakeGrant()),
},
result,
Expand Down
2 changes: 1 addition & 1 deletion src/grants/testutils/mock-grant-query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const mockGrantQuery = (
result: MockQueryResult,
options?: MswOptions & { data?: Grant },
) =>
http.get(`${GRANT_QUERY_URLS.GRANT_DETAILS}/:grantId`, async ({ params }) => {
http.get(`${GRANT_QUERY_URLS.BASE}/:grantId`, async ({ params }) => {
const { networkDelay } = options || DEFAULT_MSW_OPTIONS;
await delay(networkDelay);

Expand Down
Loading
Loading