Skip to content

Commit

Permalink
fix: activity library settings mobile (#9275)
Browse files Browse the repository at this point in the history
* add minimize animation

* fix cta on desktop and mobile

* ensure cta buttons have a higher z index that the minimized content

* add useMenu comment
  • Loading branch information
nickoferrall committed Dec 7, 2023
1 parent 8520063 commit f3ab591
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@ const ActivityDetails = (props: Props) => {
}`

const isOwner = viewerLowestScope === 'TEAM'
const MOBILE_SETTINGS_HEIGHT = 208

return (
<div className='flex h-full flex-col bg-white'>
<div className='flex grow'>
<div className={clsx(`flex grow pb-[${MOBILE_SETTINGS_HEIGHT}px]`)}>
<div className='mt-4 grow'>
<div className='mb-14 ml-4 flex h-min w-max items-center'>
<div className='mr-4'>
Expand Down Expand Up @@ -140,6 +141,18 @@ const ActivityDetails = (props: Props) => {
</div>
</div>
</div>
<div className='hidden lg:block'>
<ActivityDetailsSidebar
selectedTemplateRef={activity}
teamsRef={teams}
isOpen={!isEditing}
type={activity.type}
preferredTeamId={preferredTeamId}
viewerRef={viewer}
/>
</div>
</div>
<div className={`fixed min-h-[${MOBILE_SETTINGS_HEIGHT}px] bottom-0 w-full lg:hidden`}>
<ActivityDetailsSidebar
selectedTemplateRef={activity}
teamsRef={teams}
Expand Down
250 changes: 140 additions & 110 deletions packages/client/components/ActivityLibrary/ActivityDetailsSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {LockOpen} from '@mui/icons-material'
import graphql from 'babel-plugin-relay/macro'
import clsx from 'clsx'
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
import React, {useState, useEffect, useRef} from 'react'
import {useFragment} from 'react-relay'
import StartSprintPokerMutation from '~/mutations/StartSprintPokerMutation'
Expand Down Expand Up @@ -40,6 +42,8 @@ import {SelectGroup} from '../../ui/Select/SelectGroup'
import {SelectItem} from '../../ui/Select/SelectItem'
import OneOnOneTeamStatus from './OneOnOneTeamStatus'
import ScheduleMeetingButton from './ScheduleMeetingButton'
import useBreakpoint from '../../hooks/useBreakpoint'
import {Breakpoint} from '../../types/constEnums'

interface Props {
selectedTemplateRef: ActivityDetailsSidebar_template$key
Expand All @@ -52,6 +56,8 @@ interface Props {

const ActivityDetailsSidebar = (props: Props) => {
const {selectedTemplateRef, teamsRef, type, isOpen, preferredTeamId, viewerRef} = props
const [isMinimized, setIsMinimized] = useState(false)
const isMobile = !useBreakpoint(Breakpoint.INVOICE)
const selectedTemplate = useFragment(
graphql`
fragment ActivityDetailsSidebar_template on MeetingTemplate {
Expand Down Expand Up @@ -288,129 +294,153 @@ const ActivityDetailsSidebar = (props: Props) => {
{isOpen && <div className='w-96' />}
<div
className={clsx(
'fixed right-0 flex h-screen translate-x-0 flex-col border-l border-solid border-slate-300 px-4 pb-9 pt-14 transition-all',
isOpen ? ' w-96' : 'w-0 overflow-hidden opacity-0'
'fixed bottom-0 flex w-full flex-col overflow-hidden border-t border-solid border-slate-300 bg-white px-4 pt-2 lg:right-0 lg:top-0 lg:w-96 lg:border-l lg:pt-14',
isOpen ? 'translate-y-0' : 'translate-y-full lg:translate-x-0 lg:translate-y-0',
isOpen ? 'opacity-100' : 'opacity-0 lg:opacity-100'
)}
>
<div className='mb-6 text-xl font-semibold'>Settings</div>
<div className='flex-grow'>
<div className='flex items-center justify-between pt-2 text-xl font-semibold lg:pt-0'>
Settings
<span
className='hover:cursor-pointer lg:hidden'
onClick={() => setIsMinimized(!isMinimized)}
>
{isMinimized ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</span>
</div>

<div className='flex grow flex-col gap-2'>
{/* TODO: move one-on-one logic to its own component */}
{selectedTemplate.id === 'oneOnOneAction' ? (
<div className='rounded-lg bg-slate-200 p-3'>
<div className='text-gray-700 pb-3 text-lg font-semibold'>Teammate</div>
<AdhocTeamMultiSelect
viewerRef={viewer}
onChange={onUserSelected}
value={selectedUser ? [selectedUser] : []}
multiple={false}
/>
<div
className={clsx(
'transition-max-height duration-300 ease-in-out',
isMinimized
? 'max-h-0 opacity-0 lg:max-h-[100vh] lg:opacity-100'
: 'max-h-[100vh] pb-4 lg:pb-0'
)}
>
<div className='mt-6 flex grow flex-col gap-2'>
{/* TODO: move one-on-one logic to its own component */}
{selectedTemplate.id === 'oneOnOneAction' ? (
<div className='rounded-lg bg-slate-200 p-3'>
<div className='text-gray-700 pb-3 text-lg font-semibold'>Teammate</div>
<AdhocTeamMultiSelect
viewerRef={viewer}
onChange={onUserSelected}
value={selectedUser ? [selectedUser] : []}
multiple={false}
/>

{showOrgPicker && (
<>
<div className='text-gray-700 my-4 text-sm font-semibold'>Organization</div>
<Select
onValueChange={(orgId) => setSelectedOrgId(orgId)}
value={selectedOrgId}
>
<SelectTrigger className='bg-white'>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{viewerOrganizations
.filter((org) =>
mutualOrgsIds.length ? mutualOrgsIds.includes(org.id) : true
)
.map((org) => (
<SelectItem value={org.id} key={org.id}>
{org.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</>
)}
</div>
) : (
<NewMeetingTeamPicker
positionOverride={isMobile ? MenuPosition.UPPER_RIGHT : MenuPosition.UPPER_LEFT} // refactor this: https://github.com/ParabolInc/parabol/issues/9274
onSelectTeam={onSelectTeam}
selectedTeamRef={selectedTeam}
teamsRef={availableTeams}
customPortal={teamScopePopover}
allowAddTeam={viewer.featureFlags.adHocTeams}
/>
)}

{showOrgPicker && (
{selectedTeam.tier === 'starter' &&
!viewer.featureFlags.noTemplateLimit &&
!selectedTemplate.isFree ? (
<div className='flex grow flex-col'>
<div className='my-auto text-center'>
Upgrade to the <b>Team Plan</b> to create custom activities unlocking your
team’s ideal workflow.
</div>
<RaisedButton
palette='pink'
className='h-12 w-full text-lg font-semibold text-white focus:outline-none focus:ring-2 focus:ring-offset-2'
onClick={handleUpgrade}
>
Upgrade to Team Plan
</RaisedButton>
</div>
) : (
<>
<div className='text-gray-700 my-4 text-sm font-semibold'>Organization</div>
<Select onValueChange={(orgId) => setSelectedOrgId(orgId)} value={selectedOrgId}>
<SelectTrigger className='bg-white'>
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectGroup>
{viewerOrganizations
.filter((org) =>
mutualOrgsIds.length ? mutualOrgsIds.includes(org.id) : true
)
.map((org) => (
<SelectItem value={org.id} key={org.id}>
{org.name}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
{type === 'retrospective' && (
<>
<NewMeetingSettingsToggleCheckIn settingsRef={selectedTeam.retroSettings} />
<NewMeetingSettingsToggleTeamHealth
settingsRef={selectedTeam.retroSettings}
teamRef={selectedTeam}
/>
<NewMeetingSettingsToggleAnonymity settingsRef={selectedTeam.retroSettings} />
</>
)}
{type === 'poker' && (
<NewMeetingSettingsToggleCheckIn settingsRef={selectedTeam.pokerSettings} />
)}
{type === 'action' && (
<NewMeetingSettingsToggleCheckIn settingsRef={selectedTeam.actionSettings} />
)}
{type === 'teamPrompt' && (
<ActivityDetailsRecurrenceSettings
onRecurrenceSettingsUpdated={setRecurrenceSettings}
recurrenceSettings={recurrenceSettings}
/>
)}
</>
)}
</div>
) : (
<NewMeetingTeamPicker
positionOverride={MenuPosition.UPPER_LEFT}
onSelectTeam={onSelectTeam}
selectedTeamRef={selectedTeam}
teamsRef={availableTeams}
customPortal={teamScopePopover}
allowAddTeam={viewer.featureFlags.adHocTeams}
</div>
</div>

<div className='z-10 flex h-fit w-full flex-col gap-2 pb-4'>
{oneOnOneTeamInput && (
<OneOnOneTeamStatus
email={oneOnOneTeamInput.email}
orgId={oneOnOneTeamInput.orgId}
name={(selectedUser?.id ? selectedUser?.label : selectedUser?.email) ?? ''}
/>
)}

{selectedTeam.tier === 'starter' &&
!viewer.featureFlags.noTemplateLimit &&
!selectedTemplate.isFree ? (
<div className='flex grow flex-col'>
<div className='my-auto text-center'>
Upgrade to the <b>Team Plan</b> to create custom activities unlocking your team’s
ideal workflow.
</div>
<RaisedButton
palette='pink'
className='h-12 w-full text-lg font-semibold text-white focus:outline-none focus:ring-2 focus:ring-offset-2'
onClick={handleUpgrade}
>
Upgrade to Team Plan
</RaisedButton>
</div>
) : (
{error && <StyledError>{error.message}</StyledError>}
{selectedTemplate.id !== 'oneOnOneAction' && (
<>
{type === 'retrospective' && (
<>
<NewMeetingSettingsToggleCheckIn settingsRef={selectedTeam.retroSettings} />
<NewMeetingSettingsToggleTeamHealth
settingsRef={selectedTeam.retroSettings}
teamRef={selectedTeam}
/>
<NewMeetingSettingsToggleAnonymity settingsRef={selectedTeam.retroSettings} />
</>
)}
{type === 'poker' && (
<NewMeetingSettingsToggleCheckIn settingsRef={selectedTeam.pokerSettings} />
)}
{type === 'action' && (
<NewMeetingSettingsToggleCheckIn settingsRef={selectedTeam.actionSettings} />
)}
{type === 'teamPrompt' && (
<ActivityDetailsRecurrenceSettings
onRecurrenceSettingsUpdated={setRecurrenceSettings}
recurrenceSettings={recurrenceSettings}
/>
)}
<div className='flex grow flex-col justify-end gap-2'>
{oneOnOneTeamInput && (
<OneOnOneTeamStatus
email={oneOnOneTeamInput.email}
orgId={oneOnOneTeamInput.orgId}
name={(selectedUser?.id ? selectedUser?.label : selectedUser?.email) ?? ''}
/>
)}
{error && <StyledError>{error.message}</StyledError>}
{selectedTemplate.id !== 'oneOnOneAction' && (
<>
<NewMeetingActionsCurrentMeetings team={selectedTeam} />
{/* TODO: scheduling meeting does not work with one-on-one https://github.com/ParabolInc/parabol/issues/8820 */}
<ScheduleMeetingButton
handleStartActivity={handleStartActivity}
mutationProps={mutationProps}
teamRef={selectedTeam}
/>
</>
)}
<FlatPrimaryButton
onClick={() => handleStartActivity()}
waiting={submitting}
className='h-14'
>
<div className='text-lg'>Start Activity</div>
</FlatPrimaryButton>
</div>
<NewMeetingActionsCurrentMeetings team={selectedTeam} />
{/* TODO: scheduling meeting does not work with one-on-one https://github.com/ParabolInc/parabol/issues/8820 */}
<ScheduleMeetingButton
handleStartActivity={handleStartActivity}
mutationProps={mutationProps}
teamRef={selectedTeam}
/>
</>
)}
<FlatPrimaryButton
onClick={() => handleStartActivity()}
waiting={submitting}
className='h-14'
>
<div className='text-lg'>Start Activity</div>
</FlatPrimaryButton>
</div>
</div>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ const NewMeetingActionsCurrentMeetings = (props: Props) => {
useSnacksForNewMeetings(activeMeetings as any)
const meetingCount = activeMeetings.length
const label = `${meetingCount} Active ${plural(meetingCount, 'Meeting')}`
if (!meetingCount) return null
return (
<>
<CurrentButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const Wrapper = styled('div')({
})

const StyledDialogContainer = styled(DialogContainer)({
width: 'auto'
width: 'auto',
overflowY: 'scroll'
})

const CloseIcon = styled(Close)({
Expand Down

0 comments on commit f3ab591

Please sign in to comment.