Skip to content
This repository has been archived by the owner on Feb 10, 2025. It is now read-only.

Commit

Permalink
fix: add ApplicationSummary to EvaluationView page (#87)
Browse files Browse the repository at this point in the history
* fix: add ApplicationSummary to EvaluationView page

- refactor ApplicationSummary into component
- reuse in SubmitEvaluation
- wire it into EvaluationView page
- rename gray -> grey
- update ApplicationSummary component to accordian

closes PAR-688

* address feedback
  • Loading branch information
thelostone-mc authored Dec 11, 2024
1 parent 301a3d6 commit c3a42cb
Show file tree
Hide file tree
Showing 13 changed files with 372 additions and 165 deletions.
4 changes: 2 additions & 2 deletions src/components/pool/components/PoolSummary/PoolSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const PoolSummary = (pool: PoolSummaryProps) => {
<div className="flex items-end gap-6">
<Button
icon={<Icon type={IconType.LINK} />}
className="border-gray-100 bg-white text-black shadow-sm"
className="border-grey-100 bg-white text-black shadow-sm"
value="Round application"
onClick={() => {
navigator.clipboard.writeText(applyLink).then(
Expand All @@ -125,7 +125,7 @@ export const PoolSummary = (pool: PoolSummaryProps) => {
/>
<Button
icon={<Icon type={IconType.EXPLORER} />}
className="border-gray-100 bg-white text-black shadow-sm"
className="border-grey-100 bg-white text-black shadow-sm"
value="View round"
onClick={() => window.open(explorerLink, "_blank")}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Meta, Title, Primary, Stories, Controls, Story } from "@storybook/blocks";

import { ApplicationSummary } from "./ApplicationSummary";

import * as ApplicationSummaryStories from "./ApplicationSummary.stories";

<Meta of={ApplicationSummaryStories} />

# ApplicationSummary

The `ApplicationSummary` component provides a detailed view of a project, its current application, and any past applications.

## Examples

<Story of={ApplicationSummaryStories.Default} />

# Controls

<Controls />

# Other variations

<Stories />
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Meta, StoryObj } from "@storybook/react";

import { ApplicationSummary } from "./ApplicationSummary";
import { project, application, pastApplications } from "./mocks";

const meta: Meta<typeof ApplicationSummary> = {
title: "Components/project/ApplicationSummary",
component: ApplicationSummary,
argTypes: {
project: { control: "object", description: "Metadata about the project." },
application: { control: "object", description: "Current application details." },
pastApplications: { control: "object", description: "List of past applications." },
},
};

export default meta;

type Story = StoryObj<typeof ApplicationSummary>;

export const Default: Story = {
args: {
project,
application,
pastApplications,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { ApplicationBadge, ApplicationBadgeStatus, IconLabel, ProjectSummary } from "@/components";
import { PastApplication, ProjectApplication, ProjectMetadata } from "@/features/checker";
import { DateFormat, formatDate } from "@/lib/dates/formatDate";
import { Accordion, IconType, ListGrid, ListGridColumn, Markdown } from "@/primitives";

export enum SummaryAccordians {
project = "project",
projectDetails = "projectDetails",
applicationAnswers = "applicationAnswers",
pastApplications = "pastApplications",
}

export const ApplicationSummary = ({
project,
application,
pastApplications,
hideAccordians,
className,
}: {
project: ProjectMetadata;
application: ProjectApplication;
pastApplications: PastApplication[];
hideAccordians?: SummaryAccordians[];
className?: string;
}) => {
const columns: ListGridColumn<PastApplication>[] = pastApplications
? [
{
header: "Status",
key: "status",
width: "0.5fr",
render: (item) => {
let status;
// Determine the badge properties based on the status
if (item.status === "REJECTED") {
status = ApplicationBadgeStatus.Rejected;
} else if (item.status === "APPROVED") {
status = ApplicationBadgeStatus.Approved;
} else {
status = ApplicationBadgeStatus.Pending;
}
return <ApplicationBadge status={status} />;
},
},
{
header: "Date",
key: "createdAtBlock",
width: "1.2fr",
render: (item) => (
<span className="text-[16px]/[24px]">
{formatDate(new Date(item.statusSnapshots[0]?.updatedAt), DateFormat.FullDate24Hour)}
</span>
),
},
{
header: "Round",
key: "name",
width: "1.8fr",
render: (item) => <p className="text-[16px]/[24px]">{item.round.roundMetadata.name}</p>,
},
]
: [];

return (
<div className={`${className} flex w-full flex-col gap-4`}>
{!hideAccordians?.includes(SummaryAccordians.project) && (
<Accordion
header={
<IconLabel
type="default"
label={project.title}
iconType={IconType.GLOBE}
iconVariant="text-lg font-medium"
/>
}
isOpen={true}
content={<ProjectSummary projectMetadata={project} application={application} />}
variant="default"
border="none"
padding="none"
/>
)}

{!hideAccordians?.includes(SummaryAccordians.projectDetails) && (
<Accordion
header={
<IconLabel
type="default"
label="Project details"
iconType={IconType.CLIPBOARD_LIST}
iconVariant="text-lg font-medium"
/>
}
content={<Markdown>{project.description}</Markdown>}
variant="default"
border="none"
padding="none"
isOpen={false}
/>
)}

{!hideAccordians?.includes(SummaryAccordians.applicationAnswers) && (
<Accordion
header={
<IconLabel
type="default"
label="Application answers"
iconType={IconType.STAR}
iconVariant="text-lg font-medium"
/>
}
content={
<div className="flex flex-col gap-4">
{application.metadata.application.answers.map((answer, index) => {
if (answer.encryptedAnswer || !answer.answer) {
return null;
}
return (
<div key={index} className="flex flex-col gap-2">
<span className="font-ui-sans text-[16px]/[24px] font-bold">
{answer.question}
</span>
<span className="font-ui-sans text-[16px]/[24px] font-normal">
<Markdown>{answer.answer}</Markdown>
</span>
</div>
);
})}
</div>
}
variant="default"
border="none"
padding="none"
isOpen={false}
/>
)}
{!hideAccordians?.includes(SummaryAccordians.pastApplications) && (
<Accordion
header={
<IconLabel
type="default"
label="Past applications"
iconType={IconType.INFORMATION_CIRCLE}
iconVariant="text-lg font-medium"
/>
}
content={
pastApplications ? (
<div>
<ListGrid
data={pastApplications}
columns={columns}
rowClassName="h-[72px]"
getRowKey={(item: PastApplication) => `${item.id}-${item.roundId}`}
/>
</div>
) : (
<div>No past applications</div>
)
}
variant="default"
border="none"
padding="none"
isOpen={false}
/>
)}
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import "./ApplicationSummary";
101 changes: 101 additions & 0 deletions src/components/project/components/ApplicationSummary/mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
ProjectMetadata,
CheckerApplication,
ApplicationStatus,
PastApplication,
} from "@/features/checker";

export const project: ProjectMetadata = {
title: "Sample Project",
description: "An example project description to showcase ApplicationSummary.",
website: "https://example.com",
bannerImg: "sampleBannerCID",
logoImg: "sampleLogoCID",
projectTwitter: "exampleproject",
userGithub: "exampleuser",
projectGithub: "exampleproject",
credentials: {},
owners: [{ address: "0x1234567890abcdef1234567890abcdef12345678" }],
recipient: "0x1234567890abcdef1234567890abcdef12345678",
createdAt: 1672531200, // Timestamp for Jan 1, 2023
lastUpdated: 1675119600, // Timestamp for Feb 1, 2023
};

export const application: CheckerApplication = {
id: "application-123",
projectId: "project-123",
chainId: 1,
roundId: "round-1",
status: ApplicationStatus.APPROVED,
metadataCid: "bafybeihsamplemetadata",
metadata: {
signature: "0xsamplesignature",
application: {
round: "Round 1",
answers: [
{
type: "text",
hidden: false,
question: "What is the purpose of your project?",
questionId: 1,
answer: "To make the world a better place.",
},
{
type: "text",
hidden: false,
question: "Who is your target audience?",
questionId: 2,
answer: "Developers, creators, and tech enthusiasts.",
},
],
project,
recipient: "0x1234567890abcdef1234567890abcdef12345678",
},
},
distributionTransaction: null,
totalAmountDonatedInUsd: 10000,
totalDonationsCount: 500,
uniqueDonorsCount: 100,
anchorAddress: "0xanchoraddress1234567890abcdef12345678",
statusSnapshots: [
{
status: ApplicationStatus.APPROVED,
updatedAtBlock: "123456",
updatedAt: "2023-01-01T00:00:00Z",
},
],
canonicalProject: {
roles: [{ address: "0xroleaddress1234567890abcdef12345678" }],
},
alloApplicationId: "",
evaluations: [],
};

export const pastApplications: PastApplication[] = [
{
id: "past-1",
roundId: "round-1",
statusSnapshots: [
{
status: ApplicationStatus.APPROVED,
updatedAtBlock: "123456",
updatedAt: "2023-01-01T00:00:00Z",
},
],
status: ApplicationStatus.APPROVED,
round: { roundMetadata: { name: "Round 1" } },
},
{
id: "past-2",
roundId: "round-2",
statusSnapshots: [
{
status: ApplicationStatus.REJECTED,
updatedAtBlock: "123457",
updatedAt: "2023-02-01T00:00:00Z",
},
],
status: ApplicationStatus.REJECTED,
round: { roundMetadata: { name: "Round 2" } },
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import * as React from "react";
import { IconLabel } from "@/components/IconLabel";
// import { useCredentialverification } from "@/features/checker/hooks";
import { ProjectApplicationForManager, ProjectMetadata } from "@/features/checker/services/allo";
import { IconType } from "@/primitives/Icon";
import { useCredentialVerification } from "@/hooks/useCredentialVerification";
import { IconType } from "@/primitives/Icon";

export interface ProjectSummaryProps {
projectMetadata: ProjectMetadata;
Expand Down Expand Up @@ -40,15 +40,15 @@ export const ProjectSummary: React.FC<ProjectSummaryProps> = ({ projectMetadata,
<div className="flex flex-col gap-4">
{createdAt && (
<IconLabel
className="text-gray-700"
className="text-grey-700"
type="default"
iconType={IconType.CALENDAR}
label={appliedOnLabel}
/>
)}
{(createdAt || lastUpdated) && (
<IconLabel
className="text-gray-700"
className="text-grey-700"
type="default"
iconType={IconType.CALENDAR}
label={lastEditedLabel}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ export const Default: Story = {
},
},
args: {
chainId: 42161,
poolId: "609",
applicationId: "17",
chainId: 11155111,
poolId: "605",
applicationId: "1",
address: "0x0D1781F0b693b35939A49831A6C799B938Bd2F80",
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const ApplicationEvaluationOverviewPage = ({
avatarPosition="left"
/>
<h1 className="text-3xl font-medium leading-9">{project.title}</h1>
<div className="h-0.5 bg-[#EAEAEA]" />
<div className="h-0.5 bg-grey-200" />
<p className="leading-9 text-grey-900">
Evaluate this project and see how others have evaluated this project.
</p>
Expand Down
Loading

0 comments on commit c3a42cb

Please sign in to comment.