overleaf/services/web/frontend/js/features/group-management/components/user-row.tsx
Antoine Clausse 2f99e3ccf1 Add autoComplete="off" to React-controlled checkboxes (#18212)
Fixes https://github.com/overleaf/internal/issues/18144

Browsers use a [bfcache](https://web.dev/articles/bfcache) (Back/forward cache) which restores form data on navigation. Unfortunately, it causes checkbox appearances not to respect our React states.

Setting `autoComplete="off"` on checkboxes mitigates this problem. (From https://stackoverflow.com/questions/299811/why-does-the-checkbox-stay-checked-when-reloading-the-page)

Another solution could be to set a `Cache-Control: no-store` header, but this might additionnal undesired consequences.

GitOrigin-RevId: 7d3cceb1c818ad70de7e806ea6d714ffc8bffb4a
2024-05-06 08:04:39 +00:00

82 lines
2.1 KiB
TypeScript

import moment from 'moment'
import { useCallback } from 'react'
import { Col, Row } from 'react-bootstrap'
import { useTranslation } from 'react-i18next'
import { User } from '../../../../../types/group-management/user'
type GroupMemberRowProps = {
user: User
selectUser: (user: User) => void
unselectUser: (user: User) => void
selected: boolean
}
export default function UserRow({
user,
selectUser,
unselectUser,
selected,
}: GroupMemberRowProps) {
const { t } = useTranslation()
const handleSelectUser = useCallback(
(event, user) => {
if (event.target.checked) {
selectUser(user)
} else {
unselectUser(user)
}
},
[selectUser, unselectUser]
)
return (
<li key={`user-${user.email}`}>
<Row>
<Col xs={4}>
<label htmlFor={`select-user-${user.email}`} className="sr-only">
{t('select_user')}
</label>
<input
className="select-item"
id={`select-user-${user.email}`}
type="checkbox"
autoComplete="off"
checked={selected}
onChange={e => handleSelectUser(e, user)}
/>
<span>{user.email}</span>
</Col>
<Col xs={4}>
{user.first_name} {user.last_name}
</Col>
<Col xs={2}>
{user.last_active_at
? moment(user.last_active_at).format('Do MMM YYYY')
: 'N/A'}
</Col>
<Col xs={2}>
{user.invite ? (
<>
<i
className="fa fa-times"
aria-hidden="true"
aria-label={t('invite_not_accepted')}
/>
<span className="sr-only">{t('invite_not_accepted')}</span>
</>
) : (
<>
<i
className="fa fa-check text-success"
aria-hidden="true"
aria-label={t('accepted_invite')}
/>
<span className="sr-only">{t('accepted_invite')}</span>
</>
)}
</Col>
</Row>
</li>
)
}