Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated user post screen UI #2046

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17,685 changes: 17,683 additions & 2 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"react-i18next": "^11.18.1",
"react-icons": "^5.2.1",
"react-infinite-scroll-component": "^6.1.0",
"react-multi-carousel": "^2.8.5",
"react-redux": "^7.2.5",
"react-router-dom": "^6.23.1",
"react-scripts": "5.0.1",
Expand Down
4 changes: 2 additions & 2 deletions src/GraphQl/Mutations/OrganizationMutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ export const PLUGIN_SUBSCRIPTION = gql`
*/

export const TOGGLE_PINNED_POST = gql`
mutation TogglePostPin($id: ID!) {
togglePostPin(id: $id) {
mutation TogglePostPin($id: ID!, $title: String) {
togglePostPin(id: $id, title: $title) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

The inspection of the relevant lines indicates that:

  • In src/components/OrgPostCard/OrgPostCard.tsx, the title parameter is included in the toggle mutation call.
  • In src/components/OrgPostCard/OrgPostCard.test.tsx, the title parameter is not included in the test's mutation call.

To avoid runtime errors, the test file should also include the title parameter. Here are the specific locations that need attention:

  • src/components/OrgPostCard/OrgPostCard.test.tsx: Ensure the title parameter is included in the mutation call.
Analysis chain

The addition of the title parameter to the TOGGLE_PINNED_POST mutation enhances the functionality by allowing the title of the post to be included when toggling its pinned status. Ensure that all calls to this mutation in the frontend now include this new parameter to avoid runtime errors.


The search results provided context around the instances of TOGGLE_PINNED_POST, but they still do not clearly show whether the title parameter is being included in the mutation calls. To definitively verify this, we need to inspect the relevant lines more closely.

The next step is to extract the specific lines of code where the mutation is called and check if the title parameter is included.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify all function calls to `TOGGLE_PINNED_POST` include the `title` parameter.

# Test: Search for the function usage. Expect: Only occurrences of the new signature.
rg --type graphql $'TOGGLE_PINNED_POST'

Length of output: 70



Script:

#!/bin/bash
# Description: Verify all function calls to `TOGGLE_PINNED_POST` include the `title` parameter.

# Test: Search for the function usage in JavaScript and TypeScript files. Expect: Only occurrences of the new signature.
rg 'TOGGLE_PINNED_POST' --type js --type ts

Length of output: 497



Script:

#!/bin/bash
# Description: Verify all function calls to `TOGGLE_PINNED_POST` include the `title` parameter.

# Inspect the relevant files for the correct usage of `TOGGLE_PINNED_POST` with the `title` parameter
rg --multiline --multiline-dotall 'TOGGLE_PINNED_POST' src/components/OrgPostCard/OrgPostCard.test.tsx src/components/OrgPostCard/OrgPostCard.tsx src/GraphQl/Mutations/mutations.ts

Length of output: 548



Script:

#!/bin/bash
# Description: Verify all function calls to `TOGGLE_PINNED_POST` include the `title` parameter.

# Extract more lines around each match to provide context
rg --multiline --multiline-dotall -C 5 'TOGGLE_PINNED_POST' src/components/OrgPostCard/OrgPostCard.test.tsx src/components/OrgPostCard/OrgPostCard.tsx src/GraphQl/Mutations/mutations.ts

Length of output: 4239



Script:

#!/bin/bash
# Description: Verify all function calls to `TOGGLE_PINNED_POST` include the `title` parameter.

# Extract specific lines around the mutation calls to check for the inclusion of the `title` parameter
rg --multiline --multiline-dotall -A 10 'useMutation\(TOGGLE_PINNED_POST\)' src/components/OrgPostCard/OrgPostCard.tsx
rg --multiline --multiline-dotall -A 10 'query: TOGGLE_PINNED_POST' src/components/OrgPostCard/OrgPostCard.test.tsx

Length of output: 738

_id
}
}
Expand Down
1 change: 1 addition & 0 deletions src/components/OrgPostCard/OrgPostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export default function orgPostCard(
const { data } = await toggle({
variables: {
id,
title: props.postTitle,
},
});
if (data) {
Expand Down
7 changes: 5 additions & 2 deletions src/components/UserPortal/PostCard/PostCard.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
.cardStyles {
height: 28rem;
max-height: 30rem;
width: 20rem;
background-color: white;
padding: 0;
Expand Down Expand Up @@ -178,3 +176,8 @@
outline: none;
background-color: #f1f3f6;
}

.postImage {
height: 300px;
object-fit: cover;
}
4 changes: 1 addition & 3 deletions src/components/UserPortal/PostCard/PostCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ export default function postCard(props: InterfacePostCard): JSX.Element {
</Dropdown>
</Card.Header>
<Card.Img
className={styles.postImage}
variant="top"
src={
props.image === '' || props.image === null
Expand All @@ -291,9 +292,6 @@ export default function postCard(props: InterfacePostCard): JSX.Element {
<Card.Text className={`${styles.cardText} mt-4`}>
{props.text}
</Card.Text>
{props.image && (
<img src={props.image} className={styles.imageContainer} />
)}
</Card.Body>
<Card.Footer style={{ border: 'none', background: 'white' }}>
<div className={`${styles.cardActions}`}>
Expand Down
2 changes: 1 addition & 1 deletion src/screens/LoginPage/LoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const loginPage = (): JSX.Element => {
id: string;
};
tempObj['label'] =
`${org.name}(${org.address.city},${org.address.state},${org.address.countryCode})`;
`${org.name}(${org.address?.city},${org.address?.state},${org.address?.countryCode})`;
tempObj['id'] = org._id;
return tempObj;
},
Expand Down
124 changes: 66 additions & 58 deletions src/screens/UserPortal/Posts/Posts.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { useQuery } from '@apollo/client';
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
import SendIcon from '@mui/icons-material/Send';
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
import {
ADVERTISEMENTS_GET,
ORGANIZATION_ADVERTISEMENT_LIST,
ORGANIZATION_POST_LIST,
USER_DETAILS,
} from 'GraphQl/Queries/Queries';
import PostCard from 'components/UserPortal/PostCard/PostCard';
import type {
InterfacePostCard,
InterfaceQueryOrganizationAdvertisementListItem,
InterfaceQueryUserListItem,
} from 'utils/interfaces';
import PromotedPost from 'components/UserPortal/PromotedPost/PromotedPost';
Expand All @@ -23,7 +22,36 @@ import { Navigate, useParams } from 'react-router-dom';
import useLocalStorage from 'utils/useLocalstorage';
import styles from './Posts.module.css';
import convertToBase64 from 'utils/convertToBase64';
import Carousel from 'react-multi-carousel';
import 'react-multi-carousel/lib/styles.css';

const responsive = {
superLargeDesktop: {
breakpoint: { max: 4000, min: 3000 },
items: 5,
},
desktop: {
breakpoint: { max: 3000, min: 1024 },
items: 3,
},
tablet: {
breakpoint: { max: 1024, min: 600 },
items: 2,
},
mobile: {
breakpoint: { max: 600, min: 0 },
items: 1,
},
};

type Ad = {
_id: string;
name: string;
type: 'BANNER' | 'MENU' | 'POPUP';
mediaUrl: string;
endDate: string; // Assuming it's a string in the format 'yyyy-MM-dd'
startDate: string; // Assuming it's a string in the format 'yyyy-MM-dd'
};
interface InterfaceAdContent {
_id: string;
name: string;
Expand All @@ -45,10 +73,6 @@ type AdvertisementsConnection = {
}[];
};

interface InterfaceAdConnection {
advertisementsConnection?: AdvertisementsConnection;
}

type InterfacePostComments = {
creator: {
_id: string;
Expand Down Expand Up @@ -101,8 +125,7 @@ export default function home(): JSX.Element {
const { getItem } = useLocalStorage();
const [posts, setPosts] = useState([]);
const [pinnedPosts, setPinnedPosts] = useState([]);
const [adContent, setAdContent] = useState<InterfaceAdConnection>({});
const [filteredAd, setFilteredAd] = useState<InterfaceAdContent[]>([]);

const [showModal, setShowModal] = useState<boolean>(false);
const [postImg, setPostImg] = useState<string | null>('');
const { orgId } = useParams();
Expand All @@ -111,17 +134,32 @@ export default function home(): JSX.Element {
return <Navigate to={'/user'} />;
}

const navbarProps = {
currentPage: 'home',
};
const { data: promotedPostsData } = useQuery(ADVERTISEMENTS_GET);
const {
data: promotedPostsData,
}: {
data?: {
organizations: InterfaceQueryOrganizationAdvertisementListItem[];
};
refetch: () => void;
} = useQuery(ORGANIZATION_ADVERTISEMENT_LIST, {
variables: {
id: orgId,
first: 6,
},
});
const {
data,
refetch,
loading: loadingPosts,
} = useQuery(ORGANIZATION_POST_LIST, {
variables: { id: orgId, first: 10 },
});

const [adContent, setAdContent] = useState(
promotedPostsData?.organizations[0].advertisements?.edges.map(
(edge: { node: Ad }) => edge.node,
) || [],
);
const userId: string | null = getItem('userId');

const { data: userData } = useQuery(USER_DETAILS, {
Expand All @@ -137,15 +175,16 @@ export default function home(): JSX.Element {
}, [data]);

useEffect(() => {
if (promotedPostsData) {
setAdContent(promotedPostsData);
if (promotedPostsData && promotedPostsData.organizations) {
const ads: Ad[] =
promotedPostsData.organizations[0].advertisements?.edges.map(
(edge) => edge.node,
);

setAdContent(ads);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The use of optional chaining here can prevent potential runtime errors when promotedPostsData.organizations might be undefined. This change is suggested by static analysis and should be incorporated to enhance code robustness.

-      const ads: Ad[] = promotedPostsData.organizations[0].advertisements?.edges.map((edge) => edge.node);
+      const ads: Ad[] = promotedPostsData?.organizations[0]?.advertisements?.edges.map((edge) => edge.node) || [];
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (promotedPostsData && promotedPostsData.organizations) {
const ads: Ad[] =
promotedPostsData.organizations[0].advertisements?.edges.map(
(edge) => edge.node,
);
setAdContent(ads);
if (promotedPostsData && promotedPostsData.organizations) {
const ads: Ad[] =
promotedPostsData?.organizations[0]?.advertisements?.edges.map(
(edge) => edge.node,
) || [];
setAdContent(ads);
Tools
Biome

[error] 178-178: Change to an optional chain. (lint/complexity/useOptionalChain)

Unsafe fix: Change to an optional chain.

}
}, [promotedPostsData]);

useEffect(() => {
setFilteredAd(filterAdContent(adContent, orgId));
}, [adContent]);

useEffect(() => {
setPinnedPosts(
posts.filter(({ node }: { node: InterfacePostNode }) => {
Expand All @@ -154,34 +193,6 @@ export default function home(): JSX.Element {
);
}, [posts]);

const filterAdContent = (
data: {
advertisementsConnection?: {
edges: {
node: InterfaceAdContent;
}[];
};
},
currentOrgId: string,
currentDate: Date = new Date(),
): InterfaceAdContent[] => {
const { advertisementsConnection } = data;

if (advertisementsConnection && advertisementsConnection.edges) {
const { edges } = advertisementsConnection;

return edges
.map((edge) => edge.node)
.filter(
(ad: InterfaceAdContent) =>
ad.organization._id === currentOrgId &&
new Date(ad.endDate) > currentDate,
);
}

return [];
};

const getCardProps = (node: InterfacePostNode): InterfacePostCard => {
const {
creator,
Expand Down Expand Up @@ -321,21 +332,18 @@ export default function home(): JSX.Element {
>
<h2>{t('feed')}</h2>
{pinnedPosts.length > 0 && (
<div>
<p className="fs-5 mt-5">{t(`pinnedPosts`)}</p>
<div className={` ${styles.pinnedPostsCardsContainer}`}>
{pinnedPosts.map(({ node }: { node: InterfacePostNode }) => {
const cardProps = getCardProps(node);
return <PostCard key={node._id} {...cardProps} />;
})}
</div>
</div>
<Carousel responsive={responsive}>
{pinnedPosts.map(({ node }: { node: InterfacePostNode }) => {
const cardProps = getCardProps(node);
return <PostCard key={node._id} {...cardProps} />;
})}
</Carousel>
)}
</div>

{filteredAd.length > 0 && (
{adContent.length > 0 && (
<div data-testid="promotedPostsContainer">
{filteredAd.map((post: InterfaceAdContent) => (
{adContent.map((post: Ad) => (
<PromotedPost
key={post._id}
id={post._id}
Expand Down
Loading