fix(dae): on alert modal

This commit is contained in:
devthejo 2026-03-08 18:26:53 +01:00
parent 93ba79bfa7
commit cf00b5cea4
No known key found for this signature in database
GPG key ID: 00CCA7A92B1D5351
4 changed files with 54 additions and 28 deletions

View file

@ -15,16 +15,18 @@ export default function DaeSuggestModal() {
const styles = useMemo( const styles = useMemo(
() => ({ () => ({
container: { backgroundColor: colors.surface, padding: 20 }, container: {
backgroundColor: colors.surface,
padding: 20,
marginHorizontal: 16,
borderRadius: 12,
},
title: { fontSize: 20, fontWeight: "bold" }, title: { fontSize: 20, fontWeight: "bold" },
paragraph: { marginTop: 10, fontSize: 16 }, paragraph: { marginTop: 10, fontSize: 16 },
actionsRow: { actionsColumn: {
marginTop: 18, marginTop: 18,
flexDirection: "row", gap: 10,
justifyContent: "space-between",
}, },
action: { flex: 1 },
actionLeft: { marginRight: 12 },
}), }),
[colors.surface], [colors.surface],
); );
@ -52,18 +54,14 @@ export default function DaeSuggestModal() {
> >
<Text style={styles.title}>Défibrillateur à proximité</Text> <Text style={styles.title}>Défibrillateur à proximité</Text>
<Text style={styles.paragraph}> <Text style={styles.paragraph}>
Votre alerte semble concerner un malaise grave / arrêt cardiaque. En cas d'arrêt cardiaque, un défibrillateur (DAE) à proximité peut
Recherchez rapidement un défibrillateur (DAE) près de vous. sauver une vie.
</Text> </Text>
<View style={styles.actionsRow}> <View style={styles.actionsColumn}>
<Button <Button mode="contained" onPress={goToDaeList}>
style={[styles.action, styles.actionLeft]}
mode="contained"
onPress={goToDaeList}
>
Chercher un défibrillateur Chercher un défibrillateur
</Button> </Button>
<Button style={styles.action} mode="outlined" onPress={dismiss}> <Button mode="outlined" onPress={dismiss}>
Non merci Non merci
</Button> </Button>
</View> </View>

View file

@ -16,6 +16,7 @@ import { getCurrentLocation } from "~/location";
import useSendAlertSMSToEmergency from "~/hooks/useSendAlertSMSToEmergency"; import useSendAlertSMSToEmergency from "~/hooks/useSendAlertSMSToEmergency";
import alertsList from "~/misc/alertsList";
import subjectSuggestsDefib from "~/utils/dae/subjectSuggestsDefib"; import subjectSuggestsDefib from "~/utils/dae/subjectSuggestsDefib";
import { SEND_ALERT_MUTATION } from "./gql"; import { SEND_ALERT_MUTATION } from "./gql";
@ -84,6 +85,13 @@ async function onSubmit(args, context) {
speed, speed,
}; };
// DAE suggest modal — must run before network call so it works offline.
// Show on red alerts unconditionally, or when cardiac keywords are detected.
const matchingAlert = alertsList.find((a) => a.title === subject);
if (level === "red" || subjectSuggestsDefib(subject, matchingAlert?.desc)) {
defibsActions.setShowDaeSuggestModal(true);
}
const { userId, deviceId } = getSessionState(); const { userId, deviceId } = getSessionState();
const createdAt = new Date().toISOString(); const createdAt = new Date().toISOString();
@ -133,12 +141,6 @@ async function onSubmit(args, context) {
alertActions.setNavAlertCur({ alert }); alertActions.setNavAlertCur({ alert });
// Task 9 (DAE v1): keyword detection based on subject only.
// Must be independent of network; we trigger purely from the subject and persist state in store.
if (subjectSuggestsDefib(subject)) {
defibsActions.setShowDaeSuggestModal(true);
}
navigation.navigate("Main", { navigation.navigate("Main", {
screen: "AlertCur", screen: "AlertCur",
params: { params: {

View file

@ -59,13 +59,14 @@ const DEFIB_SUGGESTION_REGEXES = [
/\brespire\s+plus\b/, /\brespire\s+plus\b/,
]; ];
export function subjectSuggestsDefib(subject) { export function subjectSuggestsDefib(...texts) {
const text = normalizeSubjectText(subject); return texts.some((input) => {
const text = normalizeSubjectText(input);
if (!text) { if (!text) {
return false; return false;
} }
return DEFIB_SUGGESTION_REGEXES.some((re) => re.test(text)); return DEFIB_SUGGESTION_REGEXES.some((re) => re.test(text));
});
} }
export const __private__ = { export const __private__ = {

View file

@ -37,4 +37,29 @@ describe("dae/subjectSuggestsDefib", () => {
expect(subjectSuggestsDefib("mal au dos")).toBe(false); expect(subjectSuggestsDefib("mal au dos")).toBe(false);
expect(subjectSuggestsDefib("panne de voiture")).toBe(false); expect(subjectSuggestsDefib("panne de voiture")).toBe(false);
}); });
test("matches when keyword is in second argument (description)", () => {
expect(
subjectSuggestsDefib(
"urgence médicale mortelle",
"crise cardiaque, attaque cérébrale, hémorragie importante, blessure grave",
),
).toBe(true);
});
test("matches when keyword is only in subject, not description", () => {
expect(subjectSuggestsDefib("arrêt cardiaque", "some other desc")).toBe(
true,
);
});
test("does not match when neither subject nor description has keywords", () => {
expect(subjectSuggestsDefib("agression", "violence physique")).toBe(false);
});
test("handles null/undefined in multi-arg", () => {
expect(subjectSuggestsDefib(null, "cardiaque")).toBe(true);
expect(subjectSuggestsDefib("cardiaque", undefined)).toBe(true);
expect(subjectSuggestsDefib(null, undefined)).toBe(false);
});
}); });