diff --git a/package.json b/package.json index 98bf7d7..371c097 100644 --- a/package.json +++ b/package.json @@ -22,11 +22,13 @@ "@react-navigation/native-stack": "^6.5.2", "@types/react-native-vector-icons": "^6.4.10", "axios": "^0.26.1", + "lottie-react-native": "^5.1.3", "react": "17.0.2", "react-native": "0.67.3", "react-native-audio-recorder-player": "^3.4.0", "react-native-bootsplash": "^4.1.5", "react-native-config": "^1.4.5", + "react-native-fade-loading": "^0.1.3", "react-native-fast-image": "^8.5.11", "react-native-image-modal": "^2.0.4", "react-native-image-picker": "^4.7.3", diff --git a/src/assets/accessibilityStrings.ts b/src/assets/accessibilityStrings.ts index 6f164d4..8bf1466 100644 --- a/src/assets/accessibilityStrings.ts +++ b/src/assets/accessibilityStrings.ts @@ -12,10 +12,7 @@ const ACCESSIBILITY_STRINGS = { helpButtonHint: 'Naar de helppagina', helpTitle: 'Helppagina', - contactTitle: 'Contactgegevens', contactSubtitle: 'Bezoek- en postadres', - contactExtraInfo: - 'Stichting Accessibility is gevestigd in het bedrijfsverzamelgebouw de Krammstate op een paar minuten lopen van Station Utrecht Overvecht.', contactExtraInfoLabel: 'Extra informatie voor bezoek aan Stichting Accessibility: Stichting Accessibility is gevestigd in het bedrijfsverzamelgebouw de Krammstate op een paar minuten lopen van Station Utrecht Overvecht.', contactStreet: 'Christiaan Krammlaan 2', @@ -23,11 +20,10 @@ const ACCESSIBILITY_STRINGS = { contactCity: 'Utrecht', contactPhone: '+31 30 239 82 70', contactEmail: 'info@accessibility.nl', - contactSendEmail: 'Stuur een e-mail', - contactSendEmailHint: + contactSendEmailLabel: 'Stuur een e-mail naar Stichting Accessibility via een beschikbare mail app', - contactCallPhone: 'Bellen', - contactCallPhoneHint: 'Bel naar het bedrijf', + contactCallPhoneLabel: 'Bel naar het bedrijf', + contactLogo: "Logo van Stichting Accessibility", backButton: 'Terug knop', backButtonHint: 'Terug naar', diff --git a/src/assets/animations/loading.json b/src/assets/animations/loading.json new file mode 100644 index 0000000..a39d143 --- /dev/null +++ b/src/assets/animations/loading.json @@ -0,0 +1,213 @@ +{ + "v": "5.8.1", + "fr": 30, + "ip": 0, + "op": 60, + "w": 300, + "h": 300, + "nm": "loading_6", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 1, + "ty": 4, + "nm": "Shape Layer 2", + "sr": 1, + "ks": { + "o": { "a": 0, "k": 100, "ix": 11 }, + "r": { + "a": 1, + "k": [ + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 0, + "s": [0] + }, + { "t": 60, "s": [360] } + ], + "ix": 10 + }, + "p": { "a": 0, "k": [150.00000000000003, 150.00000000000003, 0], "ix": 2, "l": 2 }, + "a": { "a": 0, "k": [0, 0, 0], "ix": 1, "l": 2 }, + "s": { "a": 0, "k": [30.000000000000004, 30.000000000000004, 100], "ix": 6, "l": 2 } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { "a": 0, "k": [300, 300], "ix": 2 }, + "p": { "a": 0, "k": [0, 0], "ix": 3 }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [0.22745098039215686, 0.6627450980392157, 0.8627450980392157, 1], + "ix": 3 + }, + "o": { "a": 0, "k": 100, "ix": 4 }, + "w": { "a": 0, "k": 50, "ix": 5 }, + "lc": 2, + "lj": 1, + "ml": 4, + "bm": 0, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + }, + { + "ty": "tm", + "s": { + "a": 1, + "k": [ + { + "i": { "x": [0.667], "y": [1] }, + "o": { "x": [0.333], "y": [0] }, + "t": 10, + "s": [0] + }, + { "t": 60, "s": [99] } + ], + "ix": 1 + }, + "e": { + "a": 1, + "k": [ + { + "i": { "x": [0.667], "y": [1] }, + "o": { "x": [0.333], "y": [0] }, + "t": 0, + "s": [1] + }, + { "t": 50, "s": [100] } + ], + "ix": 2 + }, + "o": { + "a": 1, + "k": [ + { + "i": { "x": [0.833], "y": [0.833] }, + "o": { "x": [0.167], "y": [0.167] }, + "t": 0, + "s": [0] + }, + { "t": 60, "s": [3] } + ], + "ix": 3 + }, + "m": 1, + "ix": 2, + "nm": "Trim Paths 1", + "mn": "ADBE Vector Filter - Trim", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + }, + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "Shape Layer 1", + "sr": 1, + "ks": { + "o": { "a": 0, "k": 30, "ix": 11 }, + "r": { "a": 0, "k": 0, "ix": 10 }, + "p": { "a": 0, "k": [150.00000000000003, 150.00000000000003, 0], "ix": 2, "l": 2 }, + "a": { "a": 0, "k": [0, 0, 0], "ix": 1, "l": 2 }, + "s": { "a": 0, "k": [30.000000000000004, 30.000000000000004, 100], "ix": 6, "l": 2 } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { "a": 0, "k": [300, 300], "ix": 2 }, + "p": { "a": 0, "k": [0, 0], "ix": 3 }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse", + "hd": false + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [0.6666666666666666, 0.8431372549019608, 0.9215686274509803, 1], + "ix": 3 + }, + "o": { "a": 0, "k": 100, "ix": 4 }, + "w": { "a": 0, "k": 50, "ix": 5 }, + "lc": 1, + "lj": 1, + "ml": 4, + "bm": 0, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke", + "hd": false + }, + { + "ty": "tr", + "p": { "a": 0, "k": [0, 0], "ix": 2 }, + "a": { "a": 0, "k": [0, 0], "ix": 1 }, + "s": { "a": 0, "k": [100, 100], "ix": 3 }, + "r": { "a": 0, "k": 0, "ix": 6 }, + "o": { "a": 0, "k": 100, "ix": 7 }, + "sk": { "a": 0, "k": 0, "ix": 4 }, + "sa": { "a": 0, "k": 0, "ix": 5 }, + "nm": "Transform" + } + ], + "nm": "Ellipse 1", + "np": 3, + "cix": 2, + "bm": 0, + "ix": 1, + "mn": "ADBE Vector Group", + "hd": false + } + ], + "ip": 0, + "op": 300, + "st": 0, + "bm": 0 + } + ], + "markers": [] +} diff --git a/src/components/question/QuestionList.tsx b/src/components/question/QuestionList.tsx index c021bb8..e7f1688 100644 --- a/src/components/question/QuestionList.tsx +++ b/src/components/question/QuestionList.tsx @@ -12,6 +12,7 @@ const QuestionList = (props: { questions: Question[] }) => { const questions: Question[] = props.questions; const navigation = useNavigation(); const isFocused = useIsFocused(); + return ( <> {questions?.length === 0 && ( diff --git a/src/components/utility/FetchQuestionnaire.tsx b/src/components/utility/FetchQuestionnaire.tsx index b085dfc..51b2345 100644 --- a/src/components/utility/FetchQuestionnaire.tsx +++ b/src/components/utility/FetchQuestionnaire.tsx @@ -18,6 +18,11 @@ export async function fetchQuestionnaire(code: string, navigation: any) { name: questionnaire.title, }), ]); + + await ParticipantCode.setCurrentQuestionaireTitle(questionnaire.title); + await ParticipantCode.setCurrentQuestionaireHelp( + questionnaire.help ? questionnaire.help : '' + ); // @ts-ignore next-line navigation.navigate('Questionnaire', { title: questionnaire.title, diff --git a/src/data/localStorage/ParticipantCode.ts b/src/data/localStorage/ParticipantCode.ts index b3fd1f3..69e2693 100644 --- a/src/data/localStorage/ParticipantCode.ts +++ b/src/data/localStorage/ParticipantCode.ts @@ -11,7 +11,28 @@ class ParticipantCode { } public static async loadCurrentParticipantCodeFromLocalStorage() { - return await AsyncStorage.getItem('ParticipantCode'); + return AsyncStorage.getItem('ParticipantCode'); + } + + public static async setCurrentQuestionaireHelp(help: string) { + await AsyncStorage.setItem('CurrentQuestionaireHelp', JSON.stringify(help)); + } + + public static async getCurrentQuestionaireHelp(): Promise { + return AsyncStorage.getItem('CurrentQuestionaireHelp'); + } + + static async setCurrentQuestionaireTitle(title: string) { + await AsyncStorage.setItem('CurrentQuestionaireTitle', JSON.stringify(title)); + } + + static async getCurrentQuestionaireTitle(): Promise { + return AsyncStorage.getItem('CurrentQuestionaireTitle'); + } + + public static async getCurrentQuestionaireExtraData() { + let q = await AsyncStorage.getItem('CurrentQuestionaire'); + return typeof q === 'string' ? JSON.parse(q) : null; } private static questionnaireExists(questionnaires: QuestionnaireDisplay[], code: string) { diff --git a/src/data/localStorage/Queue.ts b/src/data/localStorage/Queue.ts index 885041c..b184731 100644 --- a/src/data/localStorage/Queue.ts +++ b/src/data/localStorage/Queue.ts @@ -27,6 +27,10 @@ class TempStorage { return TempStorage.instance; } + public clearStorage() { + AsyncStorage.clear(); + } + private loadQueueFromLocalStorage() { AsyncStorage.getItem('Queue') .then((result: string | null) => { diff --git a/src/models/Questionnaire.ts b/src/models/Questionnaire.ts index bfb6b33..d5c9d3c 100644 --- a/src/models/Questionnaire.ts +++ b/src/models/Questionnaire.ts @@ -7,6 +7,7 @@ export class Questionnaire { participantCode: string; description?: string; instructions?: string; + help?: string; teachableMachineLink?: string; sections?: Section[]; @@ -17,6 +18,7 @@ export class Questionnaire { participantCode: string, description?: string, instructions?: string, + help?: string, teachableMachineLink?: string, sections?: Section[] ) { @@ -26,6 +28,7 @@ export class Questionnaire { this.participantCode = participantCode; this.description = description; this.instructions = instructions; + this.help = help; this.teachableMachineLink = teachableMachineLink; this.sections = sections; } diff --git a/src/screens/HelpScreen.tsx b/src/screens/HelpScreen.tsx index 7f06010..5dd0da4 100644 --- a/src/screens/HelpScreen.tsx +++ b/src/screens/HelpScreen.tsx @@ -1,9 +1,63 @@ -import React from 'react'; -import { Image, Linking, Platform, StyleSheet, Text, TouchableOpacity, View } from 'react-native'; -import MasterContainer from '../components/generic/MasterContainer'; +import React, { useState } from 'react'; +import { + Image, + Linking, + Platform, + ScrollView, + StyleSheet, + Text, + TouchableOpacity, + View, +} from 'react-native'; import FONTS from '../assets/fonts'; import COLORS from '../assets/colors'; import ACC_STRS from '../assets/accessibilityStrings'; +import { useFocusEffect } from '@react-navigation/native'; +import ParticipantCode from '../data/localStorage/ParticipantCode'; +import LottieView from 'lottie-react-native'; +import loadingScreen from '../assets/animations/loading.json'; + +let helptext: string = ''; +let customTitle: string = ''; + +const HelpScreen = () => { + const [hasHelpPage, setHasHelpPage] = useState(false); + const [loading, setLoading] = useState(false); + + useFocusEffect( + React.useCallback(() => { + setLoading(true); + Promise.all([ + ParticipantCode.getCurrentQuestionaireTitle().then((title) => { + if (title) { + setHasHelpPage(true); + customTitle = `Hulp bij ${title.slice(title.indexOf('"') + 1, title.lastIndexOf('"'))}`; + } + }), + ParticipantCode.getCurrentQuestionaireHelp().then((h) => { + if (h) { + if (h == '' || h == '""') h = 'Geen helptekst beschikbaar.'; + helptext = h.slice(h.indexOf('"') + 1, h.lastIndexOf('"')); + } + }), + ]) + .then(() => setLoading(false)) + .catch((c) => console.log(c)); + }, []) + ); + + const determineHelpScreen = () => { + if (!loading && hasHelpPage) { + return HelpPage(); + } else if (!loading) { + return AccessibilityScreen(true); + } else { + return LoadingComponent(); + } + }; + + return <>{determineHelpScreen()}; +}; const createText = () => { return data.map((element, index) => { @@ -15,7 +69,6 @@ const createText = () => { }); }; -// TODO fill phoneNumber based on data of specific cliƫnt const phoneCall = () => { let phoneNumber = ACC_STRS.contactPhone; @@ -28,17 +81,38 @@ const phoneCall = () => { Linking.openURL(phoneNumber); }; -const HelpScreen = () => { +const LoadingComponent = () => { return ( - - + + + + ); +}; + +function HelpPage() { + return ( + + {OptionalCompanyHelp()} + {AccessibilityScreen(false)} + + ); +} + +function AccessibilityScreen(image: boolean) { + return ( + + {image && ( + + )} - {ACC_STRS.contactTitle} - {/*Creating text elements based on data*/} + Contactgegevens Stichting Accessibility {createText()} { > - {ACC_STRS.contactSendEmail} + Stuur een e-mail - {ACC_STRS.contactCallPhone} + Bellen @@ -72,15 +146,43 @@ const HelpScreen = () => { accessibilityLabel={ACC_STRS.contactExtraInfoLabel} style={styles.contactText} > - {ACC_STRS.contactExtraInfo} + Stichting Accessibility is gevestigd in het bedrijfsverzamelgebouw de Krammstate op een paar minuten lopen van Station Utrecht Overvecht. - + ); -}; +} + +function OptionalCompanyHelp() { + return ( + <> + + {customTitle} + {helptext} + + + + ); +} const styles = StyleSheet.create({ + main: { + flex: 1, + }, + empty: { + padding: 20, + }, + tabScreen: { + flex: 1, + marginTop: 20, + paddingBottom: 20, + }, + accessibilityScreen: { + flex: 2, + }, logo: { + margin: 0, + padding: 0, width: '100%', height: 100, resizeMode: 'contain', @@ -105,7 +207,7 @@ const styles = StyleSheet.create({ }, contactInfo: { position: 'relative', - left: -30, + left: -20, backgroundColor: COLORS.gray, paddingLeft: 10, padding: 20, @@ -143,10 +245,6 @@ const styles = StyleSheet.create({ }); const data = [ - // { - // text: ACC_STRS.contactSubtitle, - // style: styles.contactTitle, - // }, { text: ACC_STRS.contactStreet, style: styles.contactText, @@ -155,22 +253,6 @@ const data = [ text: `${ACC_STRS.contactPostalCode} ${ACC_STRS.contactCity}`, style: styles.contactText, }, - // { - // text: ACC_STRS.phone, - // style: styles.contactTitle, - // }, - // { - // text: ACC_STRS.contactPhone, - // style: styles.contactText, - // }, - // { - // text: ACC_STRS.email, - // style: styles.contactTitle, - // }, - // { - // text: ACC_STRS.contactEmail, - // style: styles.contactText, - // }, ]; export default HelpScreen; diff --git a/yarn.lock b/yarn.lock index b827e98..61becb8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2872,6 +2872,11 @@ decode-uri-component@^0.2.0: resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +dedent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb" + integrity sha512-cSfRWjXJtZQeRuZGVvDrJroCR5V2UvBNUMHsPCdNYzuAG8b9V8aAy3KUcdQrGQPXs17Y+ojbPh1aOCplg9YR9g== + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" @@ -4008,7 +4013,7 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -invariant@^2.2.4: +invariant@^2.2.2, invariant@^2.2.4: version "2.2.4" resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -5055,6 +5060,14 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lottie-react-native@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/lottie-react-native/-/lottie-react-native-5.1.3.tgz#6f5d0867bb762cee1dfc0613845d50c73e138ddd" + integrity sha512-Ho+oM+D3if85I2EBn8c17tcg7pc880Sp/DOeNW5aWiNtlCJKX/kmlhoM19NLqjzkHEm96fTkTcTy82ZwYU3Kbg== + dependencies: + invariant "^2.2.2" + react-native-safe-modules "^1.0.3" + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" @@ -6175,6 +6188,11 @@ react-native-config@^1.4.5: resolved "https://registry.npmjs.org/react-native-config/-/react-native-config-1.4.5.tgz" integrity sha512-5oiAsoW88SOYDg/0cleJ2vJDqv98FJUbFQYEnH4sdMtEn3AAT3lb7BkTGW8HO/t3Vk9VOruwxUUnO4tzuxzCsw== +react-native-fade-loading@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/react-native-fade-loading/-/react-native-fade-loading-0.1.3.tgz#2a5e9d3e5d73c68a389a03502f5a17f2107ea1c6" + integrity sha512-EIv4IRrovmLGcdMmXVczyRlfcRVythwyls9yohbqhXtc4n+V8rL9Tb0TM01PV5+opA+bot+yZn3jpv+EKqstHw== + react-native-fast-image@^8.5.11: version "8.5.11" resolved "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-8.5.11.tgz" @@ -6207,6 +6225,13 @@ react-native-safe-area-context@^4.2.4: resolved "https://registry.npmjs.org/react-native-safe-area-context/-/react-native-safe-area-context-4.2.4.tgz" integrity sha512-OOX+W2G4YYufvryonn6Kw6YnyT8ZThkxPHZBD04NLHaZmicUaaDVII/PZ3M5fD1o5N62+T+8K4bCS5Un2ggvkA== +react-native-safe-modules@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/react-native-safe-modules/-/react-native-safe-modules-1.0.3.tgz#f5f29bb9d09d17581193843d4173ad3054f74890" + integrity sha512-DUxti4Z+AgJ/ZsO5U7p3uSCUBko8JT8GvFlCeOXk9bMd+4qjpoDvMYpfbixXKgL88M+HwmU/KI1YFN6gsQZyBA== + dependencies: + dedent "^0.6.0" + react-native-screens@^3.13.1: version "3.13.1" resolved "https://registry.npmjs.org/react-native-screens/-/react-native-screens-3.13.1.tgz"