Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple choice for flagging #1041

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 33 additions & 29 deletions src/app/harbor/battles/battles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Modal from '@/components/ui/modal'
import { sendFraudReport } from './fraud-utils'
import { Button } from '@/components/ui/button'
import { Howl } from 'howler'
import { MultiSelect } from '@/components/ui/multi-select'
interface Matchup {
project1: Ships
project2: Ships
Expand All @@ -47,7 +48,7 @@ export default function Matchups({ session }: { session: HsSession }) {
const [blessed, setBlessed] = useState(false)

const [fraudProject, setFraudProject] = useState<Ship>()
const [fraudType, setFraudType] = useState<string>()
const [fraudTypes, setFraudTypes] = useState<string[] | null>()
const [fraudReason, setFraudReason] = useState<string>()
const debounceTimeoutRef = useRef<number | null>(null)

Expand Down Expand Up @@ -390,11 +391,11 @@ export default function Matchups({ session }: { session: HsSession }) {
window.clearTimeout(debounceTimeoutRef.current)
}

if (!fraudProject || !fraudReason || !fraudType) return
if (!fraudProject || !fraudReason || !fraudTypes) return

debounceTimeoutRef.current = window.setTimeout(async () => {
try {
await sendFraudReport(fraudProject, fraudType, fraudReason)
await sendFraudReport(fraudProject, fraudTypes, fraudReason)
} catch (error) {
console.error('Failed to flag project:', error)
}
Expand All @@ -407,8 +408,8 @@ export default function Matchups({ session }: { session: HsSession }) {

setFraudProject(undefined)
setFraudReason('')
setFraudType('')
}, [fraudProject, fraudType, fraudReason])
setFraudTypes(null)
}, [fraudProject, fraudTypes, fraudReason])

if (isReadmeView) {
return (
Expand Down Expand Up @@ -508,47 +509,50 @@ export default function Matchups({ session }: { session: HsSession }) {
<h3 className="text-2xl font-bold">
Why are you flagging {fraudProject?.title}?
</h3>
<select
value={fraudType}
onChange={(e) => setFraudType(e.target.value)}
className="w-full my-4 p-1 text-black"
>
<option value="">Select the reason for flagging</option>
<option value="Incomplete README">Incomplete README</option>
<option value="No screenshot">No screenshot</option>
<option value="No demo link">No demo link</option>
<option value="Suspected fraud">Suspected fraud</option>
<option value="Wrong repo">
Repo not found / not open source
</option>
</select>

<MultiSelect
options={[
{ label: 'Incomplete README', value: 'Incomplete README' },
{ label: 'No screenshot', value: 'No screenshot' },
{ label: 'No demo link', value: 'No demo link' },
{ label: 'Suspected fraud', value: 'Suspected fraud' },
{
label: 'Repo not found / not open source',
value: 'Wrong repo',
},
]}
onValueChange={(val) => setFraudTypes(val)}
hideSelectAll={true}
className="my-4"
/>

<AnimatePresence>
{fraudType === 'Incomplete README' ||
fraudType === 'No demo link' ||
fraudType === 'No screenshot' ||
fraudType === 'Wrong repo' ? (
{fraudTypes?.includes('Suspected fraud') ? (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'fit-content', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
>
<p className="mb-3">
The creator of this project will be notified. Thanks for
making High Seas better! :)
The creator of this project will not know you reported
them for potential fraud.{' '}
<b>Only the High Seas team will see this.</b>
</p>
</motion.div>
) : null}

{fraudType === 'Suspected fraud' ? (
{fraudTypes?.includes('Incomplete README') ||
fraudTypes?.includes('No demo link') ||
fraudTypes?.includes('No screenshot') ||
fraudTypes?.includes('Wrong repo') ? (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'fit-content', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
>
<p className="mb-3">
The creator of this project will not know you reported
them. <b>Only the High Seas team will see this.</b>
The creator of this project will be notified about
incorrect links. Thanks for making High Seas better! :)
</p>
</motion.div>
) : null}
Expand All @@ -564,7 +568,7 @@ export default function Matchups({ session }: { session: HsSession }) {

<Button
variant={'destructive'}
disabled={!fraudType || !fraudReason}
disabled={!fraudTypes || !fraudReason}
onClick={handleFraudReport}
className="w-full bg-red-500 hover:bg-red-600 text-white font-semibold py-2 px-4 rounded"
>
Expand Down
6 changes: 3 additions & 3 deletions src/app/harbor/battles/fraud-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Ship } from '@/app/utils/data'

export async function sendFraudReport(
project: Ship,
type: string,
types: string[],
reason: string,
) {
const session = await getSession()
Expand All @@ -24,7 +24,7 @@ export async function sendFraudReport(
fields: {
project: [project.id],
reporter: [session?.personId],
reason: type,
reason: types,
details: reason,
},
},
Expand All @@ -35,5 +35,5 @@ export async function sendFraudReport(
.then((data) => data.json())
.then(console.log)

console.log(project, type, reason)
console.log(project, types, reason)
}
41 changes: 25 additions & 16 deletions src/components/ui/multi-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,12 @@ interface MultiSelectProps
*/
asChild?: boolean

/**
* Flag to exclude the "Selected All" option from the choice.
* Optional, defaults to false.
*/
hideSelectAll?: boolean

/**
* Additional class names to apply custom styles to the multi-select component.
* Optional, can be used to add custom styles.
Expand All @@ -123,6 +129,7 @@ export const MultiSelect = React.forwardRef<
maxCount = 3,
modalPopover = false,
asChild = false,
hideSelectAll = false,
className,
...props
},
Expand Down Expand Up @@ -275,23 +282,25 @@ export const MultiSelect = React.forwardRef<
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
<CommandItem
key="all"
onSelect={toggleAll}
className="cursor-pointer"
>
<div
className={cn(
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
selectedValues.length === options.length
? 'bg-primary text-primary-foreground'
: 'opacity-50 [&_svg]:invisible',
)}
<div hidden={hideSelectAll}>
<CommandItem
key="all"
onSelect={toggleAll}
className="cursor-pointer"
>
<CheckIcon className="h-4 w-4" />
</div>
<span>(Select All)</span>
</CommandItem>
<div
className={cn(
'mr-2 flex h-4 w-4 items-center justify-center rounded-sm border border-primary',
selectedValues.length === options.length
? 'bg-primary text-primary-foreground'
: 'opacity-50 [&_svg]:invisible',
)}
>
<CheckIcon className="h-4 w-4" />
</div>
<span>(Select All)</span>
</CommandItem>
</div>
{options.map((option) => {
const isSelected = selectedValues.includes(option.value)
return (
Expand Down
Loading