All files / app/features/communities/discussions DiscussionsListPage.tsx

96.77% Statements 30/31
85.71% Branches 12/14
87.5% Functions 7/8
96.66% Lines 29/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 1146x 6x 6x 6x 6x 6x       6x 6x 6x 6x   6x 6x   6x 6x 6x   6x                     6x         17x 17x         17x 17x                   17x     17x   17x                           3x                   1x 1x               11x   23x                                      
import { Collapse, makeStyles } from "@material-ui/core";
import Alert from "components/Alert";
import Button from "components/Button";
import CircularProgress from "components/CircularProgress";
import { EmailIcon } from "components/Icons";
import TextBody from "components/TextBody";
import {
  SectionTitle,
  useCommunityPageStyles,
} from "features/communities/CommunityPage";
import { useListDiscussions } from "features/communities/hooks";
import { useTranslation } from "i18n";
import { COMMUNITIES } from "i18n/namespaces";
import { Community } from "proto/communities_pb";
import { useState } from "react";
import hasAtLeastOnePage from "utils/hasAtLeastOnePage";
 
import CreateDiscussionForm from "./CreateDiscussionForm";
import DiscussionCard from "./DiscussionCard";
import useDiscussionsListStyles from "./useDiscussionsListStyles";
 
const useStyles = makeStyles((theme) => ({
  newPostButtonContainer: {
    "& > * + *": {
      marginInlineStart: theme.spacing(2),
    },
    display: "flex",
    alignItems: "center",
    minHeight: theme.typography.pxToRem(40),
  },
}));
 
export default function DiscussionsListPage({
  community,
}: {
  community: Community.AsObject;
}) {
  const { t } = useTranslation([COMMUNITIES]);
  const classes = {
    ...useCommunityPageStyles(),
    ...useDiscussionsListStyles(),
    ...useStyles(),
  };
  const hash = typeof window !== "undefined" ? window.location.hash : "";
  const [isCreatingNewPost, setIsCreatingNewPost] = useState(
    hash.includes("new")
  );
  const {
    isLoading: isDiscussionsLoading,
    isFetching: isDiscussionsFetching,
    error: discussionsError,
    data: discussions,
    hasNextPage: discussionsHasNextPage,
    fetchNextPage,
  } = useListDiscussions(community.communityId);
 
  // loading is false when refetched since there's old data in cache already
  const isRefetching = !isDiscussionsLoading && isDiscussionsFetching;
 
  return (
    <>
      <div className={classes.discussionsHeader}>
        <SectionTitle icon={<EmailIcon />}>
          {t("communities:discussions_title")}
        </SectionTitle>
      </div>
      {discussionsError && (
        <Alert severity="error">{discussionsError.message}</Alert>
      )}
      <Collapse in={!isCreatingNewPost}>
        <div className={classes.newPostButtonContainer}>
          <Button
            className={classes.createResourceButton}
            onClick={() => setIsCreatingNewPost(true)}
          >
            {t("communities:new_post_label")}
          </Button>
          {isRefetching && <CircularProgress />}
        </div>
      </Collapse>
      <Collapse in={isCreatingNewPost}>
        <CreateDiscussionForm
          communityId={community.communityId}
          onCancel={() => setIsCreatingNewPost(false)}
          onPostSuccess={() => setIsCreatingNewPost(false)}
        />
      </Collapse>
      <div className={classes.discussionsContainer}>
        {isDiscussionsLoading ? (
          <CircularProgress />
        ) : hasAtLeastOnePage(discussions, "discussionsList") ? (
          discussions.pages
            .flatMap((res) => res.discussionsList)
            .map((discussion) => (
              <DiscussionCard
                discussion={discussion}
                key={`discussioncard-${discussion.thread!.threadId}`}
              />
            ))
        ) : (
          <TextBody>{t("communities:discussions_empty_state")}</TextBody>
        )}
        {discussionsHasNextPage && (
          <div className={classes.loadMoreButton}>
            <Button onClick={() => fetchNextPage()}>
              {t("communities:see_more_discussions_label")}
            </Button>
          </div>
        )}
      </div>
    </>
  );
}