From 44e745692d30baa2e64766f48a64e9fe4e99a12f Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Thu, 26 May 2022 21:49:48 +0300 Subject: [PATCH] Add comment to database --- app/components/Dialog.tsx | 1 + app/permissions.ts | 44 ++++++++++---------- app/routes/plus/suggestions.tsx | 24 ++++++----- app/routes/plus/suggestions/comment.tsx | 54 ++++++++++++++++++++----- app/utils/remix.ts | 8 ++++ app/utils/zod.ts | 6 +++ 6 files changed, 93 insertions(+), 44 deletions(-) diff --git a/app/components/Dialog.tsx b/app/components/Dialog.tsx index a5769142a..c3f2448f7 100644 --- a/app/components/Dialog.tsx +++ b/app/components/Dialog.tsx @@ -49,6 +49,7 @@ function useDOMSync(isOpen: boolean) { if (isOpen) { dialog.showModal(); + // TODO: can be replaced with https://twitter.com/argyleink/status/1529869352660439048 once gets control html.classList.add("lock-scroll"); } else { dialog.close(); diff --git a/app/permissions.ts b/app/permissions.ts index 88ff3e231..8c1cd00d3 100644 --- a/app/permissions.ts +++ b/app/permissions.ts @@ -4,8 +4,8 @@ import { allTruthy } from "./utils/arrays"; interface CanAddCommentToSuggestionFEArgs { user?: Pick; - allSuggestions: plusSuggestions.FindResult; - target: Pick; + suggestions: plusSuggestions.FindResult; + suggested: { id: User["id"]; plusTier: NonNullable }; } export function canAddCommentToSuggestionFE( args: CanAddCommentToSuggestionFEArgs @@ -16,18 +16,16 @@ export function canAddCommentToSuggestionFE( interface CanAddCommentToSuggestionBEArgs extends CanAddCommentToSuggestionFEArgs { user?: Pick; - targetPlusTier: number; } export function canAddCommentToSuggestionBE({ user, - targetPlusTier, - allSuggestions, - target, + suggestions, + suggested, }: CanAddCommentToSuggestionBEArgs) { return allTruthy([ - canAddCommentToSuggestionFE({ user, allSuggestions, target }), - playerAlreadySuggested({ allSuggestions, target }), - targetPlusTierIsSmallerOrEqual({ user, targetPlusTier }), + canAddCommentToSuggestionFE({ user, suggestions, suggested }), + playerAlreadySuggested({ suggestions, suggested }), + targetPlusTierIsSmallerOrEqual({ user, suggested }), ]); } @@ -46,31 +44,31 @@ export function canAddCommentToSuggestionBE({ function alreadyCommentedByUser({ user, - allSuggestions, - target, + suggestions, + suggested, }: CanAddCommentToSuggestionFEArgs) { return Boolean( - allSuggestions - .find(({ tier }) => tier === target.plusTier) - ?.users.find((u) => u.info.id === target.id) + suggestions + .find(({ tier }) => tier === suggested.plusTier) + ?.users.find((u) => u.info.id === suggested.id) ?.suggestions.some((s) => s.author.id === user?.id) ); } function playerAlreadySuggested({ - allSuggestions, - target, -}: Pick) { + suggestions, + suggested, +}: Pick) { return Boolean( - allSuggestions - .find(({ tier }) => tier === target.plusTier) - ?.users.find((u) => u.info.id === target.id) + suggestions + .find(({ tier }) => tier === suggested.plusTier) + ?.users.find((u) => u.info.id === suggested.id) ); } function targetPlusTierIsSmallerOrEqual({ user, - targetPlusTier, -}: Pick) { - return user?.plusTier && user.plusTier <= targetPlusTier; + suggested, +}: Pick) { + return user?.plusTier && user.plusTier <= suggested.plusTier; } diff --git a/app/routes/plus/suggestions.tsx b/app/routes/plus/suggestions.tsx index 30b39c0a7..a79ffe997 100644 --- a/app/routes/plus/suggestions.tsx +++ b/app/routes/plus/suggestions.tsx @@ -97,7 +97,7 @@ export default function PlusSuggestionsPage() { {visibleSuggestions.users.map((u) => ( ))} @@ -135,10 +135,10 @@ function SuggestedForInfo() { } function SuggestedUser({ - user: suggestedUser, + suggested, tier, }: { - user: Unpacked< + suggested: Unpacked< Unpacked>["users"] >; tier: number; @@ -147,23 +147,25 @@ function SuggestedUser({ const user = useUser(); const commentPageUrl = `comment?${new URLSearchParams({ - id: String(suggestedUser.info.id), + id: String(suggested.info.id), tier: String(tier), }).toString()}`; + invariant(data.suggestions); + return (
-

{suggestedUser.info.discordName}

+

{suggested.info.discordName}

{canAddCommentToSuggestionFE({ user, - allSuggestions: data.suggestions!, - target: { id: suggestedUser.info.id, plusTier: tier }, + suggestions: data.suggestions, + suggested: { id: suggested.info.id, plusTier: tier }, }) ? (
- Comments ({suggestedUser.suggestions.length}) + Comments ({suggested.suggestions.length})
- {suggestedUser.suggestions.map((s) => ( + {suggested.suggestions.map((s) => ( // xxx: white-space: pre-wrap?
{discordFullName(s.author)} diff --git a/app/routes/plus/suggestions/comment.tsx b/app/routes/plus/suggestions/comment.tsx index e733d4897..43a7f7420 100644 --- a/app/routes/plus/suggestions/comment.tsx +++ b/app/routes/plus/suggestions/comment.tsx @@ -14,12 +14,21 @@ import * as React from "react"; import { PlUS_SUGGESTION_COMMENT_MAX_LENGTH } from "~/constants"; import type { ActionFunction } from "@remix-run/node"; import { z } from "zod"; -import { parseRequestFormData, requireUser } from "~/utils/remix"; -import { canAddCommentToSuggestionFE } from "~/permissions"; +import { parseRequestFormData, requireUser, validate } from "~/utils/remix"; +import { + canAddCommentToSuggestionBE, + canAddCommentToSuggestionFE, +} from "~/permissions"; import { useUser } from "~/hooks/useUser"; +import { upcomingVoting } from "~/core/plus"; +import { db } from "~/db"; +import { actualNumber } from "~/utils/zod"; +import invariant from "tiny-invariant"; const commentActionSchema = z.object({ - comment: z.string().max(PlUS_SUGGESTION_COMMENT_MAX_LENGTH), + text: z.string().min(1).max(PlUS_SUGGESTION_COMMENT_MAX_LENGTH), + tier: z.preprocess(actualNumber, z.number().min(1).max(3)), + suggestedId: z.preprocess(actualNumber, z.number()), }); export const action: ActionFunction = async ({ request }) => { @@ -29,9 +38,31 @@ export const action: ActionFunction = async ({ request }) => { }); const user = await requireUser(request); + const suggestions = db.plusSuggestions.find({ + ...upcomingVoting(new Date()), + plusTier: user.plusTier, + }); + + validate(suggestions); + validate( + canAddCommentToSuggestionBE({ + suggestions, + user, + suggested: { id: data.suggestedId, plusTier: data.tier }, + }) + ); + + db.plusSuggestions.create({ + authorId: user.id, + ...data, + ...upcomingVoting(new Date()), + }); + return null; }; +// xxx: making unnecessary call to loader + when going back to modal and back keeps making http calls? +// xxx: modal closes when submitting without redirect? export default function PlusCommentModalPage() { const user = useUser(); const matches = useMatches(); @@ -39,19 +70,20 @@ export default function PlusCommentModalPage() { const [searchParams] = useSearchParams(); const data = matches.at(-2)!.data as PlusSuggestionsLoaderData; - const userBeingCommentedId = Number(searchParams.get("id")); + const targetUserId = Number(searchParams.get("id")); const tierSuggestedTo = Number(searchParams.get("tier")); const userBeingCommented = data.suggestions ?.find(({ tier }) => tier === tierSuggestedTo) - ?.users.find((u) => u.info.id === userBeingCommentedId); + ?.users.find((u) => u.info.id === targetUserId); + invariant(data.suggestions); if ( !userBeingCommented || !canAddCommentToSuggestionFE({ user, - allSuggestions: data.suggestions!, - target: { id: userBeingCommentedId, plusTier: tierSuggestedTo }, + suggestions: data.suggestions, + suggested: { id: targetUserId, plusTier: tierSuggestedTo }, }) ) { return ; @@ -60,6 +92,8 @@ export default function PlusCommentModalPage() { return (
+ +

{userBeingCommented.info.discordName}'s +{tierSuggestedTo}{" "} suggestion @@ -85,7 +119,7 @@ function CommentTextarea() { return (