Migrate game modes.
parent
2660cac8a8
commit
283bf59546
|
@ -0,0 +1,48 @@
|
||||||
|
import * as React from "react"
|
||||||
|
import clsx from "clsx"
|
||||||
|
import {
|
||||||
|
Input as BaseInput,
|
||||||
|
InputOwnerState,
|
||||||
|
InputProps,
|
||||||
|
MultiLineInputProps,
|
||||||
|
} from "@mui/base/Input"
|
||||||
|
|
||||||
|
import { FieldContext } from "./FieldSet"
|
||||||
|
import { resolveSlotProps } from "../utils/props"
|
||||||
|
|
||||||
|
export type CheckBoxProps = Omit<InputProps, keyof MultiLineInputProps>
|
||||||
|
|
||||||
|
export const CheckBox = React.forwardRef<HTMLInputElement, CheckBoxProps>(
|
||||||
|
function CheckBox(
|
||||||
|
props: CheckBoxProps,
|
||||||
|
ref: React.ForwardedRef<HTMLInputElement>
|
||||||
|
) {
|
||||||
|
const fieldContext = React.useContext(FieldContext)
|
||||||
|
const { disabled = fieldContext?.disabled, className, ...other } = props
|
||||||
|
|
||||||
|
const inputSlotProps = (ownerState: InputOwnerState) => {
|
||||||
|
const resolved = resolveSlotProps(props.slotProps?.input, ownerState)
|
||||||
|
return {
|
||||||
|
...resolved,
|
||||||
|
className: clsx(
|
||||||
|
"w-5 h-5 accent-black cursor-pointer -translate-y-[3px]",
|
||||||
|
resolved?.className
|
||||||
|
),
|
||||||
|
style: {
|
||||||
|
color: "black",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BaseInput
|
||||||
|
ref={ref}
|
||||||
|
{...other}
|
||||||
|
type="checkbox"
|
||||||
|
className={clsx("h-5 w-5", { "opacity-60": disabled }, className)}
|
||||||
|
slotProps={{ input: inputSlotProps }}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
|
@ -2,10 +2,12 @@ import * as React from "react"
|
||||||
import { Controller, useForm } from "react-hook-form"
|
import { Controller, useForm } from "react-hook-form"
|
||||||
|
|
||||||
import { Button } from "./Button"
|
import { Button } from "./Button"
|
||||||
import { Field } from "./FieldSet"
|
import { CheckBox } from "./CheckBox"
|
||||||
|
import { Field, FieldSet } from "./FieldSet"
|
||||||
import { Input } from "./Input"
|
import { Input } from "./Input"
|
||||||
import { Label } from "./Label"
|
import { Label } from "./Label"
|
||||||
import { Modal } from "./Modal"
|
import { Modal } from "./Modal"
|
||||||
|
import { Mode, getModeName } from "../types/Mode"
|
||||||
import { SelectLanguage, SelectLanguageProps } from "./SelectLanguage"
|
import { SelectLanguage, SelectLanguageProps } from "./SelectLanguage"
|
||||||
import { Slider } from "./Slider"
|
import { Slider } from "./Slider"
|
||||||
|
|
||||||
|
@ -77,7 +79,8 @@ export function FilterModal({
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const controlFIDERating = register("fideRating")
|
const registerRating = register("rating")
|
||||||
|
const registerModes = register("modes")
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
|
@ -116,17 +119,17 @@ export function FilterModal({
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
<Field>
|
<Field>
|
||||||
<Label htmlFor={`${idPrefix}-fideRating`}>FIDE Rating:</Label>
|
<Label htmlFor={`${idPrefix}-rating`}>FIDE Rating:</Label>
|
||||||
<p className="py-2 text-sm">
|
<p className="py-2 text-sm">
|
||||||
Find coaches that have a rating within the specified range. Keep in
|
Find coaches that have a rating within the specified range. Keep in
|
||||||
mind, a higher rating does not necessarily mean a better coach{" "}
|
mind, a higher rating does not necessarily mean a better coach{" "}
|
||||||
<i>for you</i>. If you are unsure of this or do not have any
|
<i>for you</i>. If you are unsure of this or do not have any
|
||||||
preference, leave as is.
|
preference, leave as is.
|
||||||
</p>
|
</p>
|
||||||
<div id={`${idPrefix}-fideRating`} className="mt-2 w-full px-4">
|
<div id={`${idPrefix}-rating`} className="mt-2 w-full px-4">
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name={controlFIDERating.name}
|
name={registerRating.name}
|
||||||
render={({ field: { onChange, onBlur, value, ref } }) => (
|
render={({ field: { onChange, onBlur, value, ref } }) => (
|
||||||
<Slider
|
<Slider
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
@ -134,8 +137,8 @@ export function FilterModal({
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
onChange={(event, newValue: any) => {
|
onChange={(event, newValue: any) => {
|
||||||
event && onChange(event)
|
event && onChange(event)
|
||||||
setValue("fideRating.0", newValue[0])
|
setValue("rating.0", newValue[0])
|
||||||
setValue("fideRating.1", newValue[1])
|
setValue("rating.1", newValue[1])
|
||||||
}}
|
}}
|
||||||
step={10}
|
step={10}
|
||||||
min={FIDE_RATING_MIN}
|
min={FIDE_RATING_MIN}
|
||||||
|
@ -154,17 +157,32 @@ export function FilterModal({
|
||||||
<label className="text-neutral-850 text-sm font-medium">
|
<label className="text-neutral-850 text-sm font-medium">
|
||||||
Min:
|
Min:
|
||||||
</label>
|
</label>
|
||||||
<Input value={watch("fideRating.0")} disabled />
|
<Input value={watch("rating.0")} disabled />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label className="text-neutral-850 text-sm font-medium">
|
<label className="text-neutral-850 text-sm font-medium">
|
||||||
Max:
|
Max:
|
||||||
</label>
|
</label>
|
||||||
<Input value={watch("fideRating.1")} disabled />
|
<Input value={watch("rating.1")} disabled />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Field>
|
</Field>
|
||||||
|
|
||||||
|
<FieldSet className="text-sm text-neutral-600">
|
||||||
|
<p className="py-2">
|
||||||
|
Prefer a specific game mode? We{"'"}ll prioritize coaches that
|
||||||
|
specialize in the modes selected.
|
||||||
|
</p>
|
||||||
|
<div className="grid grid-cols-3 pt-3">
|
||||||
|
{(Object.keys(Mode) as Mode[]).map((m) => (
|
||||||
|
<div key={m} className="col-span-1 flex items-center gap-x-2">
|
||||||
|
<CheckBox value={m} {...registerModes} />
|
||||||
|
<div>{getModeName(m)}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FieldSet>
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,10 +21,10 @@ const filters: FilterOption[] = [
|
||||||
title: "FIDE 2000+",
|
title: "FIDE 2000+",
|
||||||
Icon: RisingGraphIcon,
|
Icon: RisingGraphIcon,
|
||||||
enable: (p) => {
|
enable: (p) => {
|
||||||
p.fideRating[0] = Math.max(2000, p.fideRating[0])
|
p.rating[0] = Math.max(2000, p.rating[0])
|
||||||
return p
|
return p
|
||||||
},
|
},
|
||||||
isEnabled: (p) => p.fideRating[0] >= 2000,
|
isEnabled: (p) => p.rating[0] >= 2000,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "English Speaking",
|
title: "English Speaking",
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
export enum Mode {
|
||||||
|
RAPID = "RAPID",
|
||||||
|
BLITZ = "BLITZ",
|
||||||
|
BULLET = "BULLET",
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getModeName = (m: Mode) => {
|
||||||
|
return m.charAt(0) + m.toLowerCase().slice(1)
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
|
import { Mode } from "./Mode"
|
||||||
|
|
||||||
export type SearchParams = {
|
export type SearchParams = {
|
||||||
fideRating: [number, number]
|
rating: [number, number]
|
||||||
|
modes: Mode[]
|
||||||
languages: string[]
|
languages: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +10,7 @@ export const FIDE_RATING_MIN = 1500
|
||||||
export const FIDE_RATING_MAX = 3200
|
export const FIDE_RATING_MAX = 3200
|
||||||
|
|
||||||
export const defaultSearchParams: SearchParams = {
|
export const defaultSearchParams: SearchParams = {
|
||||||
fideRating: [FIDE_RATING_MIN, FIDE_RATING_MAX],
|
rating: [FIDE_RATING_MIN, FIDE_RATING_MAX],
|
||||||
|
modes: [Mode.RAPID, Mode.BLITZ, Mode.BULLET],
|
||||||
languages: [],
|
languages: [],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue