Skip to content

Commit

Permalink
move eligibility flag to dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
ChangoMan committed Aug 29, 2024
1 parent d9f1cb1 commit 08ccbbe
Show file tree
Hide file tree
Showing 2 changed files with 136 additions and 95 deletions.
98 changes: 3 additions & 95 deletions packages/nextjs/app/admin/_components/SubmissionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,22 @@

import { useRouter } from "next/navigation";
import { SubmissionComments } from "./SubmissionComments";
import { SubmissionEligible } from "./SubmissionEligible";
import "./submission-rating.css";
import { useMutation } from "@tanstack/react-query";
import { useAccount } from "wagmi";
import { QuestionMarkCircleIcon } from "@heroicons/react/24/outline";
import { Address } from "~~/components/scaffold-eth";
import { Submission } from "~~/services/database/repositories/submissions";
import { getFormattedDateTime } from "~~/utils/date";
import { postMutationFetcher } from "~~/utils/react-query";
import { notification } from "~~/utils/scaffold-eth";

const eligibleLabelStyles = "label cursor-pointer text-sm justify-start gap-2";

export const SubmissionCard = ({ submission }: { submission: Submission }) => {
const { address: connectedAddress } = useAccount();

const { mutateAsync: postNewVote } = useMutation({
mutationFn: (newVote: { score: number }) =>
postMutationFetcher(`/api/submissions/${submission.id}/votes`, { body: newVote }),
});
const { mutateAsync: postNewEligible } = useMutation({
mutationFn: (newEligible: { eligible: boolean; clear: boolean }) =>
postMutationFetcher(`/api/submissions/${submission.id}/eligible`, { body: newEligible }),
});
const { refresh } = useRouter();

const vote = async (newScore: number) => {
Expand All @@ -47,36 +40,6 @@ export const SubmissionCard = ({ submission }: { submission: Submission }) => {
}
};

const setEligible = async (newEligible: boolean) => {
try {
const result = await postNewEligible({ eligible: newEligible, clear: false });

notification.success(result.message);
refresh();
} catch (error: any) {
if (error instanceof Error) {
notification.error(error.message);
return;
}
notification.error("Something went wrong");
}
};

const clearEligible = async () => {
try {
const result = await postNewEligible({ eligible: false, clear: true });

notification.success(result.message);
refresh();
} catch (error: any) {
if (error instanceof Error) {
notification.error(error.message);
return;
}
notification.error("Something went wrong");
}
};

const scoreAvg =
submission.votes.length > 0
? (submission.votes.map(vote => vote.score).reduce((a, b) => a + b, 0) / submission.votes.length).toFixed(2)
Expand All @@ -88,7 +51,8 @@ export const SubmissionCard = ({ submission }: { submission: Submission }) => {

return (
<div key={submission.id} className="card bg-base-200 text-secondary-content border border-gray-300 rounded-none">
<div className="card-body p-4">
<SubmissionEligible submission={submission} />
<div className="card-body p-4 pt-6">
<h2 className="card-title mb-3 xl:text-2xl">{submission.title}</h2>
<div className="flex flex-wrap justify-between items-center gap-4">
<div className="mt-1 flex shrink-0 gap-3">
Expand Down Expand Up @@ -117,62 +81,6 @@ export const SubmissionCard = ({ submission }: { submission: Submission }) => {

<div className="divider my-0" />

<div className="flex items-center gap-3">
<div className="form-control">
<label className={eligibleLabelStyles} htmlFor={`eligible_${submission.id}_false`}>
<input
type="radio"
id={`eligible_${submission.id}_false`}
name={`eligible_${submission.id}`}
className="radio checked:bg-opacity-60"
checked={submission.eligible === false}
onChange={() => setEligible(false)}
/>
<span className="label-text">Not Eligible</span>
</label>
</div>
<div className="form-control">
<label className={eligibleLabelStyles} htmlFor={`eligible_${submission.id}_true`}>
<input
type="radio"
id={`eligible_${submission.id}_true`}
name={`eligible_${submission.id}`}
className="radio checked:bg-opacity-60"
checked={submission.eligible === true}
onChange={() => setEligible(true)}
/>
<span className="label-text">Eligible</span>
</label>
</div>
<div className="ml-auto flex items-center gap-3">
{submission.eligible === false && (
<div
className="tooltip"
data-tip={`Set by ${submission.eligibleAdmin} on ${submission.eligibleTimestamp ? getFormattedDateTime(new Date(submission.eligibleTimestamp)) : ""}`}
>
<QuestionMarkCircleIcon className="w-4 h-4" />
</div>
)}

{submission.eligible === true && (
<div
className="tooltip"
data-tip={`Set by ${submission.eligibleAdmin} on ${submission.eligibleTimestamp ? getFormattedDateTime(new Date(submission.eligibleTimestamp)) : ""}`}
>
<QuestionMarkCircleIcon className="w-4 h-4" />
</div>
)}

{submission.eligible !== undefined && (
<button className="cursor-pointer underline text-sm hover:no-underline" onClick={clearEligible}>
Clear
</button>
)}
</div>
</div>

<div className="divider my-0" />

<div className="flex items-center justify-between">
<div className="rating flex items-center">
<input
Expand Down
133 changes: 133 additions & 0 deletions packages/nextjs/app/admin/_components/SubmissionEligible.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"use client";

import { useRouter } from "next/navigation";
import "./submission-rating.css";
import { useMutation } from "@tanstack/react-query";
import clsx from "clsx";
import { QuestionMarkCircleIcon } from "@heroicons/react/24/outline";
import { Submission } from "~~/services/database/repositories/submissions";
import { getFormattedDateTime } from "~~/utils/date";
import { postMutationFetcher } from "~~/utils/react-query";
import { notification } from "~~/utils/scaffold-eth";

const eligibleLabelStyles = "label cursor-pointer text-sm justify-start gap-2";

export const SubmissionEligible = ({ submission }: { submission: Submission }) => {
const { mutateAsync: postNewEligible } = useMutation({
mutationFn: (newEligible: { eligible: boolean; clear: boolean }) =>
postMutationFetcher(`/api/submissions/${submission.id}/eligible`, { body: newEligible }),
});
const { refresh } = useRouter();

const setEligible = async (newEligible: boolean) => {
try {
const result = await postNewEligible({ eligible: newEligible, clear: false });

notification.success(result.message);
refresh();
} catch (error: any) {
if (error instanceof Error) {
notification.error(error.message);
return;
}
notification.error("Something went wrong");
}
};

const clearEligible = async () => {
try {
const result = await postNewEligible({ eligible: false, clear: true });

notification.success(result.message);
refresh();
} catch (error: any) {
if (error instanceof Error) {
notification.error(error.message);
return;
}
notification.error("Something went wrong");
}
};

let buttonLabel = "Eligibility";
if (submission.eligible === false) {
buttonLabel = "Not Eligible";
}
if (submission.eligible === true) {
buttonLabel = "Eligible";
}

console.log("submission", submission.eligible);

return (
<details className="dropdown dropdown-end">
<summary
className={clsx("absolute top-0 right-0 btn btn-xs border-0 font-medium text-gray-200 tracking-tighter", {
"text-gray-600 bg-gray-300 hover:bg-gray-400": submission.eligible === null,
"bg-red-800 hover:bg-red-700": submission.eligible === false,
"bg-green-800 hover:bg-green-700": submission.eligible === true,
})}
>
{buttonLabel}
</summary>
<div
tabIndex={0}
className="dropdown-content bg-base-100 z-[1] w-auto py-2 px-3 top-7 border border-gray-200 shadow"
>
<div className="flex flex-col">
<div className="form-control">
<label className={eligibleLabelStyles} htmlFor={`eligible_${submission.id}_false`}>
<input
type="radio"
id={`eligible_${submission.id}_false`}
name={`eligible_${submission.id}`}
className="radio checked:bg-opacity-60"
checked={submission.eligible === false}
onChange={() => setEligible(false)}
/>
<span className="label-text tracking-tight">Not Eligible</span>
</label>
</div>
<div className="form-control">
<label className={eligibleLabelStyles} htmlFor={`eligible_${submission.id}_true`}>
<input
type="radio"
id={`eligible_${submission.id}_true`}
name={`eligible_${submission.id}`}
className="radio checked:bg-opacity-60"
checked={submission.eligible === true}
onChange={() => setEligible(true)}
/>
<span className="label-text tracking-tight">Eligible</span>
</label>
</div>
<div className="flex items-center justify-between gap-3 p-2">
{submission.eligible !== undefined && (
<button className="cursor-pointer underline text-sm hover:no-underline" onClick={clearEligible}>
Clear
</button>
)}

{submission.eligible === false && (
<div
className="tooltip before:w-96"
data-tip={`Set by ${submission.eligibleAdmin} on ${submission.eligibleTimestamp ? getFormattedDateTime(new Date(submission.eligibleTimestamp)) : ""}`}
>
<QuestionMarkCircleIcon className="w-4 h-4" />
</div>
)}

{submission.eligible === true && (
<div
className="tooltip"
data-tip={`Set by ${submission.eligibleAdmin} on ${submission.eligibleTimestamp ? getFormattedDateTime(new Date(submission.eligibleTimestamp)) : ""}`}
>
<QuestionMarkCircleIcon className="w-4 h-4" />
</div>
)}
</div>
</div>
</div>
</details>
);
};

0 comments on commit 08ccbbe

Please sign in to comment.