import { useState } from 'react' import { useTranslation } from 'react-i18next' import { OLModal, OLModalBody, OLModalFooter, OLModalHeader, OLModalTitle, } from '@/shared/components/ol/ol-modal' import OLButton from '@/shared/components/ol/ol-button' import OLSpinner from '@/shared/components/ol/ol-spinner' import OLFormGroup from '@/shared/components/ol/ol-form-group' import OLFormLabel from '@/shared/components/ol/ol-form-label' import Notification from '@/shared/components/notification' import MaterialIcon from '@/shared/components/material-icon' import DropdownMenuItem from '@/shared/components/dropdown/dropdown-menu-item' import { OLDropdown, OLDropdownMenu, OLDropdownToggle, } from '@/shared/components/ol/ol-dropdown-menu' import { requestAccess } from '@/features/share-project-modal/utils/api' import { useProjectContext } from '@/shared/context/project-context' import { useUserContext } from '@/shared/context/user-context' import { useIdeReactContext } from '@/features/ide-react/context/ide-react-context' import useAsync from '@/shared/hooks/use-async' import { RequestedPrivilegeLevel } from '@/shared/context/types/project-metadata' // `as const` keeps the icon names as literals so they satisfy // MaterialIcon's `type` prop when combined with `unfilled` (a widened // `string` would resolve to the filled-icon overload and fail type-check). const LEVEL_OPTIONS = [ { key: 'readAndWrite', icon: 'edit' }, { key: 'review', icon: 'mode_comment' }, ] as const satisfies ReadonlyArray<{ key: RequestedPrivilegeLevel icon: string }> export default function RequestAccessModal({ show, onSuccess, onCancel, }: { show: boolean onSuccess: () => void onCancel: () => void }) { const { t } = useTranslation() const { projectId } = useProjectContext() const { email } = useUserContext() const { permissionsLevel } = useIdeReactContext() const { isLoading, isError, runAsync } = useAsync() // Reviewers can only step up to editor; viewers can choose editor or // reviewer. The requestable set always excludes the level the user // already holds. const options = permissionsLevel === 'review' ? LEVEL_OPTIONS.filter(o => o.key === 'readAndWrite') : LEVEL_OPTIONS const [privilegeLevel, setPrivilegeLevel] = useState('readAndWrite') // Built with static t() calls (not t(dynamicKey)) so the keys are picked up // by the translation extractor and never render as raw key strings. const levelLabels: Record = { readAndWrite: t('editor'), review: t('reviewer'), } function submit() { runAsync(requestAccess(projectId, privilegeLevel)) .then(() => onSuccess()) .catch(() => {}) } return ( {t('request_edit_access')}

{t('signed_in_as_email', { email })}

{t('what_access_do_you_want')}
eventKey && setPrivilegeLevel(eventKey) } > {levelLabels[privilegeLevel]} {options.map(option => ( } active={privilegeLevel === option.key} trailingIcon={ privilegeLevel === option.key ? 'check' : undefined } > {levelLabels[option.key]} ))}

{t( 'your_name_and_email_address_will_be_visible_to_the_project_owner_and_other_editors' )}

{isError && ( )}
{isLoading && }
{t('cancel')} {t('send_request')}
) }