hensei-web/components/job/JobSkillItem/index.tsx
Justin Edmund 2d368c32cc Implement removing job skills
We added a (...) button next to each editable job skill that opens a context menu that will allow the user to remove the job skill. An alert is presented to make sure the user is sure before proceeding.

As part of this change, some minor restyling of JobSkillItem was necessary
2023-06-19 02:35:26 -07:00

172 lines
4.4 KiB
TypeScript

import React, { useState } from 'react'
import { useRouter } from 'next/router'
import { Trans, useTranslation } from 'next-i18next'
import classNames from 'classnames'
import Alert from '~components/common/Alert'
import Button from '~components/common/Button'
import {
ContextMenu,
ContextMenuTrigger,
ContextMenuContent,
} from '~components/common/ContextMenu'
import ContextMenuItem from '~components/common/ContextMenuItem'
import EllipsisIcon from '~public/icons/Ellipsis.svg'
import PlusIcon from '~public/icons/Add.svg'
import './index.scss'
// Props
interface Props extends React.ComponentPropsWithoutRef<'div'> {
skill?: JobSkill
position: number
editable: boolean
hasJob: boolean
removeJobSkill: (position: number) => void
}
const JobSkillItem = React.forwardRef<HTMLDivElement, Props>(
function useJobSkillItem(
{
skill,
position,
editable,
hasJob,
removeJobSkill: sendJobSkillToRemove,
...props
},
forwardedRef
) {
// Set up translation
const router = useRouter()
const { t } = useTranslation('common')
const locale =
router.locale && ['en', 'ja'].includes(router.locale)
? router.locale
: 'en'
// States: Component
const [alertOpen, setAlertOpen] = useState(false)
const [contextMenuOpen, setContextMenuOpen] = useState(false)
// Classes
const classes = classNames({
JobSkill: true,
editable: editable,
})
const imageClasses = classNames({
placeholder: !skill,
editable: editable && hasJob,
})
const buttonClasses = classNames({
Clicked: contextMenuOpen,
})
// Methods: Data mutation
function removeJobSkill() {
if (skill) sendJobSkillToRemove(position)
setAlertOpen(false)
}
// Methods: Context menu
function handleButtonClicked() {
setContextMenuOpen(!contextMenuOpen)
}
function handleContextMenuOpenChange(open: boolean) {
if (!open) setContextMenuOpen(false)
}
const skillImage = () => {
let jsx: React.ReactNode
if (skill) {
jsx = (
<img
alt={skill.name[locale]}
className={imageClasses}
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-skills/${skill.slug}.png`}
/>
)
} else {
jsx = (
<div className={imageClasses}>
{editable && hasJob ? <PlusIcon /> : ''}
</div>
)
}
return jsx
}
const label = () => {
let jsx: React.ReactNode
if (skill) {
jsx = <p>{skill.name[locale]}</p>
} else if (editable && hasJob) {
jsx = <p className="placeholder">{t('job_skills.state.selectable')}</p>
} else {
jsx = <p className="placeholder">{t('job_skills.state.no_skill')}</p>
}
return jsx
}
const removeAlert = () => {
return (
<Alert
open={alertOpen}
primaryAction={removeJobSkill}
primaryActionText={t('modals.job_skills.buttons.remove')}
cancelAction={() => setAlertOpen(false)}
cancelActionText={t('buttons.cancel')}
message={
<Trans i18nKey="modals.job_skills.messages.remove">
Are you sure you want to remove{' '}
<strong>{{ job_skill: skill?.name[locale] }}</strong> from your
team?
</Trans>
}
/>
)
}
const contextMenu = () => {
return (
<>
<ContextMenu onOpenChange={handleContextMenuOpenChange}>
<ContextMenuTrigger asChild>
<Button
leftAccessoryIcon={<EllipsisIcon />}
className={buttonClasses}
blended={true}
onClick={handleButtonClicked}
/>
</ContextMenuTrigger>
<ContextMenuContent align="start">
<ContextMenuItem onSelect={() => setAlertOpen(true)}>
{t('context.remove_job_skill')}
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
{removeAlert()}
</>
)
}
return (
<div className={classes} ref={forwardedRef}>
<div className="Info" onClick={props.onClick} tabIndex={0}>
{skillImage()}
{label()}
</div>
{skill && editable && contextMenu()}
</div>
)
}
)
export default JobSkillItem