[questions][ui] add to list dropdown

pull/468/head
wlren 3 years ago
parent 9f214cddc2
commit a08d7e22b7

@ -0,0 +1,89 @@
import { forwardRef, Fragment, useEffect, useRef, useState } from 'react';
import { Menu, Transition } from '@headlessui/react';
import { CheckIcon, HeartIcon } from '@heroicons/react/20/solid';
import { lists } from '~/pages/questions/lists';
function classNames(...classes: Array<string>) {
return classes.filter(Boolean).join(' ');
}
export default function AddToListDropdown() {
const [menuOpened, setMenuOpened] = useState(false);
const ref = useRef() as React.MutableRefObject<HTMLDivElement>;
const addClickOutsideListener = () => {
document.addEventListener('click', handleClickOutside, true);
};
const handleClickOutside = (event: MouseEvent) => {
if (!ref.current.contains(event.target as Node)) {
setMenuOpened(false);
document.removeEventListener('click', handleClickOutside, true);
}
};
const CustomMenuButton = ({ children }: any) => (
<button
className="focus:ring-primary-500 inline-flex w-full justify-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-700 shadow-sm hover:bg-slate-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-slate-100"
type="button"
onClick={() => {
addClickOutsideListener();
setMenuOpened(!menuOpened);
}}>
{children}
</button>
);
return (
<Menu ref={ref} as="div" className="relative inline-block text-left">
<div>
<Menu.Button as={CustomMenuButton}>
<HeartIcon aria-hidden="true" className="-ml-1 mr-2 h-5 w-5" />
Add to List
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
show={menuOpened}>
<Menu.Items
className="absolute right-0 z-10 mt-2 w-56 origin-top-right divide-y divide-slate-100 rounded-md bg-white shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
static={true}>
{menuOpened && (
<>
{lists.map((list) => (
<div key={list.id} className="py-1">
<Menu.Item>
{({ active }) => (
<button
className={classNames(
active
? 'bg-slate-100 text-slate-900'
: 'text-slate-700',
'group flex w-full items-center px-4 py-2 text-sm',
)}
type="button">
<CheckIcon
aria-hidden="true"
className="mr-3 h-5 w-5 text-slate-400 group-hover:text-slate-500"
/>
list.name
</button>
)}
</Menu.Item>
</div>
))}
</>
)}
</Menu.Items>
</Transition>
</Menu>
);
}

@ -11,6 +11,7 @@ import { Button } from '@tih/ui';
import { useQuestionVote } from '~/utils/questions/useVote';
import AddToListDropdown from '../../AddToListDropdown';
import type { CreateQuestionEncounterData } from '../../forms/CreateQuestionEncounterForm';
import CreateQuestionEncounterForm from '../../forms/CreateQuestionEncounterForm';
import QuestionAggregateBadge from '../../QuestionAggregateBadge';
@ -79,7 +80,16 @@ type CreateEncounterProps =
showCreateEncounterButton?: false;
};
type AddToListProps =
| {
showAddToList: true;
}
| {
showAddToList?: false;
};
export type BaseQuestionCardProps = ActionButtonProps &
AddToListProps &
AnswerStatisticsProps &
CreateEncounterProps &
DeleteProps &
@ -117,6 +127,7 @@ export default function BaseQuestionCard({
showHover,
onReceivedSubmit,
showDeleteButton,
showAddToList,
onDelete,
truncateContent = true,
}: BaseQuestionCardProps) {
@ -135,12 +146,17 @@ export default function BaseQuestionCard({
)}
<div className="flex flex-col items-start gap-2">
<div className="flex items-baseline justify-between">
<div className="flex items-baseline gap-2 text-slate-500">
<div className="flex items-center gap-2 text-slate-500">
<QuestionTypeBadge type={type} />
<QuestionAggregateBadge statistics={companies} variant="primary" />
<QuestionAggregateBadge statistics={locations} variant="success" />
<QuestionAggregateBadge statistics={roles} variant="danger" />
<p className="text-xs">{timestamp}</p>
{showAddToList && (
<div className="pl-4">
<AddToListDropdown></AddToListDropdown>
</div>
)}
</div>
{showActionButton && (
<Button

@ -4,6 +4,7 @@ import BaseQuestionCard from './BaseQuestionCard';
export type QuestionOverviewCardProps = Omit<
BaseQuestionCardProps & {
showActionButton: false;
showAddToList: true;
showAnswerStatistics: false;
showCreateEncounterButton: true;
showDeleteButton: false;
@ -13,6 +14,7 @@ export type QuestionOverviewCardProps = Omit<
| 'actionButtonLabel'
| 'onActionButtonClick'
| 'showActionButton'
| 'showAddToList'
| 'showAnswerStatistics'
| 'showCreateEncounterButton'
| 'showDeleteButton'
@ -25,6 +27,7 @@ export default function FullQuestionCard(props: QuestionOverviewCardProps) {
<BaseQuestionCard
{...props}
showActionButton={false}
showAddToList={true}
showAnswerStatistics={false}
showCreateEncounterButton={true}
showReceivedStatistics={false}

@ -16,8 +16,7 @@ import { APP_TITLE } from '~/utils/questions/constants';
import { SAMPLE_QUESTION } from '~/utils/questions/constants';
import createSlug from '~/utils/questions/createSlug';
export default function ListPage() {
const questions = [
export const questions = [
SAMPLE_QUESTION,
SAMPLE_QUESTION,
SAMPLE_QUESTION,
@ -33,16 +32,17 @@ export default function ListPage() {
SAMPLE_QUESTION,
SAMPLE_QUESTION,
SAMPLE_QUESTION,
];
];
const lists = [
export const lists = [
{ id: 1, name: 'list 1', questions },
{ id: 2, name: 'list 2', questions },
{ id: 3, name: 'list 3', questions },
{ id: 4, name: 'list 4', questions },
{ id: 5, name: 'list 5', questions },
];
];
export default function ListPage() {
const [selectedList, setSelectedList] = useState(
(lists ?? []).length > 0 ? lists[0].id : '',
);

Loading…
Cancel
Save