Refactor Pinned Items into a reusable component

This commit is contained in:
Pico2x 2022-10-06 17:04:00 +01:00
parent 26f04fb04a
commit 59de979949
2 changed files with 118 additions and 93 deletions

View File

@ -145,8 +145,6 @@ function GroupOverviewPinned(props: {
}) { }) {
const { group, posts, isEditable } = props const { group, posts, isEditable } = props
const [pinned, setPinned] = useState<JSX.Element[]>([]) const [pinned, setPinned] = useState<JSX.Element[]>([])
const [open, setOpen] = useState(false)
const [editMode, setEditMode] = useState(false)
useEffect(() => { useEffect(() => {
async function getPinned() { async function getPinned() {
@ -185,100 +183,127 @@ function GroupOverviewPinned(props: {
...(selectedItems as { itemId: string; type: 'contract' | 'post' }[]), ...(selectedItems as { itemId: string; type: 'contract' | 'post' }[]),
], ],
}) })
setOpen(false) }
function onDeleteClicked(index: number) {
const newPinned = group.pinnedItems.filter((item) => {
return item.itemId !== group.pinnedItems[index].itemId
})
updateGroup(group, { pinnedItems: newPinned })
} }
return isEditable || (group.pinnedItems && group.pinnedItems.length > 0) ? ( return isEditable || (group.pinnedItems && group.pinnedItems.length > 0) ? (
pinned.length > 0 || isEditable ? ( <PinnedItems
<div> posts={posts}
<Row className="mb-3 items-center justify-between"> group={group}
<SectionHeader label={'Pinned'} /> isEditable={isEditable}
{isEditable && ( pinned={pinned}
<Button onDeleteClicked={onDeleteClicked}
color="gray" onSubmit={onSubmit}
size="xs" modalMessage={'Pin posts or markets to the overview of this group.'}
onClick={() => { />
setEditMode(!editMode) ) : (
}} <LoadingIndicator />
> )
{editMode ? ( }
'Done'
) : (
<>
<PencilIcon className="inline h-4 w-4" />
Edit
</>
)}
</Button>
)}
</Row>
<div>
<Masonry
breakpointCols={{ default: 2, 768: 1 }}
className="-ml-4 flex w-auto"
columnClassName="pl-4 bg-clip-padding"
>
{pinned.length == 0 && !editMode && (
<div className="flex flex-col items-center justify-center">
<p className="text-center text-gray-400">
No pinned items yet. Click the edit button to add some!
</p>
</div>
)}
{pinned.map((element, index) => (
<div className="relative my-2">
{element}
{editMode && ( export function PinnedItems(props: {
<CrossIcon posts: Post[]
onClick={() => { isEditable: boolean
const newPinned = group.pinnedItems.filter((item) => { pinned: JSX.Element[]
return item.itemId !== group.pinnedItems[index].itemId onDeleteClicked: (index: number) => void
}) onSubmit: (selectedItems: { itemId: string; type: string }[]) => void
updateGroup(group, { pinnedItems: newPinned }) group?: Group
}} modalMessage: string
/> }) {
)} const {
</div> isEditable,
))} pinned,
{editMode && group.pinnedItems && pinned.length < 6 && ( onDeleteClicked,
<div className=" py-2"> onSubmit,
<Row posts,
className={ group,
'relative gap-3 rounded-lg border-4 border-dotted p-2 hover:cursor-pointer hover:bg-gray-100' modalMessage,
} } = props
> const [editMode, setEditMode] = useState(false)
<button const [open, setOpen] = useState(false)
className="flex w-full justify-center"
onClick={() => setOpen(true)} return pinned.length > 0 || isEditable ? (
> <div>
<PlusCircleIcon <Row className="mb-3 items-center justify-between">
className="h-12 w-12 text-gray-600" <SectionHeader label={'Pinned'} />
aria-hidden="true" {isEditable && (
/> <Button
</button> color="gray"
</Row> size="xs"
</div> onClick={() => {
setEditMode(!editMode)
}}
>
{editMode ? (
'Done'
) : (
<>
<PencilIcon className="inline h-4 w-4" />
Edit
</>
)} )}
</Masonry> </Button>
</div> )}
<PinnedSelectModal </Row>
open={open} <div>
group={group} <Masonry
posts={posts} breakpointCols={{ default: 2, 768: 1 }}
setOpen={setOpen} className="-ml-4 flex w-auto"
title="Pin a post or market" columnClassName="pl-4 bg-clip-padding"
description={ >
<div className={'text-md my-4 text-gray-600'}> {pinned.length == 0 && !editMode && (
Pin posts or markets to the overview of this group. <div className="flex flex-col items-center justify-center">
<p className="text-center text-gray-400">
No pinned items yet. Click the edit button to add some!
</p>
</div> </div>
} )}
onSubmit={onSubmit} {pinned.map((element, index) => (
/> <div className="relative my-2">
{element}
{editMode && <CrossIcon onClick={() => onDeleteClicked(index)} />}
</div>
))}
{editMode && pinned.length < 6 && (
<div className=" py-2">
<Row
className={
'relative gap-3 rounded-lg border-4 border-dotted p-2 hover:cursor-pointer hover:bg-gray-100'
}
>
<button
className="flex w-full justify-center"
onClick={() => setOpen(true)}
>
<PlusCircleIcon
className="h-12 w-12 text-gray-600"
aria-hidden="true"
/>
</button>
</Row>
</div>
)}
</Masonry>
</div> </div>
) : ( <PinnedSelectModal
<LoadingIndicator /> open={open}
) group={group}
posts={posts}
setOpen={setOpen}
title="Pin a post or market"
description={
<div className={'text-md my-4 text-gray-600'}>{modalMessage}</div>
}
onSubmit={onSubmit}
/>
</div>
) : ( ) : (
<></> <></>
) )

View File

@ -20,8 +20,8 @@ export function PinnedSelectModal(props: {
selectedItems: { itemId: string; type: string }[] selectedItems: { itemId: string; type: string }[]
) => void | Promise<void> ) => void | Promise<void>
contractSearchOptions?: Partial<Parameters<typeof ContractSearch>[0]> contractSearchOptions?: Partial<Parameters<typeof ContractSearch>[0]>
group: Group
posts: Post[] posts: Post[]
group?: Group
}) { }) {
const { const {
title, title,
@ -134,8 +134,8 @@ export function PinnedSelectModal(props: {
highlightClassName: highlightClassName:
'!bg-indigo-100 outline outline-2 outline-indigo-300', '!bg-indigo-100 outline outline-2 outline-indigo-300',
}} }}
additionalFilter={{ groupSlug: group.slug }} additionalFilter={group ? { groupSlug: group.slug } : undefined}
persistPrefix={`group-${group.slug}`} persistPrefix={group ? `group-${group.slug}` : undefined}
headerClassName="bg-white sticky" headerClassName="bg-white sticky"
{...contractSearchOptions} {...contractSearchOptions}
/> />
@ -152,7 +152,7 @@ export function PinnedSelectModal(props: {
'!bg-indigo-100 outline outline-2 outline-indigo-300', '!bg-indigo-100 outline outline-2 outline-indigo-300',
}} }}
/> />
{posts.length === 0 && ( {posts.length == 0 && (
<div className="text-center text-gray-500">No posts yet</div> <div className="text-center text-gray-500">No posts yet</div>
)} )}
</div> </div>