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

feat(app): add ability to edit question on questions page and single question page for admin #502

Merged
merged 26 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
04ad078
feat(app): add ability to edit questions on questions list to admin
grzegorzpokorski Jan 13, 2023
cd8cdaf
feat(app): add ability to edit question on question page to admin
grzegorzpokorski Jan 13, 2023
4a995d4
fix(app): refetch questions after edit one of them in user panel
grzegorzpokorski Jan 13, 2023
cd56f09
fix(app): fix text align in "CtaHedaerActiveLink"
grzegorzpokorski Jan 13, 2023
64b8f10
Remove unused import
grzegorzpokorski Jan 13, 2023
2f61628
Merge branch 'develop' into 479-issue
grzegorzpokorski Jan 15, 2023
68c0cbb
chore: add prettier config file to worspace config
grzegorzpokorski Jan 20, 2023
080d2b4
fix: update questions list after edit any of them in user dashboard
grzegorzpokorski Jan 20, 2023
eebca85
fix: add loading indicator to questions list in dashboards
grzegorzpokorski Jan 20, 2023
7b1b878
fix: disable ssr for QuestionsManagement on questions pages
grzegorzpokorski Jan 20, 2023
686b623
fix: small improvements in "EditAnswer" and "AnswerForm"
grzegorzpokorski Jan 20, 2023
34f3b48
fix: remove unused import
grzegorzpokorski Jan 20, 2023
f3eb9fe
fix: refresh ssr generated page after edit question
grzegorzpokorski Jan 20, 2023
db0594d
fix: remove unused import
grzegorzpokorski Jan 20, 2023
9b13a5e
fix: fix vercel deployment
grzegorzpokorski Jan 20, 2023
e4dd509
Merge branch 'fix-user-questions-dashboard' into 479-issue
grzegorzpokorski Jan 20, 2023
536a05f
fix: rename function name "customOnClose" => "additionalActionOnClose"
grzegorzpokorski Jan 20, 2023
f747452
feat: change loading indicator component
grzegorzpokorski Jan 20, 2023
906eb57
fix: improve "Loading" component styles
grzegorzpokorski Jan 20, 2023
d4e5a74
fix: improve loader a11y
grzegorzpokorski Jan 20, 2023
a92f98b
fix: improve styles of "Loading" component
grzegorzpokorski Jan 20, 2023
32f3641
fix: improve light theme of loading component
grzegorzpokorski Jan 20, 2023
2155e50
Update apps/app/src/components/Loading.tsx
grzegorzpokorski Jan 21, 2023
c14f3fa
Merge branch 'develop' into 479-issue
grzegorzpokorski Jan 23, 2023
e87aebb
implement "additionalActionOnClose" function in dashboard modals
grzegorzpokorski Jan 23, 2023
2d109c5
improve loading component and implement this changes
grzegorzpokorski Jan 23, 2023
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
2 changes: 1 addition & 1 deletion apps/app/src/components/CtaHeader/CtaHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type CtaHeaderActiveLinkProps = Readonly<{
const CtaHeaderActiveLink = (props: CtaHeaderActiveLinkProps) => (
<ActiveLink
activeClassName="font-bold border-white"
className="flex h-12 grow items-center justify-center border-b-2 border-transparent px-7 transition-opacity hover:opacity-80"
className="flex h-12 grow items-center justify-center border-b-2 border-transparent px-7 text-center transition-opacity hover:opacity-80"
{...props}
/>
);
Expand Down
27 changes: 17 additions & 10 deletions apps/app/src/components/QuestionsList/QuestionsList.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
"use client";

import { useGetQuestionsVotes } from "../../hooks/useQuestionVoting";
import { Question, QuestionFilter } from "../../types";
import { AdminQuestion, QuestionFilter } from "../../types";
import { QuestionItem } from "../QuestionItem/QuestionItem";
import { QuestionLevel } from "../QuestionItem/QuestionLevel";
import { QuestionVoting } from "./QuestionVoting";
import { QuestionsManagement } from "./QuestionsManagment";

type QuestionsListProps = Readonly<{
questions: Question[];
questions: AdminQuestion[];
questionFilter: QuestionFilter;
}>;

Expand All @@ -20,8 +21,11 @@ export const QuestionsList = ({ questions, questionFilter }: QuestionsListProps)

return (
<ul className="space-y-10">
{questions.map(({ id, mdxContent, _levelId, _categoryId, acceptedAt }) => {
const questionVote = questionsVotes?.find((questionVote) => questionVote.id === id);
{questions.map((question) => {
const { id, mdxContent, _levelId, _categoryId, acceptedAt } = question;
const questionVote = questionsVotes?.find(
(questionVote) => questionVote.id === question.id,
);
const [votes, voted] = questionVote
? [questionVote.votesCount, questionVote.currentUserVotedOn]
: [0, false];
Expand All @@ -35,12 +39,15 @@ export const QuestionsList = ({ questions, questionFilter }: QuestionsListProps)
technology={_categoryId}
acceptedAt={acceptedAt}
leftSection={
<QuestionVoting
questionId={id}
votes={votes}
voted={voted}
onQuestionVote={onQuestionVote}
/>
<div className="flex flex-col gap-1.5">
<QuestionVoting
questionId={id}
votes={votes}
voted={voted}
onQuestionVote={onQuestionVote}
/>
<QuestionsManagement question={question} />
</div>
}
rightSection={<QuestionLevel level={_levelId} />}
/>
Expand Down
24 changes: 24 additions & 0 deletions apps/app/src/components/QuestionsList/QuestionsManagment.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Button } from "../Button/Button";
import { PrivateElement } from "../PrivateElement";
import PencilIcon from "../../../public/icons/pencil.svg";
import { AdminQuestion } from "../../types";
import { useUIContext } from "../../providers/UIProvider";

export const QuestionsManagement = ({ question }: { question: AdminQuestion }) => {
const { openModal } = useUIContext();

return (
<PrivateElement role="admin">
<div className="mr-3 flex flex-col justify-start gap-1.5">
<Button
variant="branding"
className="m-px flex w-24 min-w-0 items-center justify-center gap-2 p-0"
onClick={() => openModal("AddQuestionModal", question)}
>
<PencilIcon className="fill-violet-700 dark:fill-neutral-200" />
Edytuj
</Button>
</div>
</PrivateElement>
);
};
29 changes: 16 additions & 13 deletions apps/app/src/components/SingleQuestion.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
"use client";

import { Question } from "../types";
import { AdminQuestion, Question } from "../types";
grzegorzpokorski marked this conversation as resolved.
Show resolved Hide resolved
import { useGetQuestionVotesById } from "../hooks/useQuestionVoting";
import { QuestionItem } from "./QuestionItem/QuestionItem";
import { QuestionVoting } from "./QuestionsList/QuestionVoting";
import { QuestionTechnology } from "./QuestionItem/QuestionTechnology";
import { QuestionLevel } from "./QuestionItem/QuestionLevel";
import { QuestionsManagement } from "./QuestionsList/QuestionsManagment";

type SingleQuestionProps = Readonly<{
question: Question;
question: AdminQuestion;
}>;

export const SingleQuestion = ({
question: { id, mdxContent, _levelId, _categoryId, acceptedAt },
}: SingleQuestionProps) => {
export const SingleQuestion = ({ question }: SingleQuestionProps) => {
const { id, mdxContent, _levelId, _categoryId, acceptedAt } = question;
const { votes, voted, refetch } = useGetQuestionVotesById(id);

return (
Expand All @@ -24,14 +24,17 @@ export const SingleQuestion = ({
technology={_categoryId}
acceptedAt={acceptedAt}
leftSection={
<QuestionVoting
questionId={id}
votes={votes}
voted={voted}
onQuestionVote={() => {
void refetch();
}}
/>
<div className="flex flex-col gap-1.5">
<QuestionVoting
questionId={id}
votes={votes}
voted={voted}
onQuestionVote={() => {
void refetch();
}}
/>
<QuestionsManagement question={question} />
</div>
}
rightSection={
<div className="flex flex-col items-center">
Expand Down
15 changes: 13 additions & 2 deletions apps/app/src/components/UserQuestions/UserQuestionLeftSection.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import { useEffect } from "react";
import { useUIContext } from "../../providers/UIProvider";
import { AdminQuestion } from "../../types";
import PencilIcon from "../../../public/icons/pencil.svg";
import { Button } from "../Button/Button";

type UserQuestionLeftSectionProps = Readonly<{
question: AdminQuestion;
refetchQuestions: () => void;
}>;

export const UserQuestionLeftSection = ({ question }: UserQuestionLeftSectionProps) => {
const { openModal } = useUIContext();
export const UserQuestionLeftSection = ({
question,
refetchQuestions,
}: UserQuestionLeftSectionProps) => {
const { openModal, openedModal } = useUIContext();

useEffect(() => {
if (!openedModal) {
refetchQuestions();
grzegorzpokorski marked this conversation as resolved.
Show resolved Hide resolved
}
}, [openedModal, refetchQuestions]);

return (
<Button
Expand Down
10 changes: 7 additions & 3 deletions apps/app/src/components/UserQuestions/UserQuestions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { Suspense } from "react";
import { Suspense, useCallback } from "react";
import { useGetAllQuestions } from "../../hooks/useGetAllQuestions";
import { useUser } from "../../hooks/useUser";
import { Technology } from "../../lib/technologies";
Expand All @@ -16,13 +16,17 @@ type UserQuestionsProps = Readonly<{

export const UserQuestions = ({ page, technology, levels }: UserQuestionsProps) => {
const { userData } = useUser();
const { isSuccess, data } = useGetAllQuestions({
const { isSuccess, data, refetch } = useGetAllQuestions({
page,
technology,
levels,
userId: userData?._user.id,
});

const refetchQuestions = useCallback(() => {
void refetch();
}, [refetch]);

return (
<FilterableQuestionsList
page={page}
Expand All @@ -32,7 +36,7 @@ export const UserQuestions = ({ page, technology, levels }: UserQuestionsProps)
>
{isSuccess && data.data.data.length > 0 ? (
<Suspense>
<UserQuestionsList questions={data.data.data} />
<UserQuestionsList questions={data.data.data} refetchQuestions={refetchQuestions} />
</Suspense>
) : (
<p className="mt-10 text-2xl font-bold uppercase text-primary dark:text-neutral-200">
Expand Down
7 changes: 5 additions & 2 deletions apps/app/src/components/UserQuestions/UserQuestionsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ import { UserQuestionLeftSection } from "./UserQuestionLeftSection";

type UserQuestionsListProps = Readonly<{
questions: APIQuestion[];
refetchQuestions: () => void;
}>;

export const UserQuestionsList = memo(({ questions }: UserQuestionsListProps) => {
export const UserQuestionsList = memo(({ questions, refetchQuestions }: UserQuestionsListProps) => {
const serializedQuestions = questions.map((question) =>
use(
(async () => {
Expand All @@ -29,7 +30,9 @@ export const UserQuestionsList = memo(({ questions }: UserQuestionsListProps) =>
<QuestionItem
level={question._levelId}
technology={question._categoryId}
leftSection={<UserQuestionLeftSection question={question} />}
leftSection={
<UserQuestionLeftSection question={question} refetchQuestions={refetchQuestions} />
}
rightSection={
<div className="flex flex-col items-center">
<QuestionTechnology technology={question._categoryId} />
Expand Down
2 changes: 1 addition & 1 deletion apps/app/src/lib/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type QuestionStatus = typeof statuses[number];

export const serializeQuestionToMarkdown = async ({ question, ...rest }: APIQuestion) => {
const mdxContent = await serializeSource(question);
return { mdxContent, ...rest };
return { mdxContent, question, ...rest };
};

export const parseStatusQuery = (query: QueryParam | null): QuestionStatus | null => {
Expand Down