Skip to content

Commit

Permalink
[DEV-1517]: questions page reactiveness (#759)
Browse files Browse the repository at this point in the history
* feat(DEV-1517): more reactiveness on questions page

* chore: add changeset

* feat(DEV-1517): fix PR comments

* feat(DEV-1517): increase refresh interval

* fix(DEV-1517): fix PR comments

---------

Co-authored-by: Marco Ponchia <[email protected]>
  • Loading branch information
MikeAtUqido and MarcoPonchia committed Apr 5, 2024
1 parent 21f9eee commit f4a7ef8
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/afraid-pens-hunt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nextjs-website": patch
---

Update the local state of the webinar's questions page when an user highlight or hide a question to show the changes in real time.
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,18 @@ type WebinarQuestionsTableProps = {
userName: string;
questions: WebinarQuestion[];
title: string;
updateLocalQuestions: (
createdAt: Date,
highlight: boolean,
hidden: boolean
) => null;
};

const WebinarQuestionsTable = ({
userName,
questions,
title,
updateLocalQuestions,
}: WebinarQuestionsTableProps) => {
return (
<TableContainer component={Paper} sx={{ marginY: 2 }}>
Expand All @@ -36,26 +42,36 @@ const WebinarQuestionsTable = ({
key={question.id.createdAt.toISOString()}
question={question}
userName={userName}
onHide={async (hide) =>
onHide={async (hide) => {
updateLocalQuestions(
question.id.createdAt,
!!question.highlightedBy,
hide
);
await updateWebinarQuestion({
id: question.id,
updates: {
hiddenBy: hide
? { operation: 'update', value: userName }
: { operation: 'remove' },
},
})
}
onHighlight={async (highlight) =>
});
}}
onHighlight={async (highlight) => {
updateLocalQuestions(
question.id.createdAt,
highlight,
!!question.hiddenBy
);
await updateWebinarQuestion({
id: question.id,
updates: {
highlightedBy: highlight
? { operation: 'update', value: userName }
: { operation: 'remove' },
},
})
}
});
}}
/>
))}
</TableBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import SummaryInformation from '@/components/atoms/SummaryInformation/SummaryInf
import { Box, Grid } from '@mui/material';
import { Webinar } from '@/lib/types/webinar';
import { useWebinar } from '@/helpers/webinar.helpers';
import { useEffect } from 'react';
import { useEffect, useState } from 'react';
import { getWebinarQuestionList } from '@/lib/webinarApi';
import Spinner from '@/components/atoms/Spinner/Spinner';
import useSWR from 'swr';
Expand All @@ -12,6 +12,7 @@ import { fetchWebinarsQuestionsIntervalMs } from '@/config';
import { useUser } from '@/helpers/user.helper';
import WebinarQuestionsTable from '@/components/organisms/WebinarQuestionsTable/WebinarQuestionsTable';
import { useTranslations } from 'next-intl';
import { WebinarQuestion } from '@/lib/webinars/webinarQuestions';

type WebinarQuestionsTemplateProps = {
webinar: Webinar;
Expand All @@ -23,6 +24,7 @@ const WebinarQuestionsTemplate = ({
const { user, loading } = useUser();
const { webinarState, setWebinar } = useWebinar();
const t = useTranslations('webinar.questionList');
const [questions, setQuestions] = useState<readonly WebinarQuestion[]>([]);

const { data, error } = useSWR(webinar.slug, getWebinarQuestionList, {
refreshInterval: fetchWebinarsQuestionsIntervalMs,
Expand All @@ -32,20 +34,48 @@ const WebinarQuestionsTemplate = ({
webinar && setWebinar(webinar);
}, [webinar]);

useEffect(() => {
setQuestions(data ?? []);
}, [data]);

if (error || (!loading && !user)) return <PageNotFound />;
else if (!data || loading || !user) return <Spinner />;
else {
const userName = `${user.attributes['given_name']} ${user.attributes['family_name']}`;
const sortedVisibleQuestions = [...data]
const sortedVisibleQuestions = [...questions]
.sort((a, b) => b.id.createdAt.getTime() - a.id.createdAt.getTime())
.filter(({ hiddenBy }) => !hiddenBy || userName === hiddenBy);

const highlightedQuestions = sortedVisibleQuestions.filter(
(question) => !!question.highlightedBy
);

const notHighlightedQuestions = sortedVisibleQuestions.filter(
(question) => !question.highlightedBy
);

const updateLocalQuestionsByDate = (
createdAt: Date,
updateHighlight: boolean,
updateHide: boolean
) => {
setQuestions((oldQuestions) =>
oldQuestions.map((oldQuestion) => {
const userName = `${user.attributes['given_name']} ${user.attributes['family_name']}`;
return createdAt.toISOString() ===
oldQuestion.id.createdAt.toISOString()
? {
...oldQuestion,
hiddenBy: updateHide ? userName : undefined,
highlightedBy: updateHighlight ? userName : undefined,
}
: oldQuestion;
})
);

return null;
};

return (
<>
<SummaryInformation
Expand All @@ -67,13 +97,15 @@ const WebinarQuestionsTemplate = ({
>
<Grid key={'notHighlightedQuestions'} item xs={12} md={6}>
<WebinarQuestionsTable
updateLocalQuestions={updateLocalQuestionsByDate}
userName={userName}
questions={notHighlightedQuestions}
title={t('title.questions')}
/>
</Grid>
<Grid key={'highlightedQuestions'} item xs={12} md={6}>
<WebinarQuestionsTable
updateLocalQuestions={updateLocalQuestionsByDate}
userName={userName}
questions={highlightedQuestions}
title={t('title.highlightedQuestions')}
Expand Down
2 changes: 1 addition & 1 deletion apps/nextjs-website/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export const baseUrl = isProduction

export const defaultOgTagImage = `${baseUrl}/images/dev-portal-home.jpg`;
export const resetResendEmailAfterMs = 4_000;
export const fetchWebinarsQuestionsIntervalMs = 250;
export const fetchWebinarsQuestionsIntervalMs = 1_000;

export const defaultLanguage = { id: 'it', value: 'Italiano' };
export const languages = [defaultLanguage];
Expand Down

0 comments on commit f4a7ef8

Please sign in to comment.