Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
import React from "react";
import VeryGoodSvg from "../../assets/svg/veryGood.svg";
import GoodSvg from "../../assets/svg/good.svg";
import MiddleSvg from "../../assets/svg/middle.svg";
import BadSvg from "../../assets/svg/bad.svg";
import VeryBadSvg from "../../assets/svg/veryBad.svg";
import TodaySvg from "../../assets/svg/today.svg";
import YesterdaySvg from "../../assets/svg/yesterday.svg";
import NotesSvg from "../../assets/svg/notes.svg";
import DrugsSvg from "../../assets/svg/drugs.svg";
import HeartsSvg from "../../assets/svg/hearts.svg";
import PlusSvg from "../../assets/svg/plus-1.svg";
import QuestionMarkSvg from "../../assets/svg/QuestionMark.js";

import { StyleSheet, View } from "react-native";
Expand All @@ -18,6 +7,7 @@ import SmileyGood from "@assets/svg/smileys/good";
import SmileyMiddle from "@assets/svg/smileys/middle";
import SmileyBad from "@assets/svg/smileys/bad";
import SmileyVeryBad from "@assets/svg/smileys/veryBad";
import PlusIcon from "@assets/svg/icon/plus";

const styles = StyleSheet.create({
iconContainer: {
Expand All @@ -40,13 +30,8 @@ const mapIconToSvg = (icon) => {
MiddleSvg: SmileyMiddle,
BadSvg: SmileyBad,
VeryBadSvg: SmileyVeryBad,
TodaySvg,
YesterdaySvg,
NotesSvg,
DrugsSvg,
HeartsSvg,
PlusSvg,
QuestionMarkSvg,
Plus: PlusIcon,
};
return iconMap[icon];
};
Expand Down
27 changes: 14 additions & 13 deletions app/src/scenes/status/DiaryList.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { canEdit } from "./utils/index";
import { useFocusEffect, useNavigation } from "@react-navigation/native";
import { getGoalsData } from "../../utils/localStorage/goals";
import localStorage from "../../utils/localStorage";
import NewStatusItem from "./NewStatusItem";

export const DiaryList = forwardRef(({ ...props }, ref) => {
const navigation = useNavigation();
Expand All @@ -33,19 +34,19 @@ export const DiaryList = forwardRef(({ ...props }, ref) => {
const renderItem = useCallback(
({ item: date }) => {
return (
<View>
<View style={styles.dateContainer}>
<View style={styles.dateDot} />
{canEdit(date) ? (
<Text style={styles.dateLabel}>{formatDateThread(date)}</Text>
) : (
<TouchableOpacity style={styles.item} onPress={() => navigation.navigate("too-late", { date })}>
<Text style={styles.dateLabel}>{formatDateThread(date)}</Text>
</TouchableOpacity>
)}
</View>
<StatusItem date={date} indicateurs={indicateurs} patientState={diaryData[date]} goalsData={goalsData} navigation={navigation} />
</View>
// <View>
// <View style={styles.dateContainer}>
// <View style={styles.dateDot} />
// {canEdit(date) ? (
// <Text style={styles.dateLabel}>{formatDateThread(date)}</Text>
// ) : (
// <TouchableOpacity style={styles.item} onPress={() => navigation.navigate("too-late", { date })}>
// <Text style={styles.dateLabel}>{formatDateThread(date)}</Text>
// </TouchableOpacity>
// )}
// </View>
<NewStatusItem date={date} indicateurs={indicateurs} patientState={diaryData[date]} goalsData={goalsData} navigation={navigation} />
// </View>
);
},
[diaryData, goalsData, indicateurs]
Expand Down
230 changes: 230 additions & 0 deletions app/src/scenes/status/NewStatusItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
import React, { useEffect, useState, useRef } from "react";
import { StyleSheet, View, TouchableOpacity, Text } from "react-native";
import PatientStateItem from "./patient-state-item";
import { displayedCategories, TW_COLORS } from "../../utils/constants";
import Notes from "./notes";
import localStorage from "../../utils/localStorage";
import Posology from "./posology";
import { canEdit } from "./utils/index.js";
import Button from "../../components/RoundButtonIcon";
import Toxic from "./toxic";
import Context from "./context";
import logEvents from "../../services/logEvents";
import {
GENERIC_INDICATOR_SUBSTANCE,
INDICATEURS_HUMEUR,
INDICATEURS_LIST,
STATIC_UUID_FOR_INSTANCE_OF_GENERIC_INDICATOR_SUBSTANCE,
} from "../../utils/liste_indicateurs.1";
import { GoalsStatus } from "../goals/status/GoalsStatus";
import { Card } from "../../components/Card";
import { GoalsStatusNoData } from "../goals/status/GoalsStatusNoData";
import { generateIndicatorFromPredefinedIndicator, Indicator } from "@/entities/Indicator";
import { DiaryDataAnswer, DiaryEntry } from "@/entities/DiaryData";
import { GoalRecordsData, GoalsData } from "@/entities/Goal";
import { BasicIcon } from "@/components/CircledIcon";
import { answers as emojis } from "../survey-v2/utils";
import { typography } from "@/utils/typography";
import { mergeClassNames } from "@/utils/className";
import { formatRelativeDate } from "@/utils/date/helpers";
import ArrowIcon from "@assets/svg/icon/Arrow";

export default ({
navigation,
indicateurs = [],
patientState,
goalsData,
date,
}: {
navigation: any;
indicateurs: Indicator[];
patientState: DiaryEntry;
goalsData: GoalsData;
date: Date;
}) => {
const [customs, setCustoms] = useState([]);
const [oldCustoms, setOldCustoms] = useState([]);
let mounted = useRef(true);

useEffect(() => {
(async () => {
const c = await localStorage.getCustomSymptoms();
if (c && mounted) setCustoms(c);

//retrocompatibility
const t = c.map((e) => `${e}_FREQUENCE`);
if (t && mounted) setOldCustoms(t);
return;
})();
return () => (mounted = false);
}, [patientState]);
Comment on lines +47 to +60
Copy link
Collaborator

@revu-bot revu-bot Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mounted ref pattern is being used but the cleanup in useEffect return is not properly implemented. The ref should be properly typed and the cleanup should set mounted.current = false.

Suggested change
let mounted = useRef(true);
useEffect(() => {
(async () => {
const c = await localStorage.getCustomSymptoms();
if (c && mounted) setCustoms(c);
//retrocompatibility
const t = c.map((e) => `${e}_FREQUENCE`);
if (t && mounted) setOldCustoms(t);
return;
})();
return () => (mounted = false);
}, [patientState]);
const mounted = useRef(true);


const handleEdit = (tab, editingSurvey = false, toGoals) => {
if (!canEdit(date)) return;
const currentSurvey = {
date,
answers: patientState,
};
navigation.navigate(tab, {
currentSurvey,
editingSurvey,
toGoals,
});
};

const hasAnswerSurvey = () =>
patientStateRecordKeys.some((key) => patientState[key]?.value !== undefined) || goalsData?.records?.byDate?.[date]?.length > 0;
Comment on lines +75 to +76
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function calls hasAnswerSurvey() before patientStateRecordKeys is defined, which will cause a ReferenceError. The function definition should be moved after the patientStateRecordKeys declaration.

Suggested change
const hasAnswerSurvey = () =>
patientStateRecordKeys.some((key) => patientState[key]?.value !== undefined) || goalsData?.records?.byDate?.[date]?.length > 0;
// hasAnswerSurvey function moved after patientStateRecordKeys definition


const handlePressItem = ({ editingSurvey, toGoals } = {}) => {
if (!canEdit(date)) return navigation.navigate("too-late", { date });
logEvents.logFeelingEditButtonClick();
handleEdit("day-survey", editingSurvey, toGoals);
};

// DiaryDataAnswer;
const patientStateRecordKeys = patientState
? Object.keys(patientState)
.filter((key) => {
return !["CONTEXT", "POSOLOGY", "NOTES", "PRISE_DE_TRAITEMENT", "PRISE_DE_TRAITEMENT_SI_BESOIN", "becks"].includes(key);
})
.filter((key) => !!patientState[key])
.filter((key) => key)
.sort((_a, _b) => {
const a = patientState[_a];
const b = patientState[_b];
const aIndex = indicateurs?.findIndex?.((indicateur) => indicateur?.uuid === a?._indicateur?.uuid) || 0;
const bIndex = indicateurs?.findIndex?.((indicateur) => indicateur?.uuid === b?._indicateur?.uuid) || 0;
return aIndex - bIndex;
})
: [];
Comment on lines +98 to +99
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the hasAnswerSurvey function definition after patientStateRecordKeys is available, and fix the logic to handle the case when patientStateRecordKeys is empty.

Suggested change
})
: [];
})
: [];
const hasAnswerSurvey = () =>
patientStateRecordKeys.some((key) => patientState[key]?.value !== undefined) || goalsData?.records?.byDate?.[date]?.length > 0;


if (hasAnswerSurvey()) {
const emotion = Object.keys(patientState).find(
(key) => (key === INDICATEURS_HUMEUR.uuid || key === INDICATEURS_HUMEUR.name) && patientState[key].value !== undefined
);
let emotionValue;
if (emotion) {
emotionValue = patientState[emotion].value;
}
return (
<TouchableOpacity className="rounded-2xl border border-gray-500 flex-col my-4 p-6" onPress={() => handlePressItem({ editingSurvey: true })}>
<View className="mb-4 flex-row justify-between">
<Text className={mergeClassNames(typography.textMdBold, "text-cnam-primary-950 capitalize")}>{formatRelativeDate(date)}</Text>
<ArrowIcon />
</View>
<View className="flex-1 flex-row items-center mb-6">
{emotionValue && (
<BasicIcon
color={emojis[emotionValue].backgroundColor}
borderColor={TW_COLORS.PRIMARY}
iconColor={emojis[emotionValue].iconColor}
icon={emojis[emotionValue].icon}
borderWidth={0}
iconContainerStyle={{ marginRight: 0 }}
iconWidth={32}
iconHeight={32}
/>
)}
<View className="ml-2 p-2 flex-1">
<Text className={mergeClassNames(typography.textSmMedium, "text-cnam-primary-950")}>Anxiété, Accablement, Contrariété, Jalousie,</Text>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded placeholder text should be replaced with dynamic data based on the actual patient state indicators.

Suggested change
<Text className={mergeClassNames(typography.textSmMedium, "text-cnam-primary-950")}>Anxiété, Accablement, Contrariété, Jalousie,</Text>
<Text className={mergeClassNames(typography.textSmMedium, "text-cnam-primary-950")}>
{patientStateRecordKeys.map(key => {
const indicator = indicateurs.find(i => i.genericUuid === key) || indicateurs.find(i => i.uuid === key);
return indicator?.name;
}).filter(Boolean).join(', ')}
</Text>

</View>
</View>
{[0, 1, 2, 3].map((item) => (
<View className="flex-1 flex-row items-center mb-2">
<View className="h-3 w-3 rounded-full mr-2 bg-red"></View>
<View>
<Text>Anxiété, Irritabilité</Text>
</View>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hardcoded text and the map over [0,1,2,3] appears to be placeholder/debug code. Hardcoded strings like 'Anxiété, Accablement, Contrariété, Jalousie,' should be replaced with dynamic data or at minimum moved to constants.

Suggested change
{[0, 1, 2, 3].map((item) => (
<View className="flex-1 flex-row items-center mb-2">
<View className="h-3 w-3 rounded-full mr-2 bg-red"></View>
<View>
<Text>Anxiété, Irritabilité</Text>
</View>
{patientStateRecordKeys.map((key) => {
let patientStateRecord = patientState[key];
if (!patientStateRecord || patientStateRecord?.value === null || patientStateRecord.value === undefined) {
return null;
}
const indicator = indicateurs.find((i) => i.genericUuid === key) || indicateurs.find((i) => i.uuid === key);
return (
<View key={key} className="flex-1 flex-row items-center mb-2">
<View className="h-3 w-3 rounded-full mr-2 bg-red"></View>
<View>
<Text>{indicator?.name || 'Unknown Indicator'}</Text>
</View>

{/* <View>
{patientStateRecordKeys.map((key) => {
let patientStateRecord = patientState[key];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the large blocks of commented-out code. This appears to be old implementation that should either be deleted or moved to a separate branch/PR if it's still needed for reference.

if (!patientStateRecord || patientStateRecord?.value === null || patientStateRecord.value === undefined) {
return;
}
let [categoryName] = key.split("_");
if (categoryName === "TOXIC") {
// for user with historic value in 'TOXIC', we replace category name by uuid for indicator substance
key = STATIC_UUID_FOR_INSTANCE_OF_GENERIC_INDICATOR_SUBSTANCE;
patientStateRecord = {
...patientStateRecord,
_indicateur: {
...generateIndicatorFromPredefinedIndicator(GENERIC_INDICATOR_SUBSTANCE),
uuid: key,
},
};
}
const indicator = indicateurs.find((i) => i.genericUuid === key) || indicateurs.find((i) => i.uuid === key);
return (
<PatientStateItem
key={key}
category={key}
patientStateRecord={patientStateRecord}
label={
indicator?.name ||
patientStateRecord?._indicateur?.name ||
INDICATEURS_LIST[key] ||
displayedCategories[key] ||
categoryName ||
"Unknown Indicator"
}
/>
);
})}

<GoalsStatus goalsData={goalsData} date={date} withSeparator={patientStateRecordKeys?.length > 0} />
<Context data={patientState?.CONTEXT} />
<Posology posology={patientState?.POSOLOGY} patientState={patientState} date={date} onPress={() => handleEdit("drugs")} />
<Notes notes={patientState?.NOTES} date={date} onPress={() => handleEdit("notes")} />
</View> */}
</View>
))}
{/* {canEdit(date) ? (
<View>
<Button icon="pencil" visible={true} onPress={() => handlePressItem({ editingSurvey: true })} />
</View>
) : null} */}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Large commented code blocks should be removed rather than left in the codebase. This improves readability and reduces maintenance overhead.

</TouchableOpacity>
);
} else {
return (
<>
{/* {canEdit(date) ? (
<View>
<Card
preset="grey"
title={canEdit(date) ? "Renseigner mon état pour ce jour-là" : "Je ne peux plus saisir mon questionnaire pour ce jour"}
image={{ source: require("./../../../assets/imgs/indicateur.png") }}
onPress={handlePressItem}
/>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another large commented code block should be removed to keep the codebase clean.

<GoalsStatusNoData goalsData={goalsData} date={date} onPress={handlePressItem} />
</View>
) : (
<View />
)} */}
{canEdit(date) && (
<TouchableOpacity className="rounded-2xl border border-gray-500 flex-col my-4 p-6" onPress={() => handlePressItem({ editingSurvey: true })}>
<View className="mb-4 flex-row justify-between">
<Text className={mergeClassNames(typography.textMdBold, "text-cnam-primary-950 capitalize")}>{formatRelativeDate(date)}</Text>
<ArrowIcon />
</View>
<View className="flex-row items-center">
<BasicIcon
color={TW_COLORS.CNAM_CYAN_50_LIGHTEN_90}
borderColor={TW_COLORS.CNAM_PRIMARY_500}
iconColor={TW_COLORS.GRAY_950}
icon={"Plus"}
borderWidth={1}
iconContainerStyle={{ marginRight: 0 }}
iconWidth={32}
iconHeight={32}
/>
<View className="ml-2 p-2 flex-1">
<Text className={mergeClassNames(typography.textSmMedium, "text-cnam-primary-950")}>Complétez l'observation</Text>
</View>
</View>
</TouchableOpacity>
)}
</>
);
}
};
1 change: 1 addition & 0 deletions app/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ export const TW_COLORS = {
CNAM_CYAN_0: "#00A5DF",
CNAM_PRIMARY_900: "#134449",
CNAM_PRIMARY_700: "#518B9A",
CNAM_PRIMARY_500: "#65AEC1",
BEIGE: "#FCEBD9",
GRAY_800: "#4A5D5F",
GRAY_700: "#617778",
Expand Down
1 change: 1 addition & 0 deletions app/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ module.exports = {
800: "#4A5D5F",
700: "#617778",
600: "#799092",
500: "#92A9AB",
400: "#ACC3C5",
300: "#C7DDDE",
200: "#E3F6F8",
Expand Down
Loading