Fix typecheck

This commit is contained in:
MartinBraquet
2026-03-01 17:15:28 +01:00
parent 699890a0be
commit 0d8d81e09c
26 changed files with 64 additions and 72 deletions

View File

@@ -129,7 +129,7 @@ export function CreateEventModal(props: {
}
const handleChange = (
e: React.ChangeEvent<HTMLTextAreaElement | HTMLTextAreaElement | HTMLSelectElement>,
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>,
) => {
const {name, value} = e.target
setFormData((prev) => ({...prev, [name]: value}))

View File

@@ -24,7 +24,7 @@ export function MyMatchesToggle(props: {
type="checkbox"
className="border-ink-300 bg-canvas-0 dark:border-ink-500 text-primary-600 focus:ring-primary-500 h-4 w-4 rounded hover:bg-canvas-200"
checked={on}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setYourFilters(e.target.checked)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setYourFilters(e.target.checked)}
/>
<label htmlFor={label} className={clsx('text-ink-600 ml-2')}>
{label}

View File

@@ -226,7 +226,7 @@ export const Search = forwardRef<
<Row className="gap-2">
<Select
ref={sortSelectRef}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
if (isOrderBy(e.target.value)) {
updateFilter({
orderBy: e.target.value,

View File

@@ -25,7 +25,7 @@ export function ShortBioToggle(props: {
type="checkbox"
className="border-ink-300 bg-canvas-0 dark:border-ink-500 text-primary-600 focus:ring-primary-500 h-4 w-4 rounded hover:bg-canvas-200 cursor-pointer"
checked={on}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
updateFilter({shortBio: e.target.checked ? true : undefined})
}
/>

View File

@@ -21,9 +21,7 @@ export function FontPicker(props: {className?: string} = {}) {
<select
id="font-picker"
value={font}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
setFont(e.target.value as FontOption)
}
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => setFont(e.target.value as FontOption)}
className={clsx(
'rounded-md border border-gray-300 px-2 py-1 text-sm bg-canvas-50',
className,

View File

@@ -48,7 +48,7 @@ export function MinimalistTabs(props: TabProps & {activeIndex: number}) {
<a
href="#"
key={tab.queryString ?? tab.title}
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
onClick={(e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault()
onClick?.(tab.queryString?.toLowerCase() ?? tab.title.toLowerCase(), i)
if (trackingName) {
@@ -108,7 +108,7 @@ export function ControlledTabs(props: TabProps & {activeIndex: number}) {
<a
href="#"
key={tab.queryString ?? tab.title}
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
onClick={(e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault()
onClick?.(tab.queryString?.toLowerCase() ?? tab.title.toLowerCase(), i)

View File

@@ -118,7 +118,7 @@ export const MultiCheckbox = (props: {
<Input
value={newLabel}
placeholder={addPlaceholder ?? t('multi-checkbox.search_or_add', 'Search or add')}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setNewLabel(e.target.value)
setError(null)
}}

View File

@@ -1,5 +1,5 @@
import {Dialog, Transition} from '@headlessui/react'
import {MenuAlt3Icon} from '@heroicons/react/24/solid'
import {Bars3Icon} from '@heroicons/react/24/solid'
import clsx from 'clsx'
import {User} from 'common/user'
import Link from 'next/link'
@@ -57,7 +57,7 @@ export function BottomNavBar(props: {navigationOptions: Item[]; sidebarNavigatio
className={clsx(itemClass, 'relative', sidebarOpen ? selectedItemClass : '')}
onClick={() => setSidebarOpen(true)}
>
<MenuAlt3Icon className="mx-auto my-1 h-6 w-6" aria-hidden="true" />
<Bars3Icon className="mx-auto my-1 h-6 w-6" aria-hidden="true" />
{t('nav.more', 'More')}
</div>
<MobileSidebar
@@ -271,7 +271,7 @@ export function MobileSidebar(props: {
leaveTo="opacity-0"
>
{/* background cover */}
<Dialog.Overlay className="bg-canvas-100/75 fixed inset-0" />
<div className="bg-canvas-100/75 fixed inset-0" />
</Transition.Child>
<Transition.Child
as={Fragment}

View File

@@ -1,4 +1,4 @@
import {LoginIcon, LogoutIcon} from '@heroicons/react/24/outline'
import {ArrowLeftOnRectangleIcon, ArrowRightOnRectangleIcon} from '@heroicons/react/24/outline'
import clsx from 'clsx'
import {ANDROID_APP_URL} from 'common/constants'
import {buildArray} from 'common/util/array'
@@ -98,13 +98,13 @@ const bottomNav = (loggedIn: boolean) =>
!loggedIn && {
key: 'nav.sign_in',
name: 'Sign in',
icon: LoginIcon,
icon: ArrowRightOnRectangleIcon,
href: '/signin',
},
loggedIn && {
key: 'nav.sign_out',
name: 'Sign out',
icon: LogoutIcon,
icon: ArrowLeftOnRectangleIcon,
onClick: logout,
},
)

View File

@@ -297,7 +297,7 @@ export function AvatarNotificationIcon(props: {
<Link
href={href}
target={href.startsWith('http') ? '_blank' : undefined}
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.stopPropagation}
onClick={(e: React.MouseEvent<HTMLAnchorElement>) => e.stopPropagation}
>
<Avatar
username={sourceUserName}

View File

@@ -38,7 +38,7 @@ function replaceTw(element: ReactNode): ReactNode {
// pure element
// Replace `className` with `tw` for this element
const {props} = element
const props = element.props as {className?: string; children?: ReactNode; tw?: string}
const newProps = {...props}
if (props.className) {
newProps.tw = props.className

View File

@@ -353,7 +353,7 @@ export const OptionalProfileUserForm = (props: {
min={18}
max={100}
error={!!ageError}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value ? Number(e.target.value) : null
if (value !== null && value < 18) {
setAgeError(
@@ -378,7 +378,7 @@ export const OptionalProfileUserForm = (props: {
<Input
type="number"
data-testid="height-feet"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value === '') {
setHeightFeet(undefined)
} else {
@@ -397,7 +397,7 @@ export const OptionalProfileUserForm = (props: {
<Input
type="number"
data-testid="height-inches"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value === '') {
setHeightInches(undefined)
} else {
@@ -419,7 +419,7 @@ export const OptionalProfileUserForm = (props: {
<Input
type="number"
data-testid="height-centimeters"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value === '') {
setHeightFeet(undefined)
setHeightInches(undefined)
@@ -534,7 +534,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="keywords"
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setKeywordsString(e.target.value)
const keywords = e.target.value
.split(',')
@@ -579,7 +579,7 @@ export const OptionalProfileUserForm = (props: {
<Select
data-testid="pref-age-min"
value={profile['pref_age_min'] ?? ''}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
const newMin = e.target.value ? Number(e.target.value) : 18
const currentMax = profile['pref_age_max'] ?? 100
setProfile('pref_age_min', Math.min(newMin, currentMax))
@@ -599,7 +599,7 @@ export const OptionalProfileUserForm = (props: {
<Select
data-testid="pref-age-max"
value={profile['pref_age_max'] ?? ''}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
const newMax = e.target.value ? Number(e.target.value) : 100
const currentMin = profile['pref_age_min'] ?? 18
setProfile('pref_age_max', Math.max(newMax, currentMin))
@@ -671,7 +671,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="current-number-of-kids"
type="number"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value === '' ? null : Number(e.target.value)
setProfile('has_kids', value)
}}
@@ -749,7 +749,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="university"
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setProfile('university', e.target.value)
}
className={'w-52'}
@@ -770,7 +770,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="job-title"
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setProfile('occupation_title', e.target.value)
}
className={'w-52'}
@@ -783,7 +783,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="company"
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setProfile('company', e.target.value)
}
className={'w-52'}
@@ -816,7 +816,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="political-belief-details"
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setProfile('political_details', e.target.value)
}
className={'w-full sm:w-96'}
@@ -840,7 +840,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="religious-belief-details"
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setProfile('religious_beliefs', e.target.value)
}
className={'w-full sm:w-96'}
@@ -940,7 +940,7 @@ export const OptionalProfileUserForm = (props: {
<Input
data-testid="alcohol-consumed-per-month"
type="number"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value === '' ? null : Number(e.target.value)
setProfile('drinks_per_month', value)
}}
@@ -974,7 +974,7 @@ export const OptionalProfileUserForm = (props: {
<label className={clsx(labelClassName)}>Birthplace</label>
<Input
type="text"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setProfileState('born_in_location', e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setProfileState('born_in_location', e.target.value)}
className={'w-52'}
value={profile['born_in_location'] ?? undefined}
/>
@@ -1008,7 +1008,7 @@ export const OptionalProfileUserForm = (props: {
<Input
type="text"
value={value!}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
updateUserLink(platform, e.target.value)
}
className="col-span-2 sm:col-span-1"
@@ -1036,9 +1036,7 @@ export const OptionalProfileUserForm = (props: {
: t('profile.optional.site_url', 'Site URL')
}
value={newLinkValue}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
setNewLinkValue(e.target.value)
}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setNewLinkValue(e.target.value)}
// disable password managers
autoComplete="off"
data-1p-ignore
@@ -1134,7 +1132,7 @@ const CitySearchBox = (props: {onCitySelected: (city: City | undefined) => void}
<>
<Input
value={query}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setQuery(e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setQuery(e.target.value)}
placeholder={t('profile.optional.search_city', 'Search city...')}
onFocus={() => setFocused(true)}
onBlur={(e) => {

View File

@@ -1,5 +1,5 @@
import {EyeSlashIcon, FlagIcon} from '@heroicons/react/24/outline'
import {EllipsisHorizontalIcon, ReplyIcon} from '@heroicons/react/24/solid'
import {ArrowUturnLeftIcon, EllipsisHorizontalIcon} from '@heroicons/react/24/solid'
import {Editor} from '@tiptap/react'
import clsx from 'clsx'
import {type Comment, MAX_COMMENT_LENGTH, ReplyToUserInfo} from 'common/comment'
@@ -333,7 +333,7 @@ function CommentActions(props: {
}}
className={'text-ink-500'}
>
<ReplyIcon className="h-5 w-5 " />
<ArrowUturnLeftIcon className="h-5 w-5 " />
</IconButton>
</Tooltip>
)}

View File

@@ -150,7 +150,7 @@ const QuestionRow = (props: {row: rowFor<'compatibility_prompts'>; user: User})
className={'w-20'}
max={1000}
min={0}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setForm({...form, integer: Number(e.target.value)})
}
value={form.integer ?? undefined}
@@ -211,7 +211,7 @@ export const IndividualQuestionRow = (props: {
className={'w-20'}
max={1000}
min={0}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setForm({...form, integer: Number(e.target.value)})
}
value={form.integer ?? undefined}

View File

@@ -108,7 +108,7 @@ export const RequiredProfileUserForm = (props: {
type="text"
placeholder="Display name"
value={name}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateUserState({name: e.target.value || ''})
}}
onBlur={updateDisplayName}
@@ -132,7 +132,7 @@ export const RequiredProfileUserForm = (props: {
type="text"
placeholder="Username"
value={username}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateUserState({
username: e.target.value || '',
errorUsername: '',

View File

@@ -82,7 +82,7 @@ export function SelectUsers(props: {
name="user name"
id="user name"
value={query}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => setQuery(e.target.value)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => setQuery(e.target.value)}
placeholder="Search users..."
/>
</Col>

View File

@@ -1,4 +1,4 @@
import {DocumentReportIcon, LinkIcon} from '@heroicons/react/24/solid'
import {DocumentTextIcon, LinkIcon} from '@heroicons/react/24/solid'
import {Site} from 'common/socials'
import {ReactNode} from 'react'
import {LuBookmark, LuHandshake, LuHeart, LuUsers} from 'react-icons/lu'
@@ -36,7 +36,7 @@ export const PLATFORM_ICONS: {
okcupid: LuHeart,
datingdoc: LuHeart,
friendshipdoc: LuUsers,
workdoc: DocumentReportIcon,
workdoc: DocumentTextIcon,
connectiondoc: LuHandshake,
calendly: TbCalendar,
}

View File

@@ -46,7 +46,7 @@ export function VoteComponent() {
<select
id="orderBy"
value={orderBy}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLSelectElement>) =>
setOrderBy(e.target.value as OrderBy)
}
className="rounded-md border border-gray-300 px-2 py-1 text-sm bg-canvas-50"
@@ -79,7 +79,7 @@ export function VoteComponent() {
value={title}
placeholder={t('vote.form.title_placeholder', 'Title')}
className={'w-full mb-2'}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setTitle(e.target.value)
}}
/>
@@ -89,7 +89,7 @@ export function VoteComponent() {
type="checkbox"
id="anonymous"
checked={isAnonymous}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setIsAnonymous(e.target.checked)
}
className="h-4 w-4 rounded-md border-gray-300 text-blue-600 focus:ring-blue-500"

View File

@@ -22,7 +22,7 @@ export function Checkbox(props: {
type="checkbox"
className="border-ink-300 bg-canvas-0 dark:border-ink-500 text-primary-600 focus:ring-primary-500 h-5 w-5 rounded hover:bg-canvas-300"
checked={checked}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => toggle(e.target.checked)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => toggle(e.target.checked)}
disabled={disabled}
/>
<span

View File

@@ -48,7 +48,7 @@ export function ChoicesToggleGroup<T extends Record<string, string | number | bo
'border-ink-300 text-ink-400 bg-canvas-0 inline-flex flex-row gap-2 rounded-md border p-1 text-sm shadow-sm',
disabled && 'bg-canvas-50 !cursor-not-allowed',
)}
value={currentChoice}
value={currentChoice ?? undefined}
onChange={setChoice}
disabled={disabled}
>

View File

@@ -92,7 +92,7 @@ export function Tooltip(props: {
}
}, [])
const {x, y, reference, floating, strategy, middlewareData, context, placement} = useFloating({
const {x, y, refs, strategy, middlewareData, context, placement} = useFloating({
open: open,
onOpenChange: (next) => {
if (next) {
@@ -131,7 +131,7 @@ export function Tooltip(props: {
data-testid={testId}
suppressHydrationWarning={suppressHydrationWarning}
className={className}
ref={reference}
ref={refs.reference as any}
{...getReferenceProps()}
>
{children}
@@ -146,14 +146,14 @@ export function Tooltip(props: {
leaveFrom="opacity-100"
leaveTo="opacity-0"
// div attributes
role="tooltip"
ref={floating}
as="div"
ref={refs.floating as any}
style={{position: strategy, top: y ?? 0, left: x ?? 0}}
className="text-ink-1000 bg-canvas-50 z-20 w-max max-w-xs whitespace-normal rounded px-2 py-1 text-center text-sm font-medium"
suppressHydrationWarning={suppressHydrationWarning}
{...getFloatingProps()}
>
{text}
<div role="tooltip">{text}</div>
<div
ref={arrowRef}
className="bg-canvas-50 absolute h-2 w-2 rotate-45"

View File

@@ -73,7 +73,7 @@ export function UserLink(props: {
<Link
href={`/${username}`}
className={clsx(linkClass, 'inline-flex flex-row items-center gap-1', className)}
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.stopPropagation()}
onClick={(e: React.MouseEvent<HTMLAnchorElement>) => e.stopPropagation()}
>
{children}
</Link>

View File

@@ -1,7 +1,7 @@
import {RefObject, useEffect} from 'react'
export function useClickOutside<T extends HTMLElement = HTMLElement>(
ref: RefObject<T>,
ref: RefObject<T | null>,
callback: (event: MouseEvent | TouchEvent) => void,
) {
useEffect(() => {

View File

@@ -39,7 +39,7 @@ export function updateSupabaseAuth(token?: string) {
// db['rest'].headers['Authorization']
db['realtime'].setAuth(null)
} else {
db['rest'].headers['Authorization'] = `Bearer ${token}`
db['rest'].headers.set('Authorization', `Bearer ${token}`)
db['realtime'].setAuth(token)
}
}

View File

@@ -1,6 +1,6 @@
import type {DisplayUser} from 'common/api/user-types'
import {APIError} from 'common/api/utils'
import {run} from 'common/supabase/utils'
import {run, TableName} from 'common/supabase/utils'
import {MONTH_MS} from 'common/util/time'
import {api} from 'web/lib/api'
@@ -52,16 +52,14 @@ export async function getDisplayUsers(userIds: string[]) {
db
.from('users')
.select(`id, name, username, data->avatarUrl, data->isBannedFromPosting`)
.in('id', userIds)
.in('id', userIds),
)
return data as unknown as DisplayUser[]
}
export async function getProfilesCreations() {
const {data} = await run(
db.from('profiles').select(`id, created_time`).order('created_time')
)
const {data} = await run(db.from('profiles').select(`id, created_time`).order('created_time'))
return data
}
@@ -71,12 +69,12 @@ export async function getCompletedProfilesCreations() {
.from('profiles')
.select(`id, created_time`)
.or(`bio_length.gte.100,occupation_title.not.is.null`)
.order('created_time')
.order('created_time'),
)
return data
}
export async function getCount(table: string) {
export async function getCount(table: TableName | 'active_members') {
if (table == 'private_user_messages') {
const result = await api('get-messages-count')
return result.count
@@ -86,13 +84,11 @@ export async function getCount(table: string) {
db
.from('user_activity')
.select('*', {count: 'exact', head: true})
.gt('last_online_time', new Date(Date.now() - MONTH_MS).toISOString()) // last month
.gt('last_online_time', new Date(Date.now() - MONTH_MS).toISOString()), // last month
)
return count
}
const {count} = await run(
db.from(table).select('*', {count: 'exact', head: true})
)
const {count} = await run(db.from(table as any).select('*', {count: 'exact', head: true}))
return count
}

View File

@@ -116,7 +116,7 @@ export default function CompatibilityPage() {
value={keyword}
placeholder={t('compatibility.search_placeholder', 'Search questions and answers...')}
className={'w-full max-w-xs mb-4'}
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
setKeyword(e.target.value)
}}
/>