Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | 9x 9x 9x 9x 8x 8x 8x 8x 8x 8x 8x 8x 8x 3x 3x 1x 5x 9x | import { MouseEvent, useState } from "react";
import NiceModal from "@ebay/nice-modal-react";
import {
DotsThreeVerticalIcon,
EnvelopeOpenIcon,
PlusIcon,
} from "@phosphor-icons/react";
import { ACTION_DENY_MESSAGE } from "@constants/permissions";
import ContextualMenu from "@shared/ContextualMenu/ContextualMenu";
import { ContextualMenuOptionProps } from "@shared/ContextualMenu/ContextualMenu.types";
import GiveButton from "@shared/Button/GiveButton";
import GiveIconButton from "@shared/IconButton/GiveIconButton";
import GiveTooltip from "@shared/Tooltip/GiveTooltip";
import { useTeamPermissions } from "@features/Permissions/AccessControl/hooks";
import { useCustomThemeV2 } from "@theme/hooks/useCustomThemeV2";
import {
EVENT_ASSIGN_HOST_MODAL,
EVENT_INVITE_HOST_MODAL,
} from "modals/modal_names";
export const ASSIGN_HOST_ACTION = "Assign Host";
export const INVITE_HOST_ACTION = "Invite Host";
const ACTIONS_ARIA_LABEL = "Host actions";
type Props = {
eventId?: string;
};
/**
* The Host tab's toolbar actions (frames 8119-109601 / 8124-60014).
*
* Two actions now, because an event's door staff can come from two places: a
* host the merchant already has (Assign, the primary — it needs no email and no
* waiting) or a new one (Invite). The pair is what drives the icon change on
* this row: Assign takes the plus, Invite takes the envelope it used to share.
*
* A 390px row fits the search field and one 32px control, so the pair collapses
* into an overflow sheet there.
*
* Both are member writes: inviting creates an account member, and assigning
* writes an existing member's assignment set — so each carries the gate its own
* call is subject to, and reports a denial the way Settings → Team does.
*/
const HostToolbarActions = ({ eventId }: Props) => {
const { isMobileView } = useCustomThemeV2();
const { isAddAllowed, isUpdateAccessPolicyAllowed } = useTeamPermissions();
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const closeMenu = () => setAnchorEl(null);
const openAssignModal = () =>
NiceModal.show(EVENT_ASSIGN_HOST_MODAL, { eventId });
const openInviteModal = () =>
NiceModal.show(EVENT_INVITE_HOST_MODAL, { eventId });
const canAssign = Boolean(eventId) && isUpdateAccessPolicyAllowed;
const canInvite = Boolean(eventId) && isAddAllowed;
if (isMobileView) {
// Frame 8124-60544 — the sheet leads with the label and trails the glyph,
// the same arrangement the event's own (…) menu uses.
const options: ContextualMenuOptionProps[] = [
{
text: ASSIGN_HOST_ACTION,
IconRight: PlusIcon,
disabled: !canAssign,
tooltipTitle: ACTION_DENY_MESSAGE,
disableTooltip: canAssign,
onClick: () => {
closeMenu();
openAssignModal();
},
},
{
text: INVITE_HOST_ACTION,
IconRight: EnvelopeOpenIcon,
disabled: !canInvite,
tooltipTitle: ACTION_DENY_MESSAGE,
disableTooltip: canInvite,
onClick: () => {
closeMenu();
openInviteModal();
},
},
];
return (
<>
<GiveIconButton
Icon={DotsThreeVerticalIcon}
variant="ghost"
size="large"
aria-label={ACTIONS_ARIA_LABEL}
data-testid="event-hosts-mobile-actions"
onClick={(event: MouseEvent<HTMLElement>) =>
setAnchorEl(event.currentTarget)
}
/>
<ContextualMenu
anchorEl={anchorEl}
handleClose={closeMenu}
// Below v2_sm this is a bottom sheet, where the blurred tertiary
// surface reads as a grey wash — the mockups' sheet is plain white.
color="primary"
texture="solid"
options={options}
/>
</>
);
}
return (
<>
<GiveTooltip
disableHoverListener={canAssign}
title={ACTION_DENY_MESSAGE}
fluidWidth
>
<GiveButton
variant="filled"
size="large"
startIcon={<PlusIcon size={18} />}
label={ASSIGN_HOST_ACTION}
disabled={!canAssign}
onClick={openAssignModal}
sx={BUTTON_SX}
/>
</GiveTooltip>
<GiveTooltip
disableHoverListener={canInvite}
title={ACTION_DENY_MESSAGE}
fluidWidth
>
<GiveButton
variant="outline"
size="large"
startIcon={<EnvelopeOpenIcon size={18} />}
label={INVITE_HOST_ACTION}
disabled={!canInvite}
onClick={openInviteModal}
sx={BUTTON_SX}
/>
</GiveTooltip>
</>
);
};
export default HostToolbarActions;
// The toolbar row is a flex container that would otherwise stretch both
// buttons; `nowrap` keeps each label on one line as the row narrows.
const BUTTON_SX = {
width: "fit-content !important",
whiteSpace: "nowrap",
};
|