diff --git a/biome.jsonc b/biome.jsonc index 159ed8cf95..f7440af474 100644 --- a/biome.jsonc +++ b/biome.jsonc @@ -25,6 +25,12 @@ "!.vscode" ] }, + "css": { + "formatter": { + "enabled": true, + "indentStyle": "tab" + } + }, "linter": { "rules": { "recommended": false, diff --git a/client/components/FlagUserDialog/FlagUserDialog.tsx b/client/components/FlagUserDialog/FlagUserDialog.tsx new file mode 100644 index 0000000000..86a6d4ebdc --- /dev/null +++ b/client/components/FlagUserDialog/FlagUserDialog.tsx @@ -0,0 +1,133 @@ +import type { ModerationReportReason } from 'types'; + +import React, { useCallback, useState } from 'react'; + +import { Button, Callout, Classes, Dialog, HTMLSelect, Intent, TextArea } from '@blueprintjs/core'; + +import { apiFetch } from 'client/utils/apiFetch'; +import { moderationReasonLabels } from 'utils/moderationReasons'; + +const reasons = (Object.entries(moderationReasonLabels) as [ModerationReportReason, string][]).map( + ([value, label]) => ({ value, label }), +); + +type Props = { + isOpen: boolean; + onClose: () => void; + userId: string; + communityId: string; + threadCommentId?: string | null; + userName?: string; + onFlagged?: () => void; +}; + +const FlagUserDialog = (props: Props) => { + const { isOpen, onClose, userId, communityId, threadCommentId, userName, onFlagged } = props; + const [reason, setReason] = useState('spam-content'); + const [reasonText, setReasonText] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + const handleSubmit = useCallback(async () => { + setIsLoading(true); + setError(null); + try { + await apiFetch.post('/api/communityModerationReports', { + userId, + communityId, + reason, + reasonText: reasonText.trim() || null, + sourceThreadCommentId: threadCommentId ?? null, + }); + onFlagged?.(); + onClose(); + } catch (err: any) { + setError(err?.message ?? 'Failed to ban user'); + } finally { + setIsLoading(false); + } + }, [userId, communityId, reason, reasonText, threadCommentId, onFlagged, onClose]); + + return ( + +
+ +

+ This will ban the user from your community. They will not + be able to perform any actions, including creating Pubs, posting + discussions, or editing content. +

+

+ All of their existing discussions and comments will be hidden from other + users. You can reverse this action at any time from the Members settings. +

+

+ The user will not be notified of this action. +

+
+ +
+ + setReason(e.target.value as ModerationReportReason)} + fill + style={{ marginTop: 4 }} + > + {reasons.map((r) => ( + + ))} + +
+ +
+ +

+ This message will be sent to the PubPub team and helps us identify patterns + of abuse across the platform. +

+