From c84979713eb8cd7e5803dbe06ee40ef729b39d19 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Mon, 2 Sep 2024 19:47:59 +0300 Subject: [PATCH 01/16] classpuzle --- .../getMultiStageStatements.ts | 44 ++ src/model/statements/statementsSlice.ts | 16 +- .../solutions/StatementSolutionsPage.tsx | 610 +++++++++--------- .../solutions/statementSolutionsHooks.ts | 65 ++ 4 files changed, 437 insertions(+), 298 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/statementSolutionsHooks.ts diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 34bceeafa..c18798083 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -55,4 +55,48 @@ export async function getMultiStageOptions( console.error(error); dispatch(setTempStatementsForPresentation([])); } +} + +export async function getFirstEvaluationOptions( + statement: Statement, + +): Promise { + const dispatch: Dispatch = store.dispatch; + try { + const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; + + const url = isProduction() ? `https://getRandomStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getRandomStatements"; + + const response = await fetch( + `${url}?parentId=${statement.statementId}&limit=6` + ); + const { randomStatements, error } = await response.json(); + if (error) throw new Error(error); + dispatch(setTempStatementsForPresentation(randomStatements)); + return randomStatements as Statement[]; + } catch (error) { + console.error(error); + dispatch(setTempStatementsForPresentation([])); + return []; + } +} + +export async function getSecondEvaluationOptions(statement: Statement): Promise { + const dispatch: Dispatch = store.dispatch; + try { + const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; + + const url = isProduction() ? `https://getTopStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getTopStatements"; + const response = await fetch( + `${url}?parentId=${statement.statementId}&limit=10` + ); + const { topSolutions, error } = await response.json(); + if (error) throw new Error(error); + dispatch(setTempStatementsForPresentation(topSolutions)); + return topSolutions as Statement[]; + } catch (error) { + console.error(error); + dispatch(setTempStatementsForPresentation([])); + return []; + } } \ No newline at end of file diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index dd5889884..bf3315336 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -1,6 +1,6 @@ /* eslint-disable indent */ import { createSlice, PayloadAction, createSelector } from "@reduxjs/toolkit"; -import { RootState } from "../store"; +import { RootState, store } from "../store"; // Third party imports @@ -241,7 +241,7 @@ export const statementsSlicer = createSlice({ action: PayloadAction<{ statement: Statement; screen: Screen }>, ) => { try { - + const { statement, screen } = action.payload; const _statement = state.statements.find( (st) => st.statementId === statement.statementId, @@ -434,7 +434,7 @@ export const hasTokenSelector = return statement?.token?.includes(token) || false; }; - + export const subscriptionParentStatementSelector = (parentId: string) => createSelector( (state: RootState) => state.statements.statementSubscription, @@ -442,4 +442,14 @@ export const subscriptionParentStatementSelector = (parentId: string) => statementSubscription.filter((sub) => sub.statement.topParentId === parentId) ); + +export const myStatementsByStatementIdSelector = (statementId: string) =>{ + const user = store.getState().user.user; + return createSelector( + (state: RootState) => state.statements.statements, + (statements) => + statements.filter((st) => st.parentId === statementId && st.creatorId === user?.uid) + ); +} + export default statementsSlicer.reducer; diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 3877e00ec..77c282705 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -1,18 +1,18 @@ -import { FC, useEffect, useState } from 'react'; +import { FC, useEffect, useState } from "react"; // Third party imports import { - QuestionStage, - QuestionType, - Statement, - StatementType, - User, - isOptionFn, -} from 'delib-npm'; -import { useParams, useNavigate } from 'react-router'; + QuestionStage, + QuestionType, + Statement, + StatementType, + User, + isOptionFn, +} from "delib-npm"; +import { useParams, useNavigate } from "react-router"; // Utils & Helpers -import { sortSubStatements } from './statementSolutionsCont'; +import { sortSubStatements } from "./statementSolutionsCont"; // Custom Components import StatementEvaluationCard from "./components/StatementSolutionCard"; @@ -32,311 +32,331 @@ import styles from "./statementSolutinsPage.module.scss"; import ideaImage from "@/assets/images/manWithIdeaLamp.png"; import WhitePlusIcon from "@/view/components/icons/WhitePlusIcon"; import useWindowDimensions from "@/controllers/hooks/useWindowDimentions"; - +import { useMultiStage } from "./statementSolutionsHooks"; +import { set } from "node_modules/cypress/types/lodash"; interface StatementEvaluationPageProps { - statement: Statement; - subStatements: Statement[]; - handleShowTalker: (talker: User | null) => void; - showNav?: boolean; - questions?: boolean; - toggleAskNotifications: () => void; - currentPage?: string; + statement: Statement; + subStatements: Statement[]; + handleShowTalker: (talker: User | null) => void; + showNav?: boolean; + questions?: boolean; + toggleAskNotifications: () => void; + currentPage?: string; } const StatementEvaluationPage: FC = ({ - statement, - subStatements, - handleShowTalker, - questions = false, - toggleAskNotifications, - currentPage = `suggestion`, + statement, + subStatements, + handleShowTalker, + questions = false, + toggleAskNotifications, + currentPage = `suggestion`, }) => { - try { - // Hooks - const { sort } = useParams(); - const navigate = useNavigate(); - const { t } = useLanguage(); - const isMuliStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const currentStage = statement.questionSettings?.currentStage; - const stageInfo = getStagesInfo(currentStage); - const useSearchForSimilarStatements = - statement.statementSettings?.enableSimilaritiesSearch || false; + try { + // Hooks + const { sort } = useParams(); + const navigate = useNavigate(); + const { t } = useLanguage(); + const isMuliStage = + statement.questionSettings?.questionType === QuestionType.multipleSteps; + const currentStage = statement.questionSettings?.currentStage; + const stageInfo = getStagesInfo(currentStage); + const useSearchForSimilarStatements = + statement.statementSettings?.enableSimilaritiesSearch || false; + + //hooks + const { subStatements: multiStageOptions, isLoading } = useMultiStage({ + statement, + }); + + // Use States + const [showModal, setShowModal] = useState(false); + const [showToast, setShowToast] = useState(false); + const [showExplanation, setShowExplanation] = useState( + currentStage === QuestionStage.explanation && isMuliStage && !questions + ); + const [sortedSubStatements, setSortedSubStatements] = useState( + [...subStatements] + ); - // Use States - const [showModal, setShowModal] = useState(false); - const [showToast, setShowToast] = useState(false); - const [showExplanation, setShowExplanation] = useState( - currentStage === QuestionStage.explanation && isMuliStage && !questions); - const [sortedSubStatements, setSortedSubStatements] = useState( - [...subStatements] - ); + useEffect(() => { + if (isMuliStage) { + setSortedSubStatements(multiStageOptions); + } else { + const _sortedSubStatements = sortSubStatements( + subStatements, + sort + ).filter((subStatement) => { + //if questions is true, only show questions + if (questions) { + return subStatement.statementType === StatementType.question; + } - useEffect(() => { - const _sortedSubStatements = sortSubStatements( - subStatements, - sort - ).filter((subStatement) => { - //if questions is true, only show questions - if (questions) { - return subStatement.statementType === StatementType.question; - } + if (isMuliStage) { + //filter the temp presentation designed for this stage + return subStatement.isPartOfTempPresentation; + } - if (isMuliStage) { - //filter the temp presentation designed for this stage - return subStatement.isPartOfTempPresentation; - } + //if options is true, only show options + return isOptionFn(subStatement); + }); - //if options is true, only show options - return isOptionFn(subStatement); - }); + setSortedSubStatements(_sortedSubStatements); + } + }, [sort, subStatements, questions, isMuliStage, multiStageOptions]); - setSortedSubStatements(_sortedSubStatements); - }, [sort, subStatements, questions]); + useEffect(() => { + if (questions) { + setShowToast(false); + } + }, [questions]); - useEffect(() => { - if (questions) { - setShowToast(false); - } - }, [questions]); + useEffect(() => { + if (!showToast && !questions) { + setShowToast(true); + } + if ( + currentStage === QuestionStage.explanation && + isMuliStage && + !questions + ) { + setShowExplanation(true); + } + if (currentStage === QuestionStage.voting && !questions) { + //redirect us react router dom to voting page + navigate(`/statement/${statement.statementId}/vote`); + } + }, [statement.questionSettings?.currentStage, questions]); - useEffect(() => { - if (isMuliStage) { - getMultiStageOptions(statement); - } - }, [currentStage]); + // Variables + let topSum = 30; + const tops: number[] = [topSum]; + const message = stageInfo ? stageInfo.message : false; - useEffect(() => { - if (!showToast && !questions) { - setShowToast(true); - } - if ( - currentStage === QuestionStage.explanation && - isMuliStage && - !questions - ) { - setShowExplanation(true); - } - if (currentStage === QuestionStage.voting && !questions) { - //redirect us react router dom to voting page - navigate(`/statement/${statement.statementId}/vote`); - } - }, [statement.questionSettings?.currentStage, questions]); + const handlePlusIconClick = () => { + setShowModal(true); + }; - // Variables - let topSum = 30; - const tops: number[] = [topSum]; - const message = stageInfo ? stageInfo.message : false; + const { width } = useWindowDimensions(); + const smallScreen = width < 1024; - const handlePlusIconClick = () => { - setShowModal(true); - }; + const renderCommonContent = () => ( + <> +
+
+
+

+ {isLoading &&

Loading...

} + {smallScreen ? ( + <> + {t(`Click on`)}{" "} + {t(`”+”`)}{" "} + {t(`to add your ${currentPage}`)} + + ) : ( + <> +

+ {`Click on `} + + {`” ${t(`Add ${currentPage} button`)} ”`} + +
+ {` to add your ${t(`${currentPage}`)}`} +

+ + )} + +
+
+ {smallScreen ? ( + + ) : ( +

+ {" "} + {t(`Add ${currentPage}`)} {" "} +

+ )} +
+
+ +
+ {isMuliStage && stageInfo?.message && ( + + {getToastButtons(currentStage)} + + )} + {showExplanation && ( + + + + )} + {showModal && ( + + )} + + ); - const { width } = useWindowDimensions(); - const smallScreen = width < 1024; + if (sortedSubStatements.length === 0) { + return renderCommonContent(); + } - const renderCommonContent = () => ( - <> -
-
-
-

- {smallScreen ? ( - <> - {t(`Click on`)} {t(`”+”`)} {t(`to add your ${currentPage}`)} - - ) : ( - <> -

- {`Click on `} - - {`” ${t(`Add ${currentPage} button`)} ”`} -
- {` to add your ${t(`${currentPage}`)}`} -

- - )} - -
-
- {smallScreen ? ( - ) : (

{t(`Add ${currentPage}`)}

- )} -
-
- -
- {isMuliStage && stageInfo?.message && ( - - {getToastButtons(currentStage)} - - )} - {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); + return ( + <> +
+
+ {isMuliStage && message && ( + + {getToastButtons(currentStage)} + + )} + {sortedSubStatements?.map((statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } - if (sortedSubStatements.length === 0) { - return renderCommonContent(); - } - - return ( - <> -
-
- {isMuliStage && message && ( - - {getToastButtons(currentStage)} - - )} - {sortedSubStatements?.map((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); + return ( + + ); + })} +
+
+
+
+ +
+ {showExplanation && ( + + + + )} + {showModal && ( + + )} + + ); + function getToastButtons(questionStage: QuestionStage | undefined) { + try { + switch (questionStage) { + case QuestionStage.voting: + case QuestionStage.firstEvaluation: + case QuestionStage.secondEvaluation: + case QuestionStage.finished: + case QuestionStage.explanation: + return ( +
-
-
- -
- {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); - function getToastButtons(questionStage: QuestionStage | undefined) { - try { - switch (questionStage) { - case QuestionStage.voting: - case QuestionStage.firstEvaluation: - case QuestionStage.secondEvaluation: - case QuestionStage.finished: - case QuestionStage.explanation: - return ( -
- {navItems.map((navItem) => ( -
+ {navItems.map((navItem, i) => ( +
void; currentPage?: string; } - +let counter = 0; const StatementEvaluationPage: FC = ({ statement, subStatements, @@ -58,53 +55,39 @@ const StatementEvaluationPage: FC = ({ const { sort } = useParams(); const navigate = useNavigate(); const { t } = useLanguage(); - const isMuliStage = + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const currentStage = statement.questionSettings?.currentStage; + + const myStatements = useSelector(myStatementsByStatementIdSelector(statement.statementId)); + + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = statement.statementSettings?.enableSimilaritiesSearch || false; - //hooks - const { subStatements: multiStageOptions, isLoading } = useMultiStage({ - statement, - }); // Use States const [showModal, setShowModal] = useState(false); const [showToast, setShowToast] = useState(false); const [showExplanation, setShowExplanation] = useState( - currentStage === QuestionStage.explanation && isMuliStage && !questions + currentStage === QuestionStage.explanation && isMultiStage && !questions ); const [sortedSubStatements, setSortedSubStatements] = useState( [...subStatements] ); useEffect(() => { - if (isMuliStage) { - setSortedSubStatements(multiStageOptions); - } else { - const _sortedSubStatements = sortSubStatements( - subStatements, - sort - ).filter((subStatement) => { - //if questions is true, only show questions - if (questions) { - return subStatement.statementType === StatementType.question; - } - - if (isMuliStage) { - //filter the temp presentation designed for this stage - return subStatement.isPartOfTempPresentation; - } - - //if options is true, only show options - return isOptionFn(subStatement); - }); - - setSortedSubStatements(_sortedSubStatements); - } - }, [sort, subStatements, questions, isMuliStage, multiStageOptions]); + + getSubStatements({ + statement, + subStatements, + sort, + questions, + myStatements, + setSortedSubStatements, + }); + + }, [sort, subStatements, questions, isMultiStage]); useEffect(() => { if (questions) { @@ -118,7 +101,7 @@ const StatementEvaluationPage: FC = ({ } if ( currentStage === QuestionStage.explanation && - isMuliStage && + isMultiStage && !questions ) { setShowExplanation(true); @@ -134,100 +117,20 @@ const StatementEvaluationPage: FC = ({ const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - const handlePlusIconClick = () => { - setShowModal(true); - }; + - const { width } = useWindowDimensions(); - const smallScreen = width < 1024; - - const renderCommonContent = () => ( - <> -
-
-
-

- {isLoading &&

Loading...

} - {smallScreen ? ( - <> - {t(`Click on`)}{" "} - {t(`”+”`)}{" "} - {t(`to add your ${currentPage}`)} - - ) : ( - <> -

- {`Click on `} - - {`” ${t(`Add ${currentPage} button`)} ”`} - -
- {` to add your ${t(`${currentPage}`)}`} -

- - )} - -
-
- {smallScreen ? ( - - ) : ( -

- {" "} - {t(`Add ${currentPage}`)} {" "} -

- )} -
-
- -
- {isMuliStage && stageInfo?.message && ( - - {getToastButtons(currentStage)} - - )} - {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); + + if (sortedSubStatements.length === 0) { - return renderCommonContent(); + return } return ( <>
- {isMuliStage && message && ( + {isMultiStage && message && ( = ({ toggleAskNotifications={toggleAskNotifications} parentStatement={statement} isQuestion={questions} - isMuliStage={isMuliStage} + isMultiStage={isMultiStage} setShowModal={setShowModal} useSimilarStatements={useSearchForSimilarStatements} /> )} ); + + function getToastButtons(questionStage: QuestionStage | undefined) { try { switch (questionStage) { diff --git a/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx new file mode 100644 index 000000000..f75101f27 --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx @@ -0,0 +1,104 @@ +import { Dispatch, FC } from "react"; +import styles from "../../StatementSolutionsPage.module.scss"; +import useWindowDimensions from "@/controllers/hooks/useWindowDimentions"; + +// /graphics +import ideaImage from "@/assets/images/manWithIdeaLamp.png"; +import WhitePlusIcon from "@/view/components/icons/WhitePlusIcon"; +import { useLanguage } from "@/controllers/hooks/useLanguages"; +import { StageInfo } from "../../../settings/components/QuestionSettings/QuestionStageRadioBtn/QuestionStageRadioBtn"; + +interface Props { + currentPage: string; + stageInfo: StageInfo | undefined; + setShowModal: Dispatch; +} + +const EmptyScreen: FC = ({ currentPage, stageInfo,setShowModal }) => { + const {t} = useLanguage(); + const { width } = useWindowDimensions(); + const smallScreen = width < 1024; + + const handlePlusIconClick = () => { + setShowModal(true); + }; + + return ( + <> +
+
+
+

+ {smallScreen ? ( + <> + {t(`Click on`)}{" "} + {t(`”+”`)}{" "} + {t(`to add your ${currentPage}`)} + + ) : ( + <> +

+ {`Click on `} + + {`” ${t(`Add ${currentPage} button`)} ”`} + +
+ {` to add your ${t(`${currentPage}`)}`} +

+ + )} + +
+
+ {smallScreen ? ( + + ) : ( +

+ {" "} + {t(`Add ${currentPage}`)} {" "} +

+ )} +
+
+ +
+ {isMultiStage && stageInfo?.message && ( + + {getToastButtons(currentStage)} + + )} + {showExplanation && ( + + + + )} + {showModal && ( + + )} + + ); +}; + +export default EmptyScreen; diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 6777764e2..4c120a9ec 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -1,9 +1,10 @@ -import { Statement, Screen } from "delib-npm"; +import { Statement, Screen, isOptionFn, QuestionType, StatementType, QuestionStage } from "delib-npm"; import { EnhancedEvaluationThumb, enhancedEvaluationsThumbs, } from "./components/evaluation/enhancedEvaluation/EnhancedEvaluationModel"; +import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; @@ -12,32 +13,30 @@ export function sortSubStatements( sort: string | undefined, ): Statement[] { try { - let _subStatements = subStatements.map( - (statement: Statement) => statement, - ); + let _subStatements = [...subStatements]; switch (sort) { - case Screen.OPTIONS_CONSENSUS: - case Screen.QUESTIONS_CONSENSUS: - _subStatements = subStatements.sort( - (a: Statement, b: Statement) => b.consensus - a.consensus, - ); - break; - case Screen.OPTIONS_NEW: - case Screen.QUESTIONS_NEW: - _subStatements = subStatements.sort( - (a: Statement, b: Statement) => b.createdAt - a.createdAt, - ); - break; - case Screen.OPTIONS_RANDOM: - case Screen.QUESTIONS_RANDOM: - _subStatements = subStatements.sort(() => Math.random() - 0.5); - break; - case Screen.OPTIONS_UPDATED: - case Screen.QUESTIONS_UPDATED: - _subStatements = subStatements.sort( - (a: Statement, b: Statement) => b.lastUpdate - a.lastUpdate, - ); - break; + case Screen.OPTIONS_CONSENSUS: + case Screen.QUESTIONS_CONSENSUS: + _subStatements = subStatements.sort( + (a: Statement, b: Statement) => b.consensus - a.consensus, + ); + break; + case Screen.OPTIONS_NEW: + case Screen.QUESTIONS_NEW: + _subStatements = subStatements.sort( + (a: Statement, b: Statement) => b.createdAt - a.createdAt, + ); + break; + case Screen.OPTIONS_RANDOM: + case Screen.QUESTIONS_RANDOM: + _subStatements = subStatements.sort(() => Math.random() - 0.5); + break; + case Screen.OPTIONS_UPDATED: + case Screen.QUESTIONS_UPDATED: + _subStatements = subStatements.sort( + (a: Statement, b: Statement) => b.lastUpdate - a.lastUpdate, + ); + break; } const __subStatements = _subStatements.map( (statement: Statement, i: number) => { @@ -106,4 +105,78 @@ export const getEvaluationThumbsToDisplay = ({ ); return [selectedThumb || defaultThumb]; -}; \ No newline at end of file +}; + +interface GetSubStatementsProps { + statement: Statement; + subStatements: Statement[]; + sort: string | undefined; + questions: boolean; + myStatements: Statement[]; + setSortedSubStatements: React.Dispatch; +} +export async function getSubStatements({ statement, subStatements, sort, questions, myStatements, setSortedSubStatements }: GetSubStatementsProps): Promise { + try { + console.log("getSubStatements") + if (!statement) return; + if (!subStatements) return; + const _subStatements = [...subStatements]; + + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; + + if (!isMultiStage) { + const st = getSortedStatements(_subStatements, sort, questions); + console.log("single stage"); + setSortedSubStatements(st); + } else { + console.log("multi steps") + switch (statement.questionSettings?.currentStage) { + case QuestionStage.explanation: + setSortedSubStatements([]); + return; + case QuestionStage.suggestion: + setSortedSubStatements(myStatements); + return; + case QuestionStage.firstEvaluation: + getFirstEvaluationOptions(statement).then((subStatements) => { + // const st = getSortedStatements(subStatements, sort, questions); + setSortedSubStatements(subStatements); + }) + + return; + case QuestionStage.secondEvaluation: + getSecondEvaluationOptions(statement).then((subStatements) => { + const st = getSortedStatements(subStatements, sort, questions); + setSortedSubStatements(st); + }) + return; + case QuestionStage.voting: + setSortedSubStatements([]); + return; + default: + console.log("default ") + setSortedSubStatements([]); + return; + } + } + return; + + } catch (error) { + console.error(error); + + } +} + +function getSortedStatements(_subStatements:Statement[], sort: string | undefined, questions: boolean) { + return sortSubStatements( + _subStatements, + sort + ).filter((subStatement) => { + //if questions is true, only show questions + if (questions) { + return subStatement.statementType === StatementType.question; + } + //if options is true, only show options + return isOptionFn(subStatement); + }); +} diff --git a/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts b/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts index 5b50e8869..941ad3c74 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsHooks.ts @@ -3,6 +3,7 @@ import { Statement, QuestionStage, QuestionType } from "delib-npm"; import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; +import { set } from "node_modules/cypress/types/lodash"; interface Props { @@ -16,6 +17,7 @@ export function useMultiStage({ statement }: Props): Output { try { const [isLoading, setIsLoading] = useState(false); const [subStatements, setSubStatements] = useState([]); + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; const questionStage = statement.questionSettings?.currentStage || QuestionStage.finished; const questionType = statement.questionSettings?.questionType; @@ -25,36 +27,7 @@ export function useMultiStage({ statement }: Props): Output { const myStatements = useSelector(myStatementsByStatementIdSelector(statement.statementId)); - useEffect(() => { - setIsLoading(true); - switch (questionStage) { - case QuestionStage.explanation: - setSubStatements([]); - setIsLoading(false); - break; - case QuestionStage.suggestion: - setSubStatements(myStatements); - break; - case QuestionStage.firstEvaluation: - getFirstEvaluationOptions(statement).then((statements) => { - setSubStatements(statements); - setIsLoading(false); - }); - break; - case QuestionStage.secondEvaluation: - getSecondEvaluationOptions(statement).then((statements) => { - setSubStatements(statements); - setIsLoading(false); - }); - break; - case QuestionStage.voting: - //do something - break; - default: - //do something - break; - } - }, [questionStage]); + // useEffect(, [questionStage]); return { subStatements, isLoading }; } catch (error) { From 9e50b14cb30a4889322ee1c8f39196edda46d7ea Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Tue, 3 Sep 2024 09:23:25 +0300 Subject: [PATCH 03/16] refactor --- .../getMultiStageStatements.ts | 6 - .../solutions/StatementSolutionsPage.tsx | 118 +++++++++--------- .../components/emptyScreen/EmptyScreen.tsx | 34 +---- 3 files changed, 60 insertions(+), 98 deletions(-) diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index fc889db2c..9bfb39ece 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -73,9 +73,6 @@ export async function getFirstEvaluationOptions( const { randomStatements, error } = await response.json(); if (error) throw new Error(error); - randomStatements.forEach((s: Statement, i) => { - s.order = i - }) return randomStatements as Statement[]; } catch (error) { @@ -97,9 +94,6 @@ export async function getSecondEvaluationOptions(statement: Statement): Promise< const { topSolutions, error } = await response.json(); if (error) throw new Error(error); - topSolutions.forEach((s: Statement, i) => { - s.order = i - }) return topSolutions as Statement[]; } catch (error) { diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 95cdd6090..ba8e7f603 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -1,12 +1,7 @@ import { FC, useEffect, useState } from "react"; // Third party imports -import { - QuestionStage, - QuestionType, - Statement, - User -} from "delib-npm"; +import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { useParams, useNavigate } from "react-router"; // Utils & Helpers @@ -31,7 +26,6 @@ import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; - interface StatementEvaluationPageProps { statement: Statement; subStatements: Statement[]; @@ -57,15 +51,16 @@ const StatementEvaluationPage: FC = ({ const { t } = useLanguage(); const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - - const myStatements = useSelector(myStatementsByStatementIdSelector(statement.statementId)); - - const currentStage = statement.questionSettings?.currentStage; + + const myStatements = useSelector( + myStatementsByStatementIdSelector(statement.statementId) + ); + + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = statement.statementSettings?.enableSimilaritiesSearch || false; - // Use States const [showModal, setShowModal] = useState(false); const [showToast, setShowToast] = useState(false); @@ -77,16 +72,14 @@ const StatementEvaluationPage: FC = ({ ); useEffect(() => { - - getSubStatements({ - statement, - subStatements, - sort, - questions, - myStatements, - setSortedSubStatements, - }); - + getSubStatements({ + statement, + subStatements, + sort, + questions, + myStatements, + setSortedSubStatements, + }); }, [sort, subStatements, questions, isMultiStage]); useEffect(() => { @@ -117,51 +110,55 @@ const StatementEvaluationPage: FC = ({ const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - - - - - if (sortedSubStatements.length === 0) { - return + return; } return ( <>
-
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - {sortedSubStatements?.map((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } + {sortedSubStatements.length === 0 ? ( + + ) : ( +
+ {isMultiStage && message && ( + + {getToastButtons(currentStage)} + + )} + {sortedSubStatements?.map( + (statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } - return ( - - ); - })} -
-
+ return ( + + ); + } + )} +
+
+ )}
= ({ ); - function getToastButtons(questionStage: QuestionStage | undefined) { try { switch (questionStage) { diff --git a/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx index f75101f27..ab95ee8d6 100644 --- a/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx +++ b/src/view/pages/statement/components/solutions/components/emptyScreen/EmptyScreen.tsx @@ -6,15 +6,14 @@ import useWindowDimensions from "@/controllers/hooks/useWindowDimentions"; import ideaImage from "@/assets/images/manWithIdeaLamp.png"; import WhitePlusIcon from "@/view/components/icons/WhitePlusIcon"; import { useLanguage } from "@/controllers/hooks/useLanguages"; -import { StageInfo } from "../../../settings/components/QuestionSettings/QuestionStageRadioBtn/QuestionStageRadioBtn"; + interface Props { currentPage: string; - stageInfo: StageInfo | undefined; setShowModal: Dispatch; } -const EmptyScreen: FC = ({ currentPage, stageInfo,setShowModal }) => { +const EmptyScreen: FC = ({ currentPage, setShowModal }) => { const {t} = useLanguage(); const { width } = useWindowDimensions(); const smallScreen = width < 1024; @@ -69,34 +68,7 @@ const EmptyScreen: FC = ({ currentPage, stageInfo,setShowModal }) => {
- {isMultiStage && stageInfo?.message && ( - - {getToastButtons(currentStage)} - - )} - {showExplanation && ( - - - - )} - {showModal && ( - - )} + ); }; From 27e317f1835e60d21f7a2f8af6dfc1ddb24fcdd3 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Tue, 3 Sep 2024 10:30:11 +0300 Subject: [PATCH 04/16] before change of architecture --- .../solutions/StatementSolutionsPage.tsx | 6 ++---- .../solutions/statementSolutionsCont.ts | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index ba8e7f603..97c833795 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -35,7 +35,7 @@ interface StatementEvaluationPageProps { toggleAskNotifications: () => void; currentPage?: string; } -let counter = 0; + const StatementEvaluationPage: FC = ({ statement, subStatements, @@ -110,9 +110,7 @@ const StatementEvaluationPage: FC = ({ const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - if (sortedSubStatements.length === 0) { - return; - } + console.log(sortedSubStatements.map((subStatement:Statement) => subStatement.statement).join(',')); return ( <> diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 4c120a9ec..5a8f24673 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -138,17 +138,23 @@ export async function getSubStatements({ statement, subStatements, sort, questio setSortedSubStatements(myStatements); return; case QuestionStage.firstEvaluation: - getFirstEvaluationOptions(statement).then((subStatements) => { - // const st = getSortedStatements(subStatements, sort, questions); - setSortedSubStatements(subStatements); - }) + try { + const subStatements = await getFirstEvaluationOptions(statement); + const st = getSortedStatements(subStatements, sort, questions); + setSortedSubStatements(st); + } catch (error) { + console.error(error); + } return; case QuestionStage.secondEvaluation: - getSecondEvaluationOptions(statement).then((subStatements) => { + try { + const subStatements = await getSecondEvaluationOptions(statement); const st = getSortedStatements(subStatements, sort, questions); setSortedSubStatements(st); - }) + } catch (error) { + console.error(error); + } return; case QuestionStage.voting: setSortedSubStatements([]); From 383b2165f4804a13932058b912a2eeefab777a46 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Tue, 3 Sep 2024 13:14:30 +0300 Subject: [PATCH 05/16] before refactorting --- .../solutions/StatementSolutionsPage.tsx | 11 ++-- .../suggestionCards/SuggestionCards.tsx | 9 +++ .../solutions/statementSolutionsCont.ts | 56 ++++++------------- 3 files changed, 33 insertions(+), 43 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 97c833795..4ad68e497 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -67,9 +67,7 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - const [sortedSubStatements, setSortedSubStatements] = useState( - [...subStatements] - ); + const [sortedSubStatements, setSortedSubStatements] = useState([]); useEffect(() => { getSubStatements({ @@ -78,7 +76,9 @@ const StatementEvaluationPage: FC = ({ sort, questions, myStatements, - setSortedSubStatements, + }).then((_subStatements) => { + console.log("new st..............", _subStatements.length) + setSortedSubStatements(_subStatements); }); }, [sort, subStatements, questions, isMultiStage]); @@ -109,8 +109,9 @@ const StatementEvaluationPage: FC = ({ let topSum = 30; const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; + console.log(topSum, tops) - console.log(sortedSubStatements.map((subStatement:Statement) => subStatement.statement).join(',')); + return ( <> diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx new file mode 100644 index 000000000..7d1e7cc67 --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -0,0 +1,9 @@ +import React from 'react' + +const SuggestionCards = () => { + return ( +
SuggestionCards
+ ) +} + +export default SuggestionCards \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 5a8f24673..b4a725860 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -113,67 +113,47 @@ interface GetSubStatementsProps { sort: string | undefined; questions: boolean; myStatements: Statement[]; - setSortedSubStatements: React.Dispatch; } -export async function getSubStatements({ statement, subStatements, sort, questions, myStatements, setSortedSubStatements }: GetSubStatementsProps): Promise { +export async function getSubStatements({ statement, subStatements, sort, questions, myStatements }: GetSubStatementsProps): Promise { try { - console.log("getSubStatements") - if (!statement) return; - if (!subStatements) return; + + if (!statement) return []; + if (!subStatements) return []; const _subStatements = [...subStatements]; const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; if (!isMultiStage) { - const st = getSortedStatements(_subStatements, sort, questions); - console.log("single stage"); - setSortedSubStatements(st); + return getSortedStatements(_subStatements, sort, questions); } else { - console.log("multi steps") + switch (statement.questionSettings?.currentStage) { case QuestionStage.explanation: - setSortedSubStatements([]); - return; + return ([]); case QuestionStage.suggestion: - setSortedSubStatements(myStatements); - return; + return myStatements; case QuestionStage.firstEvaluation: - try { - const subStatements = await getFirstEvaluationOptions(statement); - const st = getSortedStatements(subStatements, sort, questions); - setSortedSubStatements(st); - } catch (error) { - console.error(error); - } - - return; + const firstSt = await getFirstEvaluationOptions(statement); + return getSortedStatements(firstSt, sort, questions); case QuestionStage.secondEvaluation: - try { - const subStatements = await getSecondEvaluationOptions(statement); - const st = getSortedStatements(subStatements, sort, questions); - setSortedSubStatements(st); - } catch (error) { - console.error(error); - } - return; + const secondSt = await getSecondEvaluationOptions(statement); + return getSortedStatements(secondSt, sort, questions); case QuestionStage.voting: - setSortedSubStatements([]); - return; + + return ([]); default: - console.log("default ") - setSortedSubStatements([]); - return; + return ([]); } } - return; + } catch (error) { console.error(error); - + return []; } } -function getSortedStatements(_subStatements:Statement[], sort: string | undefined, questions: boolean) { +function getSortedStatements(_subStatements: Statement[], sort: string | undefined, questions: boolean) { return sortSubStatements( _subStatements, sort From 0fcb459a24622144d4b19a1d4bc3d87481f6a55b Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 08:17:03 +0300 Subject: [PATCH 06/16] regualr sorting works --- .../solutions/StatementSolutionsPage.tsx | 41 +-- .../components/StatementSolutionCard.tsx | 304 +++++++++--------- .../SuggestionCards.module.scss | 4 + .../suggestionCards/SuggestionCards.tsx | 53 ++- 4 files changed, 214 insertions(+), 188 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 4ad68e497..20cc35258 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -25,6 +25,7 @@ import styles from "./statementSolutinsPage.module.scss"; import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; +import SuggestionCards from "./components/suggestionCards/SuggestionCards"; interface StatementEvaluationPageProps { statement: Statement; @@ -67,7 +68,9 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - const [sortedSubStatements, setSortedSubStatements] = useState([]); + const [sortedSubStatements, setSortedSubStatements] = useState( + [] + ); useEffect(() => { getSubStatements({ @@ -77,7 +80,7 @@ const StatementEvaluationPage: FC = ({ questions, myStatements, }).then((_subStatements) => { - console.log("new st..............", _subStatements.length) + console.log("new st..............", _subStatements.length); setSortedSubStatements(_subStatements); }); }, [sort, subStatements, questions, isMultiStage]); @@ -105,13 +108,7 @@ const StatementEvaluationPage: FC = ({ } }, [statement.questionSettings?.currentStage, questions]); - // Variables - let topSum = 30; - const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - console.log(topSum, tops) - - return ( <> @@ -133,29 +130,11 @@ const StatementEvaluationPage: FC = ({ {getToastButtons(currentStage)} )} - {sortedSubStatements?.map( - (statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } - - return ( - - ); - } - )} -
+
)}
diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx index 5adddffee..c78d33c17 100644 --- a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx @@ -6,8 +6,8 @@ import { Statement, StatementType, User } from "delib-npm"; // Redux Store import { useAppDispatch, useAppSelector } from "@/controllers/hooks/reduxHooks"; import { - setStatementElementHight, - statementSubscriptionSelector, + setStatementElementHight, + statementSubscriptionSelector, } from "@/model/statements/statementsSlice"; // Helpers @@ -15,7 +15,7 @@ import { isAuthorized, linkToChildren } from "@/controllers/general/helpers"; // Hooks import useStatementColor, { - StyleProps, + StyleProps, } from "@/controllers/hooks/useStatementColor"; // Custom Components @@ -33,6 +33,7 @@ import "./StatementSolutionCard.scss"; import SolutionMenu from "./solutionMenu/SolutionMenu"; interface Props { + statement: Statement; parentStatement: Statement; showImage: (talker: User | null) => void; @@ -40,156 +41,157 @@ interface Props { } const StatementSolutionCard: FC = ({ - parentStatement, - statement, - top, + + parentStatement, + statement, + top, }) => { - // Hooks - - const { t, dir } = useLanguage(); - - // Redux Store - const dispatch = useAppDispatch(); - const statementColor: StyleProps = useStatementColor( - statement.statementType || StatementType.statement - ); - const statementSubscription = useAppSelector( - statementSubscriptionSelector(statement.statementId) - ); - - // Use Refs - const elementRef = useRef(null); - - // Use States - const [newTop, setNewTop] = useState(top); - const [isEdit, setIsEdit] = useState(false); - const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = + // Hooks + + const { t, dir } = useLanguage(); + + // Redux Store + const dispatch = useAppDispatch(); + const statementColor: StyleProps = useStatementColor( + statement.statementType || StatementType.statement + ); + const statementSubscription = useAppSelector( + statementSubscriptionSelector(statement.statementId) + ); + + // Use Refs + const elementRef = useRef(null); + + // Use States + const [newTop, setNewTop] = useState(top); + const [isEdit, setIsEdit] = useState(false); + const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = useState(false); - const [isCardMenuOpen, setIsCardMenuOpen] = useState(false); - - const _isAuthorized = isAuthorized( - statement, - statementSubscription, - parentStatement.creatorId - ); - - useEffect(() => { - setNewTop(top); - }, [top]); - - useEffect(() => { - dispatch( - setStatementElementHight({ - statementId: statement.statementId, - height: elementRef.current?.clientHeight, - }) - ); - }, [statement.statement]); - - function handleSetOption() { - try { - if (statement.statementType === "option") { - const cancelOption = window.confirm( - "Are you sure you want to cancel this option?" - ); - if (cancelOption) { - setStatementIsOption(statement); - } - } else { - setStatementIsOption(statement); - } - } catch (error) { - console.error(error); - } - } - - const shouldLinkToChildStatements = linkToChildren( - statement, - parentStatement - ); - - const statementAge = new Date().getTime() - statement.createdAt; - - return ( -
-
-
- {t("Selected")} -
-
-
-
-
- -
-
- -
-
- {shouldLinkToChildStatements && ( -
- -
- )} -
- - {parentStatement.hasChildren && ( - setShouldShowAddSubQuestionModal(true)} - > - - - )} -
- {shouldShowAddSubQuestionModal && ( - - )} -
-
- ); + const [isCardMenuOpen, setIsCardMenuOpen] = useState(false); + + const _isAuthorized = isAuthorized( + statement, + statementSubscription, + parentStatement.creatorId + ); + + useEffect(() => { + setNewTop(top); + }, [top]); + + useEffect(() => { + dispatch( + setStatementElementHight({ + statementId: statement.statementId, + height: elementRef.current?.clientHeight, + }) + ); + }, [statement.statement, parentStatement.questionSettings?.currentStage]); + + function handleSetOption() { + try { + if (statement.statementType === "option") { + const cancelOption = window.confirm( + "Are you sure you want to cancel this option?" + ); + if (cancelOption) { + setStatementIsOption(statement); + } + } else { + setStatementIsOption(statement); + } + } catch (error) { + console.error(error); + } + } + + const shouldLinkToChildStatements = linkToChildren( + statement, + parentStatement + ); + + const statementAge = new Date().getTime() - statement.createdAt; + + return ( +
+
+
+ {t("Selected")} +
+
+
+
+
+ +
+
+ +
+
+ {shouldLinkToChildStatements && ( +
+ +
+ )} +
+ + {parentStatement.hasChildren && ( + setShouldShowAddSubQuestionModal(true)} + > + + + )} +
+ {shouldShowAddSubQuestionModal && ( + + )} +
+
+ ); }; export default StatementSolutionCard; diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss new file mode 100644 index 000000000..0320f56be --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.module.scss @@ -0,0 +1,4 @@ +.suggestions-wrapper{ + position: relative; + width: 100%; +} \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 7d1e7cc67..40354b9ca 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,9 +1,50 @@ -import React from 'react' +import { Statement, User } from "delib-npm"; +import { FC } from "react"; +import StatementEvaluationCard from "../StatementSolutionCard"; +import styles from "./SuggestionCards.module.scss"; -const SuggestionCards = () => { - return ( -
SuggestionCards
- ) +interface Props { + statement: Statement; + sortedSubStatements: Statement[]; + handleShowTalker: (talker: User | null) => void; } -export default SuggestionCards \ No newline at end of file +const SuggestionCards: FC = ({ + statement, + sortedSubStatements, + handleShowTalker, +}) => { + // Variables + let topSum = 30; + const tops: number[] = [topSum]; + + console.log(topSum, tops); + + return ( +
+ {sortedSubStatements?.map((statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } + + return ( + + ); + })} +
+
+ ); +}; + +export default SuggestionCards; From d15ee273f9bd1a609e8c884b8db6900d1097687f Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 08:58:22 +0300 Subject: [PATCH 07/16] refactoring to use context --- .../solutions/StatementSolutionsPage.tsx | 124 ++++++++---------- .../suggestionCards/SuggestionCards.tsx | 41 +++++- .../suggestionCards/suggestionCardsCont.ts | 16 +++ .../statementSolutionPageContext.tsx | 26 ++++ 4 files changed, 134 insertions(+), 73 deletions(-) create mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts create mode 100644 src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 20cc35258..3a1ac213e 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -4,11 +4,8 @@ import { FC, useEffect, useState } from "react"; import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { useParams, useNavigate } from "react-router"; -// Utils & Helpers -import { getSubStatements } from "./statementSolutionsCont"; - // Custom Components -import StatementEvaluationCard from "./components/StatementSolutionCard"; + import StatementBottomNav from "../nav/bottom/StatementBottomNav"; import Toast from "@/view/components/toast/Toast"; import Modal from "@/view/components/modal/Modal"; @@ -26,6 +23,7 @@ import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; import SuggestionCards from "./components/suggestionCards/SuggestionCards"; +import { SubStatementsProvider } from "./statementSolutionPageContext"; interface StatementEvaluationPageProps { statement: Statement; @@ -47,15 +45,13 @@ const StatementEvaluationPage: FC = ({ }) => { try { // Hooks - const { sort } = useParams(); + const navigate = useNavigate(); const { t } = useLanguage(); const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const myStatements = useSelector( - myStatementsByStatementIdSelector(statement.statementId) - ); + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); @@ -68,22 +64,9 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - const [sortedSubStatements, setSortedSubStatements] = useState( - [] - ); + - useEffect(() => { - getSubStatements({ - statement, - subStatements, - sort, - questions, - myStatements, - }).then((_subStatements) => { - console.log("new st..............", _subStatements.length); - setSortedSubStatements(_subStatements); - }); - }, [sort, subStatements, questions, isMultiStage]); + useEffect(() => { if (questions) { @@ -111,58 +94,61 @@ const StatementEvaluationPage: FC = ({ const message = stageInfo ? stageInfo.message : false; return ( - <> -
- {sortedSubStatements.length === 0 ? ( - + <> +
+ {subStatements.length === 0 ? ( + + ) : ( +
+ {isMultiStage && message && ( + + {getToastButtons(currentStage)} + + )} + +
+ )} +
+
+ - ) : ( -
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - + {showExplanation && ( + + -
+ )} -
-
- -
- {showExplanation && ( - - - - )} - {showModal && ( - - )} - + )} + + ); function getToastButtons(questionStage: QuestionStage | undefined) { diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 40354b9ca..7fe7b40b0 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,19 +1,52 @@ -import { Statement, User } from "delib-npm"; -import { FC } from "react"; +import { QuestionType, Statement, User } from "delib-npm"; +import { FC, useContext, useEffect } from "react"; import StatementEvaluationCard from "../StatementSolutionCard"; import styles from "./SuggestionCards.module.scss"; +import { getSubStatements } from "../../statementSolutionsCont"; +import { useParams } from "react-router-dom"; +import { useSelector } from "react-redux"; +import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; +import { SubStatementsContext } from "../../statementSolutionPageContext"; interface Props { statement: Statement; - sortedSubStatements: Statement[]; + subStatements: Statement[]; + questions: boolean; handleShowTalker: (talker: User | null) => void; } const SuggestionCards: FC = ({ statement, - sortedSubStatements, + subStatements, handleShowTalker, + questions, }) => { + const { sort } = useParams(); + const isMultiStage = + statement.questionSettings?.questionType === QuestionType.multipleSteps; + const myStatements = useSelector( + myStatementsByStatementIdSelector(statement.statementId) + ); + + const { sortedSubStatements, setSortedSubStatements } = + useContext(SubStatementsContext); + + useEffect(() => { + setSortedSubStatements(subStatements); + }, []); + + useEffect(() => { + getSubStatements({ + statement, + subStatements, + sort, + questions, + myStatements, + }).then((_subStatements) => { + setSortedSubStatements(_subStatements); + }); + }, [sort, subStatements, questions, isMultiStage]); + // Variables let topSum = 30; const tops: number[] = [topSum]; diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts new file mode 100644 index 000000000..35c5d626d --- /dev/null +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts @@ -0,0 +1,16 @@ +import { Statement } from "delib-npm"; + +export function getTops(sortedSubStatements: Statement[]): {statementId: string, top: number}[] { + let topSum = 30; + const tops: number[] = [topSum]; + + sortedSubStatements.forEach((statementSub: Statement, i: number) => { + //get the top of the element + if (statementSub.elementHight) { + topSum += statementSub.elementHight + 30; + tops.push(topSum); + } + }); + + return tops; +} \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx b/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx new file mode 100644 index 000000000..8d0acef39 --- /dev/null +++ b/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx @@ -0,0 +1,26 @@ +import React, { createContext, useState, ReactNode } from "react"; +import { Statement } from "delib-npm"; + +interface SubStatementsContextType { + sortedSubStatements: Statement[]; + setSortedSubStatements: React.Dispatch>; +} + +export const SubStatementsContext = createContext({ + sortedSubStatements: [], + setSortedSubStatements: () => {}, +}); + +interface SubStatementsProviderProps { + children: ReactNode; +} + +export const SubStatementsProvider: React.FC = ({ children }): ReactNode => { + const [sortedSubStatements, setSortedSubStatements] = useState([]); + + return ( + + {children} + + ); +}; \ No newline at end of file From cd69ec141167b21a4fa8e3e363549e425b7c6ce2 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 10:15:25 +0300 Subject: [PATCH 08/16] cont --- .../solutions/StatementSolutionsPage.tsx | 2 -- .../components/StatementSolutionCard.tsx | 36 +++++++++++++------ .../suggestionCards/SuggestionCards.tsx | 10 +++--- .../suggestionCards/suggestionCardsCont.ts | 16 --------- 4 files changed, 32 insertions(+), 32 deletions(-) delete mode 100644 src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index 3a1ac213e..fba66aba2 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -19,8 +19,6 @@ import { getTitle } from "@/controllers/general/helpers"; import CreateStatementModalSwitch from "../createStatementModalSwitch/CreateStatementModalSwitch"; import styles from "./statementSolutinsPage.module.scss"; -import { useSelector } from "react-redux"; -import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; import EmptyScreen from "./components/emptyScreen/EmptyScreen"; import SuggestionCards from "./components/suggestionCards/SuggestionCards"; import { SubStatementsProvider } from "./statementSolutionPageContext"; diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx index c78d33c17..8dc7c0760 100644 --- a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx @@ -1,4 +1,4 @@ -import { FC, useEffect, useRef, useState } from "react"; +import { FC, useContext, useEffect, useRef, useState } from "react"; // Third Party import { Statement, StatementType, User } from "delib-npm"; @@ -31,9 +31,9 @@ import CreateStatementModal from "../../createStatementModal/CreateStatementModa import Evaluation from "./evaluation/Evaluation"; import "./StatementSolutionCard.scss"; import SolutionMenu from "./solutionMenu/SolutionMenu"; +import { SubStatementsContext } from "../statementSolutionPageContext"; interface Props { - statement: Statement; parentStatement: Statement; showImage: (talker: User | null) => void; @@ -41,7 +41,6 @@ interface Props { } const StatementSolutionCard: FC = ({ - parentStatement, statement, top, @@ -63,6 +62,8 @@ const StatementSolutionCard: FC = ({ const elementRef = useRef(null); // Use States + const { sortedSubStatements, setSortedSubStatements } = + useContext(SubStatementsContext); const [newTop, setNewTop] = useState(top); const [isEdit, setIsEdit] = useState(false); const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = @@ -80,13 +81,27 @@ const StatementSolutionCard: FC = ({ }, [top]); useEffect(() => { - dispatch( - setStatementElementHight({ - statementId: statement.statementId, - height: elementRef.current?.clientHeight, - }) - ); - }, [statement.statement, parentStatement.questionSettings?.currentStage]); + const element = elementRef.current; + if (element) { + setTimeout(() => { + dispatch( + setStatementElementHight({ + statementId: statement.statementId, + height: elementRef.current?.clientHeight, + }) + ); + }, 0); + } + }, [elementRef.current?.clientHeight]); + + // useEffect(() => { + // dispatch( + // setStatementElementHight({ + // statementId: statement.statementId, + // height: elementRef.current?.clientHeight, + // }) + // ); + // }, [statement.statement, parentStatement.questionSettings?.currentStage]); function handleSetOption() { try { @@ -145,6 +160,7 @@ const StatementSolutionCard: FC = ({
+

{statement.elementHight || 0}

= ({ const { sortedSubStatements, setSortedSubStatements } = useContext(SubStatementsContext); - useEffect(() => { - setSortedSubStatements(subStatements); - }, []); + useEffect(() => { + setSortedSubStatements(subStatements); + }, []); + + useEffect(() => { getSubStatements({ @@ -45,7 +47,7 @@ const SuggestionCards: FC = ({ }).then((_subStatements) => { setSortedSubStatements(_subStatements); }); - }, [sort, subStatements, questions, isMultiStage]); + }, [sort,subStatements]); // Variables let topSum = 30; diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts deleted file mode 100644 index 35c5d626d..000000000 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCardsCont.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Statement } from "delib-npm"; - -export function getTops(sortedSubStatements: Statement[]): {statementId: string, top: number}[] { - let topSum = 30; - const tops: number[] = [topSum]; - - sortedSubStatements.forEach((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } - }); - - return tops; -} \ No newline at end of file From 57427a22ff1860db1a4407e310bfb8a0c0763fcf Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 12:51:21 +0300 Subject: [PATCH 09/16] we now have more clear sorting and animations + no update on random --- package-lock.json | 8 +- package.json | 2 +- src/model/statements/statementsSlice.ts | 26 ++++- .../solutions/StatementSolutionsPage.tsx | 105 ++++++++---------- .../suggestionCards/SuggestionCards.tsx | 74 +++++------- .../suggestionCard/SuggestionCard.scss} | 0 .../suggestionCard/SuggestionCard.tsx} | 49 ++++---- .../statementSolutionPageContext.tsx | 26 ----- .../solutions/statementSolutionsCont.ts | 36 ++++-- 9 files changed, 145 insertions(+), 181 deletions(-) rename src/view/pages/statement/components/solutions/components/{StatementSolutionCard.scss => suggestionCards/suggestionCard/SuggestionCard.scss} (100%) rename src/view/pages/statement/components/solutions/components/{StatementSolutionCard.tsx => suggestionCards/suggestionCard/SuggestionCard.tsx} (82%) delete mode 100644 src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx diff --git a/package-lock.json b/package-lock.json index df19d7431..4da32a9b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.44", + "delib-npm": "^1.3.45", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", @@ -5486,9 +5486,9 @@ } }, "node_modules/delib-npm": { - "version": "1.3.44", - "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.44.tgz", - "integrity": "sha512-6/5LMhuJ4lekGRVc4sChA6SRgEOxaXUySdswrkENlBMi1htrL8+6aM9zlX/ExJgjfzpOo8cgpibKKyKpENipOQ==", + "version": "1.3.45", + "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.45.tgz", + "integrity": "sha512-yV6KfkizLAldGPehKRCtw1ozad3PeVcuC3dzqDBflTcYvqaQOE/dAcy6Jbxny4EotgbROxG0jIiUndmgEpa+Qw==", "dependencies": { "react": "^18.3.1", "sass": "^1.77.6", diff --git a/package.json b/package.json index 476edb640..a53e6eb0e 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.44", + "delib-npm": "^1.3.45", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index bf3315336..8448a76bb 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -16,6 +16,7 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; +import { updateStatement } from "@/controllers/db/statements/setStatements"; enum StatementScreen { chat = "chat", @@ -206,6 +207,28 @@ export const statementsSlicer = createSlice({ console.error(error); } }, + updateStatementTop: ( + state, + action: PayloadAction<{ statementId: string; top: number }[]>, + ) => { + try { + const updates = action.payload; + updates.forEach((update) => { + try { + const statement = state.statements.find( + (statement) => statement.statementId === update.statementId, + ); + if (statement) statement.top = update.top; + else throw new Error("statement not found"); + } catch (error) { + console.error("On updateStatementTop loop: ",error); + } + + }); + } catch (error) { + console.error(error); + } + }, setTempStatementsForPresentation: (state, action: PayloadAction) => { try { const statements = action.payload; @@ -307,6 +330,7 @@ export const { setStatementsSubscription, setTempStatementsForPresentation, deleteStatement, + updateStatementTop, deleteSubscribedStatement, setStatementOrder, setScreen, @@ -443,7 +467,7 @@ export const subscriptionParentStatementSelector = (parentId: string) => ); -export const myStatementsByStatementIdSelector = (statementId: string) =>{ +export const myStatementsByStatementIdSelector = (statementId: string) => { const user = store.getState().user.user; return createSelector( (state: RootState) => state.statements.statements, diff --git a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx index fba66aba2..39b3f9d03 100644 --- a/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx +++ b/src/view/pages/statement/components/solutions/StatementSolutionsPage.tsx @@ -18,14 +18,11 @@ import { getStagesInfo } from "../settings/components/QuestionSettings/QuestionS import { getTitle } from "@/controllers/general/helpers"; import CreateStatementModalSwitch from "../createStatementModalSwitch/CreateStatementModalSwitch"; import styles from "./statementSolutinsPage.module.scss"; - -import EmptyScreen from "./components/emptyScreen/EmptyScreen"; import SuggestionCards from "./components/suggestionCards/SuggestionCards"; -import { SubStatementsProvider } from "./statementSolutionPageContext"; interface StatementEvaluationPageProps { statement: Statement; - subStatements: Statement[]; + handleShowTalker: (talker: User | null) => void; showNav?: boolean; questions?: boolean; @@ -35,7 +32,6 @@ interface StatementEvaluationPageProps { const StatementEvaluationPage: FC = ({ statement, - subStatements, handleShowTalker, questions = false, toggleAskNotifications, @@ -43,14 +39,12 @@ const StatementEvaluationPage: FC = ({ }) => { try { // Hooks - + const navigate = useNavigate(); const { t } = useLanguage(); const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - - const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = @@ -62,9 +56,6 @@ const StatementEvaluationPage: FC = ({ const [showExplanation, setShowExplanation] = useState( currentStage === QuestionStage.explanation && isMultiStage && !questions ); - - - useEffect(() => { if (questions) { @@ -92,61 +83,53 @@ const StatementEvaluationPage: FC = ({ const message = stageInfo ? stageInfo.message : false; return ( - - <> -
- {subStatements.length === 0 ? ( - - ) : ( -
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - -
+ <> +
+
+ {isMultiStage && message && ( + + {getToastButtons(currentStage)} + )} -
-
-
- {showExplanation && ( - - - - )} - {showModal && ( - +
+ +
+ {showExplanation && ( + + - )} - - + + )} + {showModal && ( + + )} + ); function getToastButtons(questionStage: QuestionStage | undefined) { diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 47144a475..051a5c101 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,83 +1,61 @@ import { QuestionType, Statement, User } from "delib-npm"; -import { FC, useContext, useEffect } from "react"; -import StatementEvaluationCard from "../StatementSolutionCard"; +import { FC, useEffect } from "react"; +import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; -import { getSubStatements } from "../../statementSolutionsCont"; +import { getSubStatements, sortSubStatements } from "../../statementSolutionsCont"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; -import { myStatementsByStatementIdSelector } from "@/model/statements/statementsSlice"; -import { SubStatementsContext } from "../../statementSolutionPageContext"; +import { + myStatementsByStatementIdSelector, + statementSubsSelector, +} from "@/model/statements/statementsSlice"; +import EmptyScreen from "../emptyScreen/EmptyScreen"; interface Props { statement: Statement; - subStatements: Statement[]; questions: boolean; handleShowTalker: (talker: User | null) => void; + currentPage?: string; + setShowModal: (show: boolean) => void; } const SuggestionCards: FC = ({ statement, - subStatements, handleShowTalker, questions, + currentPage = `suggestion`, + setShowModal, }) => { const { sort } = useParams(); - const isMultiStage = - statement.questionSettings?.questionType === QuestionType.multipleSteps; - const myStatements = useSelector( - myStatementsByStatementIdSelector(statement.statementId) + const subStatements = useSelector( + statementSubsSelector(statement.statementId) ); - const { sortedSubStatements, setSortedSubStatements } = - useContext(SubStatementsContext); + + useEffect(() => { + sortSubStatements(subStatements, sort, 30); + },[sort]); - useEffect(() => { - setSortedSubStatements(subStatements); - }, []); - - - - useEffect(() => { - getSubStatements({ - statement, - subStatements, - sort, - questions, - myStatements, - }).then((_subStatements) => { - setSortedSubStatements(_subStatements); - }); - }, [sort,subStatements]); - - // Variables - let topSum = 30; - const tops: number[] = [topSum]; - - console.log(topSum, tops); + if (!subStatements) { + return ( + + ); + } return (
- {sortedSubStatements?.map((statementSub: Statement, i: number) => { - //get the top of the element - if (statementSub.elementHight) { - topSum += statementSub.elementHight + 30; - tops.push(topSum); - } - + {subStatements?.map((statementSub: Statement) => { return ( ); })} -
+
); }; diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.scss b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.scss similarity index 100% rename from src/view/pages/statement/components/solutions/components/StatementSolutionCard.scss rename to src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.scss diff --git a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx similarity index 82% rename from src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx rename to src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx index 8dc7c0760..8343d5b02 100644 --- a/src/view/pages/statement/components/solutions/components/StatementSolutionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx @@ -1,7 +1,7 @@ -import { FC, useContext, useEffect, useRef, useState } from "react"; +import { FC, useEffect, useRef, useState } from "react"; // Third Party -import { Statement, StatementType, User } from "delib-npm"; +import { Screen, Statement, StatementType, User } from "delib-npm"; // Redux Store import { useAppDispatch, useAppSelector } from "@/controllers/hooks/reduxHooks"; @@ -25,29 +25,31 @@ import { useLanguage } from "@/controllers/hooks/useLanguages"; import EditTitle from "@/view/components/edit/EditTitle"; import IconButton from "@/view/components/iconButton/IconButton"; -import StatementChatMore from "../../chat/components/StatementChatMore"; +import StatementChatMore from "../../../../chat/components/StatementChatMore"; import AddQuestionIcon from "@/assets/icons/addQuestion.svg?react"; -import CreateStatementModal from "../../createStatementModal/CreateStatementModal"; -import Evaluation from "./evaluation/Evaluation"; -import "./StatementSolutionCard.scss"; -import SolutionMenu from "./solutionMenu/SolutionMenu"; -import { SubStatementsContext } from "../statementSolutionPageContext"; +import CreateStatementModal from "../../../../createStatementModal/CreateStatementModal"; +import Evaluation from "../../evaluation/Evaluation"; +import "./SuggestionCard.scss"; +import SolutionMenu from "../../solutionMenu/SolutionMenu"; +import { sortSubStatements } from "../../../statementSolutionsCont"; +import { useParams } from "react-router-dom"; interface Props { statement: Statement; + siblingStatements: Statement[]; parentStatement: Statement; showImage: (talker: User | null) => void; - top: number; } -const StatementSolutionCard: FC = ({ +const SuggestionCard: FC = ({ parentStatement, + siblingStatements, statement, - top, }) => { // Hooks const { t, dir } = useLanguage(); + const { sort } = useParams(); // Redux Store const dispatch = useAppDispatch(); @@ -62,9 +64,7 @@ const StatementSolutionCard: FC = ({ const elementRef = useRef(null); // Use States - const { sortedSubStatements, setSortedSubStatements } = - useContext(SubStatementsContext); - const [newTop, setNewTop] = useState(top); + const [isEdit, setIsEdit] = useState(false); const [shouldShowAddSubQuestionModal, setShouldShowAddSubQuestionModal] = useState(false); @@ -76,10 +76,6 @@ const StatementSolutionCard: FC = ({ parentStatement.creatorId ); - useEffect(() => { - setNewTop(top); - }, [top]); - useEffect(() => { const element = elementRef.current; if (element) { @@ -94,14 +90,11 @@ const StatementSolutionCard: FC = ({ } }, [elementRef.current?.clientHeight]); - // useEffect(() => { - // dispatch( - // setStatementElementHight({ - // statementId: statement.statementId, - // height: elementRef.current?.clientHeight, - // }) - // ); - // }, [statement.statement, parentStatement.questionSettings?.currentStage]); + useEffect(() => { + if (sort !== Screen.OPTIONS_RANDOM && sort !== Screen.QUESTIONS_RANDOM) { + sortSubStatements(siblingStatements, sort, 30); + } + }, [statement.consensus]); function handleSetOption() { try { @@ -135,7 +128,7 @@ const StatementSolutionCard: FC = ({ : "statement-evaluation-card" } style={{ - top: `${newTop}px`, + top: `${statement.top || 0}px`, borderLeft: `8px solid ${statementColor.backgroundColor || "wheat"}`, color: statementColor.color, flexDirection: dir === "ltr" ? "row" : "row-reverse", @@ -210,4 +203,4 @@ const StatementSolutionCard: FC = ({ ); }; -export default StatementSolutionCard; +export default SuggestionCard; diff --git a/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx b/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx deleted file mode 100644 index 8d0acef39..000000000 --- a/src/view/pages/statement/components/solutions/statementSolutionPageContext.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import React, { createContext, useState, ReactNode } from "react"; -import { Statement } from "delib-npm"; - -interface SubStatementsContextType { - sortedSubStatements: Statement[]; - setSortedSubStatements: React.Dispatch>; -} - -export const SubStatementsContext = createContext({ - sortedSubStatements: [], - setSortedSubStatements: () => {}, -}); - -interface SubStatementsProviderProps { - children: ReactNode; -} - -export const SubStatementsProvider: React.FC = ({ children }): ReactNode => { - const [sortedSubStatements, setSortedSubStatements] = useState([]); - - return ( - - {children} - - ); -}; \ No newline at end of file diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index b4a725860..4a3fa6377 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -5,14 +5,18 @@ import { enhancedEvaluationsThumbs, } from "./components/evaluation/enhancedEvaluation/EnhancedEvaluationModel"; import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; +import { store } from "@/model/store"; +import { updateStatementTop } from "@/model/statements/statementsSlice"; export function sortSubStatements( subStatements: Statement[], sort: string | undefined, -): Statement[] { + gap:number = 30 +): void { try { + const dispatch = store.dispatch; let _subStatements = [...subStatements]; switch (sort) { case Screen.OPTIONS_CONSENSUS: @@ -38,20 +42,28 @@ export function sortSubStatements( ); break; } - const __subStatements = _subStatements.map( - (statement: Statement, i: number) => { - const updatedStatement = Object.assign({}, statement); - updatedStatement.order = i; + + let totalHeight = gap; + const updates: { statementId: string; top: number }[] = _subStatements.map((subStatement) => { + try { + const update = { + statementId: subStatement.statementId, + top: totalHeight, + }; + totalHeight += (subStatement.elementHight || 0) + gap; + return update; + + } catch (error) { + console.error(error); + } + }).filter((update) => update !== undefined) as { statementId: string; top: number }[]; + dispatch(updateStatementTop(updates)); - return updatedStatement; - }, - ); - return __subStatements; } catch (error) { console.error(error); - return subStatements; + } } @@ -116,7 +128,7 @@ interface GetSubStatementsProps { } export async function getSubStatements({ statement, subStatements, sort, questions, myStatements }: GetSubStatementsProps): Promise { try { - + if (!statement) return []; if (!subStatements) return []; const _subStatements = [...subStatements]; @@ -126,7 +138,7 @@ export async function getSubStatements({ statement, subStatements, sort, questio if (!isMultiStage) { return getSortedStatements(_subStatements, sort, questions); } else { - + switch (statement.questionSettings?.currentStage) { case QuestionStage.explanation: return ([]); From 698fbb0355eb0672a1a27694f99234b56f9a5091 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 13:35:47 +0300 Subject: [PATCH 10/16] adjust height to new size --- .../components/suggestionCards/SuggestionCards.tsx | 11 ++++++++++- .../suggestionCards/suggestionCard/SuggestionCard.tsx | 5 ++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 051a5c101..25d559e64 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,5 +1,5 @@ import { QuestionType, Statement, User } from "delib-npm"; -import { FC, useEffect } from "react"; +import { FC, useEffect, useState } from "react"; import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; import { getSubStatements, sortSubStatements } from "../../statementSolutionsCont"; @@ -31,11 +31,20 @@ const SuggestionCards: FC = ({ statementSubsSelector(statement.statementId) ); + const [wrapperHeight, setWrapperHeight] = useState(0); + useEffect(() => { sortSubStatements(subStatements, sort, 30); },[sort]); + useEffect(() => { + if (subStatements) { + const height = subStatements.reduce((acc, statement:Statement) => acc + (statement.top ||0), 0); + setWrapperHeight(height); + } + }, [subStatements]); + if (!subStatements) { return ( diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx index 8343d5b02..8c9a02cc4 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/suggestionCard/SuggestionCard.tsx @@ -96,6 +96,10 @@ const SuggestionCard: FC = ({ } }, [statement.consensus]); + useEffect(() => { + sortSubStatements(siblingStatements, sort, 30); + }, [statement.elementHight]); + function handleSetOption() { try { if (statement.statementType === "option") { @@ -153,7 +157,6 @@ const SuggestionCard: FC = ({
-

{statement.elementHight || 0}

Date: Wed, 4 Sep 2024 14:01:26 +0300 Subject: [PATCH 11/16] created a new reducer for optins from multisteps --- package-lock.json | 8 +-- package.json | 2 +- src/model/statements/statementsSlice.ts | 48 +++++++-------- .../suggestionCards/SuggestionCards.tsx | 16 +---- .../solutions/statementSolutionsCont.ts | 60 +------------------ 5 files changed, 32 insertions(+), 102 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4da32a9b6..8f4b59db0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.45", + "delib-npm": "^1.3.46", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", @@ -5486,9 +5486,9 @@ } }, "node_modules/delib-npm": { - "version": "1.3.45", - "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.45.tgz", - "integrity": "sha512-yV6KfkizLAldGPehKRCtw1ozad3PeVcuC3dzqDBflTcYvqaQOE/dAcy6Jbxny4EotgbROxG0jIiUndmgEpa+Qw==", + "version": "1.3.46", + "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.46.tgz", + "integrity": "sha512-zOaIOguKki8p1mNbtSRjDRk0zNZrTVNCxRnPTEd3S3eoAmYrLljEJy3aIw2xrQceYfEwy+SQWPHG3KQTOJd31w==", "dependencies": { "react": "^18.3.1", "sass": "^1.77.6", diff --git a/package.json b/package.json index a53e6eb0e..93e5ad434 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "dependencies": { "@dagrejs/dagre": "^1.0.4", "@reduxjs/toolkit": "^1.9.5", - "delib-npm": "^1.3.45", + "delib-npm": "^1.3.46", "eslint-plugin-import": "^2.29.1", "eslint-plugin-sonarjs": "^1.0.3", "firebase": "^10.0.0", diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index 8448a76bb..db7198684 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -221,7 +221,7 @@ export const statementsSlicer = createSlice({ if (statement) statement.top = update.top; else throw new Error("statement not found"); } catch (error) { - console.error("On updateStatementTop loop: ",error); + console.error("On updateStatementTop loop: ", error); } }); @@ -229,29 +229,6 @@ export const statementsSlicer = createSlice({ console.error(error); } }, - setTempStatementsForPresentation: (state, action: PayloadAction) => { - try { - const statements = action.payload; - - - //clear all temp statements - state.statements.forEach((statement) => { - statement.isPartOfTempPresentation = false; - }); - - //set new temp statements - statements.forEach((statement) => { - statement.isPartOfTempPresentation = true; - state.statements = updateArray( - state.statements, - statement, - "statementId", - ); - }); - } catch (error) { - console.error(error); - } - }, setScreen: (state, action: PayloadAction) => { try { state.screen = action.payload; @@ -272,7 +249,7 @@ export const statementsSlicer = createSlice({ if (!_statement) throw new Error("statement not found"); const subScreens = _statement?.subScreens; if (subScreens?.length === 0 || subScreens === undefined) - throw new Error("no subscreens"); + throw new Error("no sub screens"); if (subScreens.includes(screen)) { _statement.subScreens = subScreens.filter( (subScreen) => subScreen !== screen, @@ -320,6 +297,27 @@ export const statementsSlicer = createSlice({ state.statementMembership = []; state.screen = StatementScreen.chat; }, + setCurrentMultiStepOptions: (state, action: PayloadAction) => { + try { + + const previousInMultiStageOptions = state.statements.filter(statement => statement.isInMultiStage); + previousInMultiStageOptions.forEach((statement) => { + statement.isInMultiStage = false; + }); + + const newStatements = action.payload; + newStatements.forEach((statement) => { + statement.isInMultiStage = true; + state.statements = updateArray( + state.statements, + statement, + "statementId", + ); + }); + } catch (error) { + console.error(error); + } + }, }, }); diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 25d559e64..600c9f678 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,15 +1,14 @@ -import { QuestionType, Statement, User } from "delib-npm"; -import { FC, useEffect, useState } from "react"; +import { Statement, User } from "delib-npm"; +import { FC, useEffect } from "react"; import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; -import { getSubStatements, sortSubStatements } from "../../statementSolutionsCont"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { - myStatementsByStatementIdSelector, statementSubsSelector, } from "@/model/statements/statementsSlice"; import EmptyScreen from "../emptyScreen/EmptyScreen"; +import { sortSubStatements } from "../../statementSolutionsCont"; interface Props { statement: Statement; @@ -22,7 +21,6 @@ interface Props { const SuggestionCards: FC = ({ statement, handleShowTalker, - questions, currentPage = `suggestion`, setShowModal, }) => { @@ -31,19 +29,11 @@ const SuggestionCards: FC = ({ statementSubsSelector(statement.statementId) ); - const [wrapperHeight, setWrapperHeight] = useState(0); - useEffect(() => { sortSubStatements(subStatements, sort, 30); },[sort]); - useEffect(() => { - if (subStatements) { - const height = subStatements.reduce((acc, statement:Statement) => acc + (statement.top ||0), 0); - setWrapperHeight(height); - } - }, [subStatements]); if (!subStatements) { return ( diff --git a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts index 4a3fa6377..562a6db5f 100644 --- a/src/view/pages/statement/components/solutions/statementSolutionsCont.ts +++ b/src/view/pages/statement/components/solutions/statementSolutionsCont.ts @@ -1,10 +1,9 @@ -import { Statement, Screen, isOptionFn, QuestionType, StatementType, QuestionStage } from "delib-npm"; +import { Statement, Screen } from "delib-npm"; import { EnhancedEvaluationThumb, enhancedEvaluationsThumbs, } from "./components/evaluation/enhancedEvaluation/EnhancedEvaluationModel"; -import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; import { store } from "@/model/store"; import { updateStatementTop } from "@/model/statements/statementsSlice"; @@ -119,62 +118,5 @@ export const getEvaluationThumbsToDisplay = ({ return [selectedThumb || defaultThumb]; }; -interface GetSubStatementsProps { - statement: Statement; - subStatements: Statement[]; - sort: string | undefined; - questions: boolean; - myStatements: Statement[]; -} -export async function getSubStatements({ statement, subStatements, sort, questions, myStatements }: GetSubStatementsProps): Promise { - try { - if (!statement) return []; - if (!subStatements) return []; - const _subStatements = [...subStatements]; - - const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - - if (!isMultiStage) { - return getSortedStatements(_subStatements, sort, questions); - } else { - - switch (statement.questionSettings?.currentStage) { - case QuestionStage.explanation: - return ([]); - case QuestionStage.suggestion: - return myStatements; - case QuestionStage.firstEvaluation: - const firstSt = await getFirstEvaluationOptions(statement); - return getSortedStatements(firstSt, sort, questions); - case QuestionStage.secondEvaluation: - const secondSt = await getSecondEvaluationOptions(statement); - return getSortedStatements(secondSt, sort, questions); - case QuestionStage.voting: - - return ([]); - default: - return ([]); - } - } - - } catch (error) { - console.error(error); - return []; - } -} - -function getSortedStatements(_subStatements: Statement[], sort: string | undefined, questions: boolean) { - return sortSubStatements( - _subStatements, - sort - ).filter((subStatement) => { - //if questions is true, only show questions - if (questions) { - return subStatement.statementType === StatementType.question; - } - //if options is true, only show options - return isOptionFn(subStatement); - }); -} From 5360ea31e49090e471f7d2e2689d60c0d3bfd769 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 15:23:47 +0300 Subject: [PATCH 12/16] freedi brings first evaluation and second evaluation --- .../getMultiStageStatements.ts | 83 ++++--------------- src/model/statements/statementsSlice.ts | 11 ++- .../settings/statementSettingsCont.ts | 8 +- .../suggestionCards/SuggestionCards.tsx | 30 +++++-- 4 files changed, 53 insertions(+), 79 deletions(-) diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 9bfb39ece..03c2c273a 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -1,68 +1,18 @@ -import { QuestionStage, Statement } from "delib-npm"; -import { Dispatch } from "react"; +import { Statement, StatementSchema } from "delib-npm"; +import { z } from "zod"; import { isProduction } from "@/controllers/general/helpers"; -import { setTempStatementsForPresentation } from "@/model/statements/statementsSlice"; +import { setCurrentMultiStepOptions } from "@/model/statements/statementsSlice"; import { store } from "@/model/store"; -// export async function getMultiStageOptions( -// statement: Statement, - -// ): Promise { -// const dispatch: Dispatch = store.dispatch; -// try { - -// const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; - -// if (statement.questionSettings?.currentStage === QuestionStage.suggestion) { -// const userId = store.getState().user.user?.uid; -// if (!userId) throw new Error("User not found"); - -// const url = isProduction() ? `https://getUserOptions-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getUserOptions"; - -// const response = await fetch( -// `${url}?parentId=${statement.statementId}&userId=${userId}` -// ); -// const { statements, error } = await response.json(); -// if (error) throw new Error(error); - -// dispatch(setTempStatementsForPresentation(statements)); -// } else if ( -// statement.questionSettings?.currentStage === QuestionStage.firstEvaluation -// ) { -// const url = isProduction() ? `https://getRandomStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getRandomStatements"; - -// const response = await fetch( -// `${url}?parentId=${statement.statementId}&limit=6` -// ); -// const { randomStatements, error } = await response.json(); -// if (error) throw new Error(error); -// dispatch(setTempStatementsForPresentation(randomStatements)); -// } else if ( -// statement.questionSettings?.currentStage === -// QuestionStage.secondEvaluation -// ) { -// const url = isProduction() ? `https://getTopStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getTopStatements"; -// const response = await fetch( -// `${url}?parentId=${statement.statementId}&limit=6` -// ); -// const { topSolutions, error } = await response.json(); -// if (error) throw new Error(error); -// dispatch(setTempStatementsForPresentation(topSolutions)); -// } else { -// dispatch(setTempStatementsForPresentation([])); -// } -// } catch (error) { -// console.error(error); -// dispatch(setTempStatementsForPresentation([])); -// } -// } export async function getFirstEvaluationOptions( statement: Statement, -): Promise { +): Promise { try { + console.log("getFirstEvaluationOptions") + const dispatch = store.dispatch; const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; const url = isProduction() ? `https://getRandomStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getRandomStatements"; @@ -72,19 +22,23 @@ export async function getFirstEvaluationOptions( ); const { randomStatements, error } = await response.json(); if (error) throw new Error(error); + z.array(StatementSchema).parse(randomStatements); + console.log(randomStatements) + + dispatch(setCurrentMultiStepOptions(randomStatements)); + - - return randomStatements as Statement[]; } catch (error) { console.error(error); - - return []; + + } } -export async function getSecondEvaluationOptions(statement: Statement): Promise { +export async function getSecondEvaluationOptions(statement: Statement): Promise { try { + const dispatch = store.dispatch; const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; const url = isProduction() ? `https://getTopStatements-${urlBase}` : "http://localhost:5001/synthesistalyaron/us-central1/getTopStatements"; @@ -94,11 +48,10 @@ export async function getSecondEvaluationOptions(statement: Statement): Promise< const { topSolutions, error } = await response.json(); if (error) throw new Error(error); - - return topSolutions as Statement[]; + z.array(StatementSchema).parse(topSolutions); + dispatch(setCurrentMultiStepOptions(topSolutions)); } catch (error) { console.error(error); - - return []; + } } \ No newline at end of file diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index db7198684..15a14d4c6 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -16,7 +16,7 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; -import { updateStatement } from "@/controllers/db/statements/setStatements"; + enum StatementScreen { chat = "chat", @@ -326,7 +326,6 @@ export const { setStatements, setStatementSubscription, setStatementsSubscription, - setTempStatementsForPresentation, deleteStatement, updateStatementTop, deleteSubscribedStatement, @@ -337,6 +336,7 @@ export const { setMembership, removeMembership, resetStatements, + setCurrentMultiStepOptions } = statementsSlicer.actions; // statements @@ -474,4 +474,11 @@ export const myStatementsByStatementIdSelector = (statementId: string) => { ); } +export const statementsOfMultiStepSelectorByStatementId =(statementId: string) => createSelector( + (state: RootState) => state.statements.statements, + (statements) => statements.filter((st) => st.isInMultiStage && st.parentId === statementId) +); + + + export default statementsSlicer.reducer; diff --git a/src/view/pages/statement/components/settings/statementSettingsCont.ts b/src/view/pages/statement/components/settings/statementSettingsCont.ts index 3e8d072b9..9cc1e5ac9 100644 --- a/src/view/pages/statement/components/settings/statementSettingsCont.ts +++ b/src/view/pages/statement/components/settings/statementSettingsCont.ts @@ -21,8 +21,7 @@ import { defaultStatementSettings, } from './emptyStatementModel'; import { NavigateFunction } from 'react-router-dom'; -import { store } from '@/model/store'; -import { setTempStatementsForPresentation } from '@/model/statements/statementsSlice'; + // Get users that voted on options in this statement export async function handleGetVoters( @@ -288,10 +287,7 @@ export async function createStatementFromModal({ addSubscription: true, }); - if (isSendToStoreTemp) { - //dispatch to the store - store.dispatch(setTempStatementsForPresentation([newStatement])); - } + } catch (error) { console.error(error); } diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 600c9f678..828a8a7fd 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,14 +1,16 @@ -import { Statement, User } from "delib-npm"; +import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { FC, useEffect } from "react"; -import StatementEvaluationCard from "./suggestionCard/SuggestionCard"; +import SuggestionCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { + statementsOfMultiStepSelectorByStatementId, statementSubsSelector, } from "@/model/statements/statementsSlice"; import EmptyScreen from "../emptyScreen/EmptyScreen"; import { sortSubStatements } from "../../statementSolutionsCont"; +import { getFirstEvaluationOptions, getSecondEvaluationOptions } from "@/controllers/db/multiStageQuestion/getMultiStageStatements"; interface Props { statement: Statement; @@ -25,14 +27,30 @@ const SuggestionCards: FC = ({ setShowModal, }) => { const { sort } = useParams(); - const subStatements = useSelector( - statementSubsSelector(statement.statementId) - ); + const {questionType ,currentStage} = statement.questionSettings || {questionType: QuestionType.singleStep, currentStage: QuestionStage.suggestion}; + const subStatements = switchSubStatements() ; + + function switchSubStatements(){ + if(questionType === QuestionType.singleStep) return useSelector( + statementSubsSelector(statement.statementId) + ) + else if(questionType === QuestionType.multipleSteps && currentStage !== QuestionStage.suggestion) return useSelector(statementsOfMultiStepSelectorByStatementId(statement.statementId)); + else return []; + } useEffect(() => { sortSubStatements(subStatements, sort, 30); },[sort]); + useEffect(() => { + if(questionType == QuestionType.multipleSteps){ + if(currentStage === QuestionStage.firstEvaluation) + getFirstEvaluationOptions(statement); + else if(currentStage === QuestionStage.secondEvaluation) + getSecondEvaluationOptions(statement); + + } + }, [currentStage, questionType]); if (!subStatements) { @@ -45,7 +63,7 @@ const SuggestionCards: FC = ({
{subStatements?.map((statementSub: Statement) => { return ( - Date: Wed, 4 Sep 2024 15:27:31 +0300 Subject: [PATCH 13/16] Bring my personal suggestions on suggestions --- .../solutions/components/suggestionCards/SuggestionCards.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 828a8a7fd..9e45d5991 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -5,6 +5,7 @@ import styles from "./SuggestionCards.module.scss"; import { useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { + myStatementsByStatementIdSelector, statementsOfMultiStepSelectorByStatementId, statementSubsSelector, } from "@/model/statements/statementsSlice"; @@ -36,6 +37,7 @@ const SuggestionCards: FC = ({ statementSubsSelector(statement.statementId) ) else if(questionType === QuestionType.multipleSteps && currentStage !== QuestionStage.suggestion) return useSelector(statementsOfMultiStepSelectorByStatementId(statement.statementId)); + else if(questionType === QuestionType.multipleSteps && currentStage === QuestionStage.suggestion) return useSelector(myStatementsByStatementIdSelector(statement.statementId)); else return []; } From 5551b66fc32b48ba1a8ce3a8c1cfcd0a781b85f6 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Wed, 4 Sep 2024 15:34:25 +0300 Subject: [PATCH 14/16] Basic steps are working --- .../solutions/components/suggestionCards/SuggestionCards.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index 9e45d5991..af7850ec1 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -2,7 +2,7 @@ import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; import { FC, useEffect } from "react"; import SuggestionCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { useSelector } from "react-redux"; import { myStatementsByStatementIdSelector, @@ -28,6 +28,7 @@ const SuggestionCards: FC = ({ setShowModal, }) => { const { sort } = useParams(); + const navigate = useNavigate(); const {questionType ,currentStage} = statement.questionSettings || {questionType: QuestionType.singleStep, currentStage: QuestionStage.suggestion}; const subStatements = switchSubStatements() ; @@ -50,6 +51,8 @@ const SuggestionCards: FC = ({ getFirstEvaluationOptions(statement); else if(currentStage === QuestionStage.secondEvaluation) getSecondEvaluationOptions(statement); + else if(currentStage === QuestionStage.voting) navigate(`statement/${statement.statementId}/vote`); + else if(currentStage === QuestionStage.finished) getSecondEvaluationOptions(statement); } }, [currentStage, questionType]); From 46bb012e17c5b23d090e0ec9e43f73ecafeee4a0 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Thu, 5 Sep 2024 09:22:25 +0300 Subject: [PATCH 15/16] multi-steps working --- .../components/suggestionCards/SuggestionCards.tsx | 12 ++++++++---- .../suggestionCard/SuggestionCard.scss | 1 - .../components/solutions/statementSolutionsCont.ts | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx index af7850ec1..853cbd3b7 100644 --- a/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx +++ b/src/view/pages/statement/components/solutions/components/suggestionCards/SuggestionCards.tsx @@ -1,5 +1,5 @@ import { QuestionStage, QuestionType, Statement, User } from "delib-npm"; -import { FC, useEffect } from "react"; +import { FC, useEffect, useState } from "react"; import SuggestionCard from "./suggestionCard/SuggestionCard"; import styles from "./SuggestionCards.module.scss"; import { useNavigate, useParams } from "react-router-dom"; @@ -30,9 +30,12 @@ const SuggestionCards: FC = ({ const { sort } = useParams(); const navigate = useNavigate(); + const [totalHeight, setTotalHeight] = useState(0); + const {questionType ,currentStage} = statement.questionSettings || {questionType: QuestionType.singleStep, currentStage: QuestionStage.suggestion}; const subStatements = switchSubStatements() ; + //change the source of options from the store based on the question type function switchSubStatements(){ if(questionType === QuestionType.singleStep) return useSelector( statementSubsSelector(statement.statementId) @@ -43,7 +46,8 @@ const SuggestionCards: FC = ({ } useEffect(() => { - sortSubStatements(subStatements, sort, 30); + const {totalHeight:_totalHeight} = sortSubStatements(subStatements, sort, 30); + setTotalHeight(_totalHeight); },[sort]); useEffect(() => { if(questionType == QuestionType.multipleSteps){ @@ -65,12 +69,12 @@ const SuggestionCards: FC = ({ } return ( -
+
{subStatements?.map((statementSub: Statement) => { return ( update !== undefined) as { statementId: string; top: number }[]; dispatch(updateStatementTop(updates)); - + return {totalHeight} } catch (error) { console.error(error); - + return {totalHeight:0}; } } From d441391cdc7d313b826c5b4e2163d9cdba13d829 Mon Sep 17 00:00:00 2001 From: Tal Yaron Date: Thu, 5 Sep 2024 10:19:42 +0300 Subject: [PATCH 16/16] linting and type check --- .../getMultiStageStatements.ts | 4 +- src/model/statements/statementsSlice.ts | 9 +- src/view/components/triangle/Triangle.tsx | 8 +- .../statement/components/SwitchScreens.tsx | 2 - .../settings/statementSettingsCont.ts | 3 +- .../solutions/StatementSolutionsPage.tsx | 331 +++++++++--------- .../components/emptyScreen/EmptyScreen.tsx | 108 +++--- .../suggestionCards/SuggestionCards.tsx | 110 +++--- .../suggestionCard/SuggestionCard.tsx | 316 ++++++++--------- .../solutions/statementSolutionsCont.ts | 48 +-- .../solutions/statementSolutionsHooks.ts | 38 -- .../components/vote/StatementVote.tsx | 2 +- 12 files changed, 468 insertions(+), 511 deletions(-) delete mode 100644 src/view/pages/statement/components/solutions/statementSolutionsHooks.ts diff --git a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 03c2c273a..51c606c4d 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -11,7 +11,7 @@ export async function getFirstEvaluationOptions( ): Promise { try { - console.log("getFirstEvaluationOptions") + const dispatch = store.dispatch; const urlBase = isProduction() ? "qeesi7aziq-uc.a.run.app" : "http://localhost:5001/synthesistalyaron/us-central1"; @@ -23,7 +23,7 @@ export async function getFirstEvaluationOptions( const { randomStatements, error } = await response.json(); if (error) throw new Error(error); z.array(StatementSchema).parse(randomStatements); - console.log(randomStatements) + dispatch(setCurrentMultiStepOptions(randomStatements)); diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index 15a14d4c6..4300da962 100644 --- a/src/model/statements/statementsSlice.ts +++ b/src/model/statements/statementsSlice.ts @@ -15,8 +15,6 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; -import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; - enum StatementScreen { chat = "chat", @@ -393,9 +391,7 @@ export const statementOptionsSelector = .sort((a, b) => a.createdAt - b.createdAt) .map((statement) => ({ ...statement })); - const sortedSubStatements = sortSubStatements(subStatements, state.statements.screen); - - return sortedSubStatements; + return subStatements; }; export const questionsSelector = (statementId: string | undefined) => (state: RootState) => state.statements.statements.filter((statement) => statement.parentId === statementId && statement.statementType === StatementType.question).sort((a, b) => a.createdAt - b.createdAt); @@ -467,7 +463,8 @@ export const subscriptionParentStatementSelector = (parentId: string) => export const myStatementsByStatementIdSelector = (statementId: string) => { const user = store.getState().user.user; - return createSelector( + +return createSelector( (state: RootState) => state.statements.statements, (statements) => statements.filter((st) => st.parentId === statementId && st.creatorId === user?.uid) diff --git a/src/view/components/triangle/Triangle.tsx b/src/view/components/triangle/Triangle.tsx index 514214674..89e03c5c9 100644 --- a/src/view/components/triangle/Triangle.tsx +++ b/src/view/components/triangle/Triangle.tsx @@ -14,12 +14,12 @@ interface Props { const Triangle: FC = ({ statement }) => { const {t} = useLanguage(); - const subStatements = useSelector( + const subStatements:Statement[] = useSelector( statementOptionsSelector(statement.statementId) - ).filter((s) => s.evaluation?.sumCon !== undefined); + ).filter((s:Statement) => s.evaluation?.sumCon !== undefined); let maxEvaluators = 0; - subStatements.forEach((subStatement) => { + subStatements.forEach((subStatement:Statement) => { if (subStatement.evaluation?.numberOfEvaluators !== undefined && subStatement.evaluation?.numberOfEvaluators > maxEvaluators) maxEvaluators = subStatement.evaluation.numberOfEvaluators; }); @@ -29,7 +29,7 @@ const Triangle: FC = ({ statement }) => {
- {subStatements.map((subStatement) => { + {subStatements.map((subStatement:Statement) => { return ( ); diff --git a/src/view/pages/statement/components/SwitchScreens.tsx b/src/view/pages/statement/components/SwitchScreens.tsx index b34271f82..18e6a355c 100644 --- a/src/view/pages/statement/components/SwitchScreens.tsx +++ b/src/view/pages/statement/components/SwitchScreens.tsx @@ -53,7 +53,6 @@ export default function SwitchScreens({ return ( @@ -83,7 +82,6 @@ export default function SwitchScreens({ return ( void; showNav?: boolean; questions?: boolean; @@ -31,178 +30,178 @@ interface StatementEvaluationPageProps { } const StatementEvaluationPage: FC = ({ - statement, - handleShowTalker, - questions = false, - toggleAskNotifications, - currentPage = `suggestion`, + statement, + handleShowTalker, + questions = false, + toggleAskNotifications, + currentPage = `suggestion`, }) => { - try { - // Hooks + try { + // Hooks - const navigate = useNavigate(); - const { t } = useLanguage(); - const isMultiStage = + const navigate = useNavigate(); + const { t } = useLanguage(); + const isMultiStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; - const currentStage = statement.questionSettings?.currentStage; - const stageInfo = getStagesInfo(currentStage); - const useSearchForSimilarStatements = + const currentStage = statement.questionSettings?.currentStage; + const stageInfo = getStagesInfo(currentStage); + const useSearchForSimilarStatements = statement.statementSettings?.enableSimilaritiesSearch || false; - // Use States - const [showModal, setShowModal] = useState(false); - const [showToast, setShowToast] = useState(false); - const [showExplanation, setShowExplanation] = useState( - currentStage === QuestionStage.explanation && isMultiStage && !questions - ); - - useEffect(() => { - if (questions) { - setShowToast(false); - } - }, [questions]); - - useEffect(() => { - if (!showToast && !questions) { - setShowToast(true); - } - if ( - currentStage === QuestionStage.explanation && + // Use States + const [showModal, setShowModal] = useState(false); + const [showToast, setShowToast] = useState(false); + const [showExplanation, setShowExplanation] = useState( + currentStage === QuestionStage.explanation && isMultiStage && !questions + ); + + useEffect(() => { + if (questions) { + setShowToast(false); + } + }, [questions]); + + useEffect(() => { + if (!showToast && !questions) { + setShowToast(true); + } + if ( + currentStage === QuestionStage.explanation && isMultiStage && !questions - ) { - setShowExplanation(true); - } - if (currentStage === QuestionStage.voting && !questions) { - //redirect us react router dom to voting page - navigate(`/statement/${statement.statementId}/vote`); - } - }, [statement.questionSettings?.currentStage, questions]); - - const message = stageInfo ? stageInfo.message : false; - - return ( - <> -
-
- {isMultiStage && message && ( - - {getToastButtons(currentStage)} - - )} - -
-
-
- -
- {showExplanation && ( - - - - )} - {showModal && ( - - )} - - ); - - function getToastButtons(questionStage: QuestionStage | undefined) { - try { - switch (questionStage) { - case QuestionStage.voting: - case QuestionStage.firstEvaluation: - case QuestionStage.secondEvaluation: - case QuestionStage.finished: - case QuestionStage.explanation: - return ( -