Skip to content

Commit

Permalink
Admin page tweaks (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
carletex authored Feb 22, 2024
1 parent 3bdf9f9 commit 298adf2
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 21 deletions.
65 changes: 52 additions & 13 deletions packages/nextjs/app/admin/_components/GrantReview.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { useSWRConfig } from "swr";
import useSWRMutation from "swr/mutation";
import { useAccount, useSignTypedData } from "wagmi";
import { GrantData } from "~~/services/database/schema";
import TelegramIcon from "~~/components/assets/TelegramIcon";
import TwitterIcon from "~~/components/assets/TwitterIcon";
import { Address } from "~~/components/scaffold-eth";
import { GrantData, GrantDataWithBuilder, SocialLinks } from "~~/services/database/schema";
import { EIP_712_DOMAIN, EIP_712_TYPES__REVIEW_GRANT } from "~~/utils/eip712";
import { PROPOSAL_STATUS, ProposalStatusType } from "~~/utils/grants";
import { notification } from "~~/utils/scaffold-eth";
Expand All @@ -13,7 +16,36 @@ type ReqBody = {
action: ProposalStatusType;
};

export const GrantReview = ({ grant }: { grant: GrantData }) => {
const BuilderSocials = ({ socialLinks }: { socialLinks?: SocialLinks }) => {
if (!socialLinks) return null;

return (
<>
{socialLinks?.twitter && (
<a
className="inline-block w-[20px] hover:opacity-80"
href={`https://twitter.com/${socialLinks?.twitter}`}
target="_blank"
rel="noreferrer"
>
<TwitterIcon />
</a>
)}
{socialLinks?.telegram && (
<a
className="inline-block w-[20px] hover:opacity-80"
href={`https://telegram.me/${socialLinks?.telegram}`}
target="_blank"
rel="noreferrer"
>
<TelegramIcon />
</a>
)}
</>
);
};

export const GrantReview = ({ grant }: { grant: GrantDataWithBuilder }) => {
const { address } = useAccount();
const { signTypedDataAsync, isLoading: isSigningMessage } = useSignTypedData();
const { trigger: postReviewGrant, isMutating: isPostingNewGrant } = useSWRMutation(
Expand Down Expand Up @@ -70,25 +102,32 @@ export const GrantReview = ({ grant }: { grant: GrantData }) => {
{grant.title}
<span className="text-sm text-gray-500 ml-2">({grant.id})</span>
</h3>
<div className="flex gap-4 items-center">
<a
href={`https://app.buidlguidl.com/builders/${grant.builder}`}
className="inline-block"
target="_blank"
rel="noreferrer"
>
<Address address={grant.builder} disableAddressLink />
</a>
<BuilderSocials socialLinks={grant.builderData?.socialLinks} />
</div>
<p>{grant.description}</p>
<div className="mt-4">
<div className="flex gap-4 mt-4 justify-end">
<button
className={`bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded ${
isLoading ? "opacity-50" : ""
}`}
onClick={() => handleReviewGrant(grant, acceptStatus)}
className={`btn btn-sm btn-error ${isLoading ? "opacity-50" : ""}`}
onClick={() => handleReviewGrant(grant, PROPOSAL_STATUS.REJECTED)}
disabled={isLoading}
>
{acceptLabel}
Reject
</button>
<button
className={`bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded ml-4 ${
isLoading ? "opacity-50" : ""
}`}
onClick={() => handleReviewGrant(grant, PROPOSAL_STATUS.REJECTED)}
className={`btn btn-sm btn-success ${isLoading ? "opacity-50" : ""}`}
onClick={() => handleReviewGrant(grant, acceptStatus)}
disabled={isLoading}
>
Reject
{acceptLabel}
</button>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions packages/nextjs/app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import { GrantReview } from "./_components/GrantReview";
import useSWR from "swr";
import { GrantData } from "~~/services/database/schema";
import { GrantDataWithBuilder } from "~~/services/database/schema";
import { PROPOSAL_STATUS } from "~~/utils/grants";
import { notification } from "~~/utils/scaffold-eth";

// ToDo. "Protect" with address header or PROTECT with signing the read.
const AdminPage = () => {
// TODO: Move the response type to a shared location
const { data, isLoading } = useSWR<{ data: GrantData[] }>("/api/grants/review", {
const { data, isLoading } = useSWR<{ data: GrantDataWithBuilder[] }>("/api/grants/review", {
onError: error => {
console.error("Error fetching grants", error);
notification.error("Error getting grants data");
Expand Down
13 changes: 13 additions & 0 deletions packages/nextjs/components/assets/TelegramIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

const TelegramIcon = (props: React.JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>) => (
<svg {...props} role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<title>Telegram</title>
<path
d="M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"
fill="#0088cc"
/>
</svg>
);

export default TelegramIcon;
13 changes: 13 additions & 0 deletions packages/nextjs/components/assets/TwitterIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from "react";

const TwitterIcon = (props: React.JSX.IntrinsicAttributes & React.SVGProps<SVGSVGElement>) => (
<svg {...props} role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<title>Twitter</title>
<path
d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"
fill="currentColor"
/>
</svg>
);

export default TwitterIcon;
19 changes: 14 additions & 5 deletions packages/nextjs/services/database/grants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getFirestoreConnector } from "./firestoreDB";
import { GrantData } from "./schema";
import { BuilderData, GrantData, GrantDataWithBuilder } from "./schema";
import { findUserByAddress } from "~~/services/database/users";
import { PROPOSAL_STATUS, ProposalStatusType } from "~~/utils/grants";

const firestoreDB = getFirestoreConnector();
Expand Down Expand Up @@ -55,11 +56,19 @@ export const getAllGrantsForReview = async () => {
const grantsSnapshot = await grantsCollection
.where("status", "in", [PROPOSAL_STATUS.PROPOSED, PROPOSAL_STATUS.SUBMITTED])
.get();
const grants: GrantData[] = [];
grantsSnapshot.forEach(doc => {
grants.push({ id: doc.id, ...doc.data() } as GrantData);

const grantsPromises = grantsSnapshot.docs.map(async doc => {
const grantData = doc.data() as Omit<GrantData, "id">;
const builderDataResponse = await findUserByAddress(grantData.builder);

return {
id: doc.id,
...grantData,
builderData: builderDataResponse.exists ? (builderDataResponse.data as BuilderData) : undefined,
} as GrantDataWithBuilder;
});
return grants;

return await Promise.all(grantsPromises);
} catch (error) {
console.error("Error getting all completed grants:", error);
throw error;
Expand Down
4 changes: 3 additions & 1 deletion packages/nextjs/services/database/schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
type SocialLinks = {
export type SocialLinks = {
twitter?: string;
github?: string;
discord?: string;
Expand Down Expand Up @@ -50,3 +50,5 @@ export type GrantData = {
// proposed and submited timestamp are imp
status: "proposed" | "approved" | "submitted" | "completed" | "rejected";
};

export type GrantDataWithBuilder = GrantData & { builderData?: BuilderData };

0 comments on commit 298adf2

Please sign in to comment.