diff --git a/.vscode/settings.json b/.vscode/settings.json index b6116f70d..1e546aacc 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,10 +2,10 @@ "eslint.workingDirectories": ["front", "back", "lib"], "editor.formatOnSave": true, "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "eslint.validate": ["javascript", "typescript"], "[html]": { "editor.formatOnSave": false - }, + } } diff --git a/front/.env.example b/front/.env.example index e78dc4d87..f97d3de24 100644 --- a/front/.env.example +++ b/front/.env.example @@ -10,7 +10,7 @@ MATOMO_URL=https://matomo.fabrique.social.gouv.fr/ PLAY_STORE_API_KEY= SENTRY_DSN=https://5dbac413000f4a43a073841acebc82f5@sentry.fabrique.social.gouv.fr/55 SENTRY_ENABLED=true -SENTRY_AUTH_TOKEN=18a8f019ec4340888a656cef36f381544b0bb2b7096a45b0b4366b1bd62d0dfd +SENTRY_AUTH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx GOOGLE_MAPS_API_KEY= DEEPLINK_DOMAIN=1000jours.fabrique.social.gouv.fr DEEPLINK_PATH=app-millejours diff --git a/front/src/components/zeroAccident/zeroAccidentBanner.component.tsx b/front/src/components/zeroAccident/zeroAccidentBanner.component.tsx new file mode 100644 index 000000000..fc2f72f6e --- /dev/null +++ b/front/src/components/zeroAccident/zeroAccidentBanner.component.tsx @@ -0,0 +1,82 @@ +import type { FC } from "react"; +import * as React from "react"; +import { Linking, StyleSheet } from "react-native"; + +import { Links } from "../../constants"; +import { PLATFORM_IS_ANDROID } from "../../constants/platform.constants"; +import { Colors, Margins, Paddings, Sizes } from "../../styles"; +import type { TrackerEvent } from "../../type"; +import { TrackerUtils } from "../../utils"; +import { CommonText, CustomButton, View } from "../baseComponents"; +import TrackerHandler from "../tracker/trackerHandler.component"; + +interface Props { + title: string; + buttonTitle: string; + fromPage: string; +} + +const ZeroAccidentBanner: FC = ({ title, buttonTitle, fromPage }) => { + const [trackerEventObject, setTrackerEventObject] = + React.useState(); + + const goToStore = React.useCallback(() => { + const storeUrl = PLATFORM_IS_ANDROID + ? Links.zeroAccidentAppUrlAndroid + : Links.zeroAccidentHttpsiOSAppUrl; + + setTrackerEventObject({ + action: TrackerUtils.TrackingEvent.ZERO_ACCIDENT, + name: `${TrackerUtils.TrackingEvent.ZERO_ACCIDENT} - ${ + PLATFORM_IS_ANDROID ? "Android" : "iOS" + } (${fromPage})`, + }); + void Linking.openURL(storeUrl); + }, [fromPage]); + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + return ( + <> + + + {title} + + + + ); +}; + +const styles = StyleSheet.create({ + bannerButtonTitle: { + fontSize: Sizes.sm, + textTransform: "uppercase", + }, + bannerDescription: { + color: Colors.commonText, + marginVertical: Margins.light, + }, + bannerTitle: { + color: Colors.primaryBlueDark, + fontSize: Sizes.sm, + lineHeight: Sizes.lg, + }, + container: { + backgroundColor: Colors.primaryBlueLight, + borderLeftColor: Colors.primaryBlueDark, + borderLeftWidth: 3, + marginBottom: Paddings.light, + marginVertical: Paddings.default, + padding: Paddings.default, + }, + header: { + paddingBottom: Paddings.larger, + }, + mainContainer: { + backgroundColor: Colors.white, + flex: 1, + paddingHorizontal: Paddings.larger, + paddingVertical: Paddings.default, + }, +}); + +export default ZeroAccidentBanner; diff --git a/front/src/constants/Labels.ts b/front/src/constants/Labels.ts index 2d99d6164..ec63019f9 100644 --- a/front/src/constants/Labels.ts +++ b/front/src/constants/Labels.ts @@ -832,4 +832,16 @@ export default { toAccessClickHere: "Pour y accéder, vous pouvez cliquer ici : ", version: "v.", warning: "Attention", + zeroAccident: { + article: { + buttonTitle: "Télécharger", + title: + "Vous êtes parent d’un jeune enfant et vous souhaitez en apprendre plus sur les risques d’accidents à la maison? Téléchargez le jeu Zéro accident: un jeu d’enfant et déjouez les chutes, les intoxications, les suffocations et la noyade!", + }, + survey: { + buttonTitle: "Jouer", + title: + "Tester ses connaissances en prévention des accidents de la vie courante chez les enfants entre 0 et 4 ans.", + }, + }, }; diff --git a/front/src/constants/databaseQueries/configDbQueries.constants.ts b/front/src/constants/databaseQueries/configDbQueries.constants.ts index 766597578..96572bf30 100644 --- a/front/src/constants/databaseQueries/configDbQueries.constants.ts +++ b/front/src/constants/databaseQueries/configDbQueries.constants.ts @@ -1,8 +1,16 @@ export const CONFIG_GET_ALL = ` - query GetLastAppVersion { + query GetConfig { config { lastAppVersionNumber news } } `; + +export const CONFIG_ZERO_ACCIDENT = ` + query GetConfig { + config { + activationZeroAccident + } + } +`; diff --git a/front/src/constants/databaseQueries/homeDbQueries.constants.ts b/front/src/constants/databaseQueries/homeDbQueries.constants.ts index 75f841eec..31da2195b 100644 --- a/front/src/constants/databaseQueries/homeDbQueries.constants.ts +++ b/front/src/constants/databaseQueries/homeDbQueries.constants.ts @@ -151,6 +151,7 @@ export const ARTICLE_DETAILS_WITH_ID = ( id } handicap + zeroAccident: zero_accident } } `; diff --git a/front/src/constants/links.constants.ts b/front/src/constants/links.constants.ts index 3dd68479f..37a1af191 100644 --- a/front/src/constants/links.constants.ts +++ b/front/src/constants/links.constants.ts @@ -9,3 +9,10 @@ export const httpsiOSAppUrl = "https://apps.apple.com/us/app/1000-premiers-jours/id1573729958"; export const tndReviewUrl = "https://jedonnemonavis.numerique.gouv.fr/Demarches/3589?&view-mode=formulaire-avis&nd_source=button&key=8681b4521eb48f91024faeb86f3d53f4"; + +export const zeroAccidentAppUrlAndroid = + "https://play.google.com/store/apps/details?id=com.fabrique.millejours"; +export const zeroAccidentAppUrliOS = + "itms-apps://itunes.com/app/1000-premiers-jours/id1573729958"; +export const zeroAccidentHttpsiOSAppUrl = + "https://apps.apple.com/us/app/1000-premiers-jours/id1573729958"; diff --git a/front/src/screens/articles/articleDetail.component.tsx b/front/src/screens/articles/articleDetail.component.tsx index 2b5ae60ea..f29a56398 100644 --- a/front/src/screens/articles/articleDetail.component.tsx +++ b/front/src/screens/articles/articleDetail.component.tsx @@ -40,7 +40,9 @@ import { View, } from "../../components/baseComponents"; import TrackerHandler from "../../components/tracker/trackerHandler.component"; +import ZeroAccidentBanner from "../../components/zeroAccident/zeroAccidentBanner.component"; import { + ConfigQueries, FetchPoliciesConstants, HomeDbQueries, Labels, @@ -54,6 +56,7 @@ import type { Article, ArticleInShortItem, ArticleLink, + Config, Step, TabHomeParamList, } from "../../types"; @@ -105,6 +108,15 @@ const ArticleDetail: FC = ({ const [articleHasBeenRead, setArticleHasBeenRead] = useState(false); const MIN_RATIO_FOR_HAS_BEEN_READ = 0.55; + const [config, setConfig] = React.useState(null); + + const handleConfig = useCallback((data: unknown) => { + const result = data ? (data as { config: Config }) : undefined; + if (result?.config) { + setConfig(result.config); + } + }, []); + useEffect(() => { const checkArticleRead = async () => { if (articleId) { @@ -321,6 +333,22 @@ const ArticleDetail: FC = ({ html={currentArticle.texte2} screenWidth={articleWidth} /> + + {config?.activationZeroAccident && + currentArticle.zeroAccident && ( + + )} { + const [config, setConfig] = React.useState(null); + + const handleConfig = useCallback((data: unknown) => { + const result = data ? (data as { config: Config }) : undefined; + if (result?.config) { + setConfig(result.config); + } + }, []); + const openEpdsSurvey = useCallback(() => { const EPDS_WIDGET_SOURCE = "1000j-application"; - void LinkingUtils.openWebsite( `${process.env.EPDS_WIDGET_URL}/?source=${EPDS_WIDGET_SOURCE}`, false ); }, []); + const openTndSurvey = useCallback(() => { void RootNavigation.navigate("tndSurvey"); }, []); @@ -54,6 +66,21 @@ const TabSurveysScreen: FC = () => { description={Labels.surveys.description} style={styles.header} /> + + {config?.activationZeroAccident && ( + + )} {surveysBanner.map((survey, index) => ( {survey.title} diff --git a/front/src/types.tsx b/front/src/types.tsx index 1c1e04797..f0dd44e38 100644 --- a/front/src/types.tsx +++ b/front/src/types.tsx @@ -174,6 +174,7 @@ export type Article = { // eslint-disable-next-line @typescript-eslint/naming-convention cartographie_pois_types?: PoiType[]; handicap?: boolean; + zeroAccident?: boolean; }; export type ArticleInShortItem = { @@ -274,6 +275,7 @@ export type ArticleListHeaderParams = { export type Config = { lastAppVersionNumber: string | null; news?: string; + activationZeroAccident?: boolean; }; export type MarkedDatesType = Record; diff --git a/front/src/utils/tracking/tracker.util.ts b/front/src/utils/tracking/tracker.util.ts index ed7c6a536..45eb62c02 100644 --- a/front/src/utils/tracking/tracker.util.ts +++ b/front/src/utils/tracking/tracker.util.ts @@ -43,6 +43,7 @@ export enum TrackingEvent { NOTIFICATIONS_DISABLED = "Notifications désactivées", RESSOURCES = "Ressources", SURVEYS = "Évaluations", + ZERO_ACCIDENT = "Zero Accident", } export const matomoInstance = async (): Promise => { diff --git a/front/tsconfig.json b/front/tsconfig.json index 124325561..02aff71b6 100644 --- a/front/tsconfig.json +++ b/front/tsconfig.json @@ -2,10 +2,7 @@ "compilerOptions": { "allowSyntheticDefaultImports": true, "jsx": "react-native", - "lib": [ - "dom", - "esnext" - ], + "lib": ["dom", "esnext"], "moduleResolution": "node", "noEmit": true, "skipLibCheck": true,