Skip to content

Commit

Permalink
Add comment sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
jonasdeluna committed Sep 10, 2024
1 parent bd7ca2d commit e00bf37
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 8 deletions.
16 changes: 16 additions & 0 deletions app/components/Comments/CommentView.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
.headerContainer {
margin-bottom: 0.25rem;
}

.sortIcon {
flex-direction: column;
}

.iconWrapper {
margin-left: 0.25rem;
}

.sortList {
margin-left: 0.5rem;
min-width: 10rem;
}
114 changes: 106 additions & 8 deletions app/components/Comments/CommentView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { Flex, LoadingIndicator } from '@webkom/lego-bricks';
import {
FilterSection,
Flex,
Icon,
LoadingIndicator,
} from '@webkom/lego-bricks';
import { ListFilter } from 'lucide-react';
import moment from 'moment';
import { useEffect, useState, type CSSProperties } from 'react';
import CommentForm from 'app/components/CommentForm';
import { generateTreeStructure } from 'app/utils';
import { SelectInput } from '../Form';
import CommentTree from './CommentTree';
import styles from './CommentView.css';
import type Comment from 'app/store/models/Comment';
import type { ContentAuthors } from 'app/store/models/Comment';
import type { ContentTarget } from 'app/store/utils/contentTarget';
import type { CSSProperties } from 'react';

type Props = {
comments: Comment[];
Expand All @@ -17,6 +26,37 @@ type Props = {
contentAuthors?: ContentAuthors;
};

const orderingOptions: Array<Option> = [
{
label: 'Nyeste',
value: 'createdAt',
},
{
label: 'Eldste',
value: 'createdAtInv',
},
{
label: 'Likes',
value: 'reactionsGrouped',
},
{
label: 'Kontroversielle',
value: 'reactionsControversial',
},
];

type Option = {
label: string;
value: string;
};

const getReactionScore = (comment: Comment, emojiString: string): number => {
const count =
comment.reactionsGrouped.find((reaction) => reaction.emoji === emojiString)
?.count || 0;
return count;
};

const Title = ({ displayTitle }: { displayTitle: boolean }) =>
displayTitle && <h3>Kommentarer</h3>;

Expand All @@ -27,23 +67,81 @@ const CommentView = (props: Props) => {
contentTarget,
style,
displayTitle = true,
newOnTop = false,
contentAuthors,
} = props;
const commentFormProps = {
contentTarget,
};
const tree = generateTreeStructure(comments);
const [ordering, setOrdering] = useState<Option>(orderingOptions[0]);
const [sortedComments, setSortedComments] = useState<Comment[]>(comments);
const [displaySorting, setDisplaySorting] = useState(false);
const tree = generateTreeStructure(sortedComments);

useEffect(() => {
const sorted = [...comments].sort((a: Comment, b: Comment) => {
if (ordering.value === 'createdAt') {
return moment(b.createdAt).valueOf() - moment(a.createdAt).valueOf();
} else if (ordering.value === 'createdAtInv') {
return moment(a.createdAt).valueOf() - moment(b.createdAt).valueOf();
} else if (ordering.value === 'reactionsGrouped') {
const scoreA =
getReactionScore(a, ':+1:') - getReactionScore(a, ':-1:');
const scoreB =
getReactionScore(b, ':+1:') - getReactionScore(b, ':-1:');
return scoreB - scoreA;
} else if (ordering.value === 'reactionsControversial') {
return getReactionScore(b, ':-1:') - getReactionScore(a, ':-1:');
}
return 0;
});

setSortedComments(sorted);
}, [ordering, comments]);

return (
<div style={style}>
<Title displayTitle={displayTitle} />
<Flex
flex-row
justifyContent="flex-start"
alignItems="center"
className={styles.headerContainer}
>
<Title displayTitle={displayTitle} />
<Flex flex-row alignItems="center" className={styles.iconWrapper}>
<Icon
name="arrow-down-wide-narrow"
size={20}
onClick={() => {
setDisplaySorting(!displaySorting);
}}
className={styles.sortIcon}
iconNode={<ListFilter />}
/>
{displaySorting && (
<div className={styles.sortList}>
<FilterSection title="">
<SelectInput
name="sorting_selector"
value={ordering}
onChange={(selectedOption: Option) => {
setOrdering(selectedOption);
}}
isClearable={false}
options={orderingOptions}
/>
</FilterSection>
</div>
)}
</Flex>
</Flex>

<Flex column gap="var(--spacing-sm)">
{!formDisabled && <CommentForm {...commentFormProps} />}

<LoadingIndicator loading={!comments}>
{comments && (
<LoadingIndicator loading={!sortedComments}>
{sortedComments && (
<CommentTree
comments={newOnTop ? tree.reverse() : tree}
comments={tree}
commentFormProps={commentFormProps}
contentTarget={contentTarget}
contentAuthors={contentAuthors}
Expand Down

0 comments on commit e00bf37

Please sign in to comment.