diff --git a/package-lock.json b/package-lock.json index df19d7431..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.44", + "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.44", - "resolved": "https://registry.npmjs.org/delib-npm/-/delib-npm-1.3.44.tgz", - "integrity": "sha512-6/5LMhuJ4lekGRVc4sChA6SRgEOxaXUySdswrkENlBMi1htrL8+6aM9zlX/ExJgjfzpOo8cgpibKKyKpENipOQ==", + "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 476edb640..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.44", + "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/controllers/db/multiStageQuestion/getMultiStageStatements.ts b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts index 34bceeafa..51c606c4d 100644 --- a/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts +++ b/src/controllers/db/multiStageQuestion/getMultiStageStatements.ts @@ -1,58 +1,57 @@ -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( + +export async function getFirstEvaluationOptions( statement: Statement, ): Promise { - const dispatch: Dispatch = store.dispatch; + + try { + + 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"; + + const response = await fetch( + `${url}?parentId=${statement.statementId}&limit=6` + ); + const { randomStatements, error } = await response.json(); + if (error) throw new Error(error); + z.array(StatementSchema).parse(randomStatements); + + + dispatch(setCurrentMultiStepOptions(randomStatements)); + + + } catch (error) { + console.error(error); + + + } +} + +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"; - 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([])); - } + 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); + + z.array(StatementSchema).parse(topSolutions); + dispatch(setCurrentMultiStepOptions(topSolutions)); } catch (error) { console.error(error); - dispatch(setTempStatementsForPresentation([])); + } } \ No newline at end of file diff --git a/src/model/statements/statementsSlice.ts b/src/model/statements/statementsSlice.ts index dd5889884..4300da962 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 @@ -15,7 +15,6 @@ import { // Helpers import { updateArray } from "../../controllers/general/helpers"; -import { sortSubStatements } from "../../view/pages/statement/components/solutions/statementSolutionsCont"; enum StatementScreen { chat = "chat", @@ -206,24 +205,23 @@ export const statementsSlicer = createSlice({ console.error(error); } }, - setTempStatementsForPresentation: (state, action: PayloadAction) => { + updateStatementTop: ( + state, + action: PayloadAction<{ statementId: string; top: number }[]>, + ) => { try { - const statements = action.payload; + 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); + } - - //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); @@ -241,7 +239,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, @@ -249,7 +247,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, @@ -297,6 +295,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); + } + }, }, }); @@ -305,8 +324,8 @@ export const { setStatements, setStatementSubscription, setStatementsSubscription, - setTempStatementsForPresentation, deleteStatement, + updateStatementTop, deleteSubscribedStatement, setStatementOrder, setScreen, @@ -315,6 +334,7 @@ export const { setMembership, removeMembership, resetStatements, + setCurrentMultiStepOptions } = statementsSlicer.actions; // statements @@ -371,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); @@ -434,7 +452,7 @@ export const hasTokenSelector = return statement?.token?.includes(token) || false; }; - + export const subscriptionParentStatementSelector = (parentId: string) => createSelector( (state: RootState) => state.statements.statementSubscription, @@ -442,4 +460,22 @@ 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 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/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 ( >; isQuestion: boolean; - isMuliStage: boolean; + isMultiStage: boolean; parentStatement: Statement; toggleAskNotifications: () => void; } @@ -16,7 +16,7 @@ export default function CreateStatementModalSwitch({ useSimilarStatements, setShowModal, isQuestion, - isMuliStage, + isMultiStage, parentStatement, toggleAskNotifications, }: CreateStatementModalSwitchProps) { @@ -26,7 +26,7 @@ export default function CreateStatementModalSwitch({ isQuestion={isQuestion} parentStatement={parentStatement} toggleAskNotifications={toggleAskNotifications} - isSendToStoreTemp={isMuliStage} + isSendToStoreTemp={isMultiStage} /> ) : ( ); } diff --git a/src/view/pages/statement/components/nav/bottom/StatementBottomNav.tsx b/src/view/pages/statement/components/nav/bottom/StatementBottomNav.tsx index 08f49af37..67335aa85 100644 --- a/src/view/pages/statement/components/nav/bottom/StatementBottomNav.tsx +++ b/src/view/pages/statement/components/nav/bottom/StatementBottomNav.tsx @@ -90,8 +90,8 @@ const StatementBottomNav: FC = ({ setShowModal, statement }) => { ) }
- {navItems.map((navItem) => ( -
+ {navItems.map((navItem, i) => ( +
void; - showNav?: boolean; - questions?: boolean; - toggleAskNotifications: () => void; - currentPage?: string; + statement: Statement; + handleShowTalker: (talker: User | null) => void; + showNav?: boolean; + questions?: boolean; + toggleAskNotifications: () => void; + currentPage?: string; } const StatementEvaluationPage: FC = ({ statement, - subStatements, handleShowTalker, questions = false, toggleAskNotifications, @@ -54,66 +38,38 @@ const StatementEvaluationPage: FC = ({ }) => { try { // Hooks - const { sort } = useParams(); + const navigate = useNavigate(); const { t } = useLanguage(); - const isMuliStage = statement.questionSettings?.questionType === QuestionType.multipleSteps; + const isMultiStage = + statement.questionSettings?.questionType === QuestionType.multipleSteps; + const currentStage = statement.questionSettings?.currentStage; const stageInfo = getStagesInfo(currentStage); const useSearchForSimilarStatements = - statement.statementSettings?.enableSimilaritiesSearch || false; + statement.statementSettings?.enableSimilaritiesSearch || false; // 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] + currentStage === QuestionStage.explanation && isMultiStage && !questions ); - 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 options is true, only show options - return isOptionFn(subStatement); - }); - - setSortedSubStatements(_sortedSubStatements); - }, [sort, subStatements, questions]); - useEffect(() => { if (questions) { setShowToast(false); } }, [questions]); - useEffect(() => { - if (isMuliStage) { - getMultiStageOptions(statement); - } - }, [currentStage]); - useEffect(() => { if (!showToast && !questions) { setShowToast(true); } if ( currentStage === QuestionStage.explanation && - isMuliStage && - !questions + isMultiStage && + !questions ) { setShowExplanation(true); } @@ -123,90 +79,13 @@ const StatementEvaluationPage: FC = ({ } }, [statement.questionSettings?.currentStage, questions]); - // Variables - let topSum = 30; - const tops: number[] = [topSum]; const message = stageInfo ? stageInfo.message : false; - const handlePlusIconClick = () => { - setShowModal(true); - }; - - const { width } = useWindowDimensions(); - const smallScreen = width < 1024; - - 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 && ( - - )} - - ); - - if (sortedSubStatements.length === 0) { - return renderCommonContent(); - } - return ( <> -
-
- {isMuliStage && message && ( +
+
+ {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 ( - - ); - })} -
+
-
+
= ({ toggleAskNotifications={toggleAskNotifications} parentStatement={statement} isQuestion={questions} - isMuliStage={isMuliStage} + isMultiStage={isMultiStage} setShowModal={setShowModal} useSimilarStatements={useSearchForSimilarStatements} /> )} ); + function getToastButtons(questionStage: QuestionStage | undefined) { try { switch (questionStage) { @@ -276,53 +141,53 @@ const StatementEvaluationPage: FC = ({ case QuestionStage.explanation: return (