|
import React, { useState } from 'react'; |
|
import { useThemeStyles } from 'components/styles'; |
|
import { Post } from 'resources/domain/entity/IItem'; |
|
import useLang from 'components/hooks/useLang'; |
|
import { Box, Grid, makeStyles, Typography } from '@material-ui/core' |
|
import { DropDown, MenuItem } from './CommonDropDown'; |
|
import { yupResolver } from '@hookform/resolvers/yup'; |
|
import InputCommentWrapper from 'components/utilities/InputCommentWrapper'; |
|
import { FormProvider, useForm } from 'react-hook-form'; |
|
import { |
|
IItemInitialValues, |
|
ItemCreateButtonState, |
|
ItemValidationSchema, |
|
} from 'components/views/GroupFeed'; |
|
import { getTextWithEllipsis } from 'util/getTextWithEllipsis'; |
|
import { CommonButton } from './CommonButton'; |
|
import { ChatBubbleOutline, LocalOffer } from '@material-ui/icons'; |
|
import { useSelector } from 'react-redux'; |
|
import { RootState } from 'state_management/reducers'; |
|
import { IItemDetailProps } from 'resources/domain/entity/IItem'; |
|
import { |
|
ISaleItemDetailProps, |
|
PostType, |
|
} from 'resources/domain/entity/ISaleItem'; |
|
import userImage from 'assets/images/user-avatar.png'; |
|
import { useSnackbar } from 'components/notification/SnackbarNotification'; |
|
import { useMutation } from 'services/useMutation'; |
|
import { useSetUserInterestOnPusher } from 'services/notifications/pusher'; |
|
import PostFeed, { usePostCacheClearing } from '../views/GroupFeed/PostFeed'; |
|
import { GroupId } from 'src/services/groupService/models/groupModel'; |
|
import { PostTypeFilter } from 'components/views/GroupFeed/PostFeed'; |
|
import { RuleId } from 'src/services/rulesService/models/rules'; |
|
|
|
const CreateEngagementPost = React.lazy( |
|
() => import('../views/CreateEngagementPost') |
|
); |
|
const CreateSalePost = React.lazy(() => import('../views/CreateSalePost')); |
|
|
|
/** |
|
* Styles logic for this component. |
|
*/ |
|
const useStyles = makeStyles({ |
|
createPostCard: { |
|
backgroundColor: '#fff', |
|
borderRadius: '10px', |
|
boxShadow: '0px 3px 6px #0000000D', |
|
marginBottom: '15px', |
|
paddingBottom: '10px', |
|
}, |
|
createPostCardTop: { |
|
borderBottom: '1px solid #707070', |
|
padding: '15px', |
|
'& h2': { |
|
color: '#000', |
|
fontSize: '22px', |
|
fontWeight: 400, |
|
height: '100%', |
|
display: 'flex', |
|
alignItems: 'center', |
|
}, |
|
'& p': { |
|
color: '#000', |
|
fontSize: '22px', |
|
fontWeight: 400, |
|
'& a': { |
|
color: '#000', |
|
}, |
|
}, |
|
}, |
|
|
|
createPostCardMid: { |
|
margin: '15px', |
|
display: 'flex', |
|
alignItems: 'center', |
|
borderBottom: '1px solid #707070', |
|
paddingBottom: '10px', |
|
'& .MuiFormControl-root': { |
|
width: '100%', |
|
}, |
|
}, |
|
circleImage: { |
|
'& img': { |
|
borderRadius: '100%', |
|
width: '50px', |
|
height: '50px', |
|
minWidth: '50px', |
|
objectFit: 'cover', |
|
objectPosition: 'center', |
|
}, |
|
}, |
|
createPostCardBottom: { |
|
display: 'flex', |
|
alignItems: 'center', |
|
justifyContent: 'space-between', |
|
padding: '15px', |
|
'& span': { |
|
color: '#707070', |
|
display: 'flex', |
|
alignItems: 'center', |
|
marginRight: '5px', |
|
cursor: 'pointer', |
|
'& svg': { |
|
width: '18px', |
|
marginRight: '5px', |
|
minWidth: '18px', |
|
marginTop: '-3px', |
|
}, |
|
}, |
|
}, |
|
}); |
|
|
|
/** |
|
* This function handles all the posts in Group Feed view. |
|
*/ |
|
const CommonGroupItemsList = ({ |
|
postType, |
|
companyId, |
|
groupId, |
|
ruleId, |
|
}: { |
|
postType?: PostTypeFilter; |
|
companyId?: string; |
|
groupId: GroupId; |
|
ruleId?: RuleId; |
|
}): JSX.Element => { |
|
const styleClasses = useStyles(); |
|
const commonStyleClasses = useThemeStyles(); |
|
const { f: translation } = useLang(); |
|
const { sendMessage } = useSnackbar(); |
|
const [loading, setLoading] = useState<boolean>(); |
|
|
|
const postCacheClearing = usePostCacheClearing(); |
|
|
|
const userInfo = useSelector((states: RootState) => states.authReducer.user); |
|
const [showCreatePostModal, setShowCreatePostModal] = useState(false); |
|
const [showCreateSalePostModal, setShowCreateSalePostModal] = useState(false); |
|
const [item, setItem] = useState<Post>(); |
|
|
|
const { mutateAsync: updateSaleMutateAsync } = useMutation({ |
|
mutationKey: 'saleItemsAndOffers.updateSaleItem', |
|
}); |
|
const { mutateAsync: createSaleMutateAsync } = useMutation({ |
|
mutationKey: 'saleItemsAndOffers.createSaleItem', |
|
}); |
|
const { mutateAsync: createDiscussionMutateAsync } = useMutation({ |
|
mutationKey: 'items.createItemForGroup', |
|
}); |
|
const { mutateAsync: updateDiscussionMutateAsync } = useMutation({ |
|
mutationKey: 'items.updateItemById', |
|
}); |
|
|
|
// eventEmitter.subscribe(EventType.REFETCH_ITEM, 'refetch', () => |
|
// postsResponse.refetch() |
|
// ); |
|
|
|
const ItemDropdown = [ |
|
{ id: 1, title: 'Discussion', icon: <ChatBubbleOutline /> }, |
|
{ id: 2, title: 'Sale', icon: <LocalOffer /> }, |
|
]; |
|
|
|
const { updateUserInterests } = useSetUserInterestOnPusher(); |
|
|
|
/** |
|
* This function handles create post in a modal. |
|
*/ |
|
const handleCreatePostModal = (id: string, value: boolean) => { |
|
if (id === 'Discussion') setShowCreatePostModal(value); |
|
if (id === 'Sale') setShowCreateSalePostModal(value); |
|
setItem(undefined); |
|
}; |
|
|
|
/** |
|
* Setting Initial values for the Create Post |
|
*/ |
|
const initialValues = { |
|
title: '', |
|
}; |
|
|
|
const methods = useForm({ |
|
resolver: yupResolver(ItemValidationSchema(translation)), |
|
}); |
|
|
|
const { |
|
handleSubmit, |
|
reset, |
|
watch, |
|
formState: { errors }, |
|
} = methods; |
|
|
|
/** |
|
* This function creates the post. |
|
*/ |
|
const onSubmit = async ( |
|
createItemPayload: |
|
| { |
|
postType: 'Discussion'; |
|
itemsData: IItemDetailProps; |
|
isUpdate: boolean; |
|
} |
|
| { |
|
postType: 'Sale'; |
|
itemsSaleData: ISaleItemDetailProps; |
|
isUpdate: boolean; |
|
} |
|
) => { |
|
if (!groupId) { |
|
sendMessage({ |
|
message: translation('app.item.create.group.undefined').replace( |
|
'postType', |
|
createItemPayload.postType.toLowerCase() |
|
), |
|
}); |
|
return; |
|
} |
|
switch (createItemPayload.postType) { |
|
case 'Discussion': |
|
return (async () => { |
|
const res = !createItemPayload.isUpdate |
|
? await createDiscussionMutateAsync({ |
|
groupId, |
|
data: createItemPayload.itemsData, |
|
}) |
|
: item && |
|
(await updateDiscussionMutateAsync({ |
|
params: { groupId, itemId: item.id }, |
|
data: createItemPayload.itemsData, |
|
})); |
|
if ([res?.data?.code].includes(200)) { |
|
sendMessage({ |
|
message: translation('app.item.message.create.success'), |
|
severity: 'success', |
|
}); |
|
reset({ ...initialValues }); |
|
postCacheClearing({ |
|
groupId, |
|
// @ts-expect-error - these types are a mess |
|
userId: userInfo.id, |
|
// todo: find a better way to get this |
|
// @ts-expect-error - companyId should not be optional on a user |
|
companyId: userInfo.company.id, |
|
}); |
|
|
|
// postsResponse.refetch(); |
|
handleCreatePostModal('Discussion', false); |
|
updateUserInterests(); |
|
} |
|
})(); |
|
case 'Sale': |
|
return (async () => { |
|
const res = !createItemPayload.isUpdate |
|
? await createSaleMutateAsync({ |
|
groupId, |
|
data: createItemPayload.itemsSaleData, |
|
}) |
|
: item?.sale?.id |
|
? await updateSaleMutateAsync({ |
|
groupId, |
|
saleId: item?.sale?.id, |
|
data: createItemPayload.itemsSaleData, |
|
}) |
|
: undefined; |
|
if ([res?.data?.code].includes(200)) { |
|
sendMessage({ |
|
message: createItemPayload.isUpdate |
|
? translation('app.item.message.update.success') |
|
: translation('app.item.message.create.success'), |
|
severity: 'success', |
|
}); |
|
reset({ ...initialValues }); |
|
postCacheClearing({ |
|
groupId, |
|
// @ts-expect-error - these types are a mess |
|
userId: userInfo.id, |
|
// todo: find a better way to get this |
|
// @ts-expect-error - companyId should not be optional on a user |
|
companyId: userInfo.company.id, |
|
}); |
|
|
|
handleCreatePostModal('Sale', false); |
|
updateUserInterests(); |
|
} |
|
})(); |
|
default: |
|
return ((_payload: never) => null)(createItemPayload); |
|
} |
|
}; |
|
/** |
|
* The function gets the data from React hook form and creates discussion items in database |
|
* If an item images are available then the function will upload it on S3 bucket and return a URL. |
|
* It then appends the URL with the data and stores it in the database |
|
* |
|
* @param data |
|
*/ |
|
const onCreateItem = async (data: IItemInitialValues) => { |
|
setLoading(true); |
|
const itemsData = { |
|
title: data.title, |
|
postType: PostType.DISCUSSION, |
|
description: '', |
|
commentsAllowed: true, |
|
}; |
|
await onSubmit({ postType: 'Discussion', itemsData, isUpdate: false }); |
|
setLoading(false); |
|
}; |
|
|
|
return ( |
|
<div> |
|
{!companyId ? ( |
|
<Box className={styleClasses.createPostCard}> |
|
<Box className={styleClasses.createPostCardTop}> |
|
<Grid container> |
|
<Grid xs={6}> |
|
<Typography variant="h2"> |
|
{translation('app.item.create')} |
|
</Typography> |
|
</Grid> |
|
<Grid xs={6}> |
|
<Box className={commonStyleClasses.textRight}> |
|
<DropDown |
|
label={translation('app.feed.item.type.label')} |
|
items={ItemDropdown} |
|
onItemClick={(item: MenuItem) => |
|
handleCreatePostModal(item?.title as string, true) |
|
} |
|
/> |
|
</Box> |
|
</Grid> |
|
</Grid> |
|
</Box> |
|
|
|
<FormProvider {...methods}> |
|
<Box className={styleClasses.createPostCardMid}> |
|
<Box className={styleClasses.circleImage}> |
|
<img |
|
src={userInfo.avatar ?? userImage} |
|
alt={getTextWithEllipsis({ text: userInfo.name, limit: 10 })} |
|
/> |
|
</Box> |
|
<InputCommentWrapper |
|
name="title" |
|
placeholder={translation('app.item.create.placeholder')} |
|
type="text" |
|
errorobj={errors as { [key: string]: { message: string } }} |
|
multiline |
|
minRows={1} |
|
disabled={loading} |
|
/> |
|
<Typography align="right" className={commonStyleClasses.ml20}> |
|
<CommonButton |
|
size="medium" |
|
label="Post" |
|
onClick={handleSubmit(onCreateItem)} |
|
loading={loading} |
|
disabled={loading} |
|
/> |
|
</Typography> |
|
</Box> |
|
</FormProvider> |
|
|
|
<Box className={styleClasses.createPostCardBottom}> |
|
{ItemCreateButtonState?.map((info, index) => ( |
|
<span |
|
key={index} |
|
onClick={() => handleCreatePostModal('Discussion', true)} |
|
> |
|
{info?.icon} |
|
{info?.label} |
|
</span> |
|
))} |
|
</Box> |
|
</Box> |
|
) : null} |
|
<PostFeed groupId={groupId} postType={postType} ruleId={ruleId} /> |
|
{showCreatePostModal ? ( |
|
<CreateEngagementPost |
|
open={showCreatePostModal} |
|
onCloseModal={() => { |
|
handleCreatePostModal('Discussion', false); |
|
reset(); |
|
}} |
|
title={watch('title', '')} |
|
onSubmit={onSubmit} |
|
item={item} |
|
/> |
|
) : null} |
|
{showCreateSalePostModal ? ( |
|
<CreateSalePost |
|
open={showCreateSalePostModal} |
|
onCloseModal={() => handleCreatePostModal('Sale', false)} |
|
title={watch('title', '')} |
|
onSubmit={onSubmit} |
|
item={item} |
|
/> |
|
) : null} |
|
</div> |
|
); |
|
}; |
|
|
|
export default CommonGroupItemsList; |