From 9ee5b41921e726b661295c57310018724ad06e43 Mon Sep 17 00:00:00 2001
From: deepakglobant <123438709+deepakglobant@users.noreply.github.com>
Date: Fri, 3 Nov 2023 15:59:29 +0530
Subject: [PATCH] feat: setup feedback package (MN-295) (#601)
---
.babelrc.json | 3 +-
.github/workflows/camera-analyze.yml | 2 +-
.github/workflows/corejs-analyze.yml | 2 +-
.github/workflows/feedback-analyze.yml | 30 ++++
.github/workflows/sights-analyze.yml | 2 +-
.github/workflows/toolkit-analyze.yml | 2 +-
.github/workflows/ui-analyze.yml | 2 +-
.github/workflows/visualization-analyze.yml | 2 +-
.github/workflows/website-deploy.yml | 4 +-
metro.config.js | 1 +
package.json | 8 +-
packages/feedback/.editorconfig | 8 +
packages/feedback/.eslintignore | 3 +
packages/feedback/.eslintrc.json | 3 +
packages/feedback/.gitignore | 29 ++++
packages/feedback/.release-it.json | 5 +
packages/feedback/LICENSE | 32 ++++
packages/feedback/README.md | 13 ++
packages/feedback/babel.config.js | 6 +
packages/feedback/bob.config.js | 8 +
packages/feedback/jsconfig.json | 6 +
packages/feedback/package.json | 62 +++++++
.../src/components/BuildQuestion/index.js | 86 ++++++++++
.../src/components/Feedback/Feedback.js | 42 +++++
.../feedback/src/components/Feedback/index.js | 15 ++
.../src/components/common/FreeTextInput.js | 48 ++++++
.../src/components/common/RadioInput.js | 79 +++++++++
.../src/components/common/SelectInput.js | 123 ++++++++++++++
.../src/components/common/TextButton.js | 40 +++++
.../feedback/src/components/common/index.js | 11 ++
packages/feedback/src/components/index.js | 2 +
packages/feedback/src/hooks/index.js | 0
packages/feedback/src/i18n/index.js | 16 ++
packages/feedback/src/i18n/resources/en.js | 5 +
packages/feedback/src/i18n/resources/fr.js | 5 +
packages/feedback/src/i18n/resources/index.js | 6 +
packages/feedback/src/index.js | 2 +
src/config/Navigation.js | 5 +
src/screens/InspectionFeedback/index.js | 104 ++++++++++++
src/screens/InspectionFeedback/styles.js | 3 +
src/screens/index.js | 1 +
src/screens/names.js | 1 +
webpack.config.js | 1 +
website/docs.sidebars.js | 1 +
website/docs/feedback.md | 159 ++++++++++++++++++
yarn.lock | 7 +
46 files changed, 984 insertions(+), 11 deletions(-)
create mode 100644 .github/workflows/feedback-analyze.yml
create mode 100644 packages/feedback/.editorconfig
create mode 100644 packages/feedback/.eslintignore
create mode 100644 packages/feedback/.eslintrc.json
create mode 100644 packages/feedback/.gitignore
create mode 100644 packages/feedback/.release-it.json
create mode 100644 packages/feedback/LICENSE
create mode 100644 packages/feedback/README.md
create mode 100644 packages/feedback/babel.config.js
create mode 100644 packages/feedback/bob.config.js
create mode 100644 packages/feedback/jsconfig.json
create mode 100644 packages/feedback/package.json
create mode 100644 packages/feedback/src/components/BuildQuestion/index.js
create mode 100644 packages/feedback/src/components/Feedback/Feedback.js
create mode 100644 packages/feedback/src/components/Feedback/index.js
create mode 100644 packages/feedback/src/components/common/FreeTextInput.js
create mode 100644 packages/feedback/src/components/common/RadioInput.js
create mode 100644 packages/feedback/src/components/common/SelectInput.js
create mode 100644 packages/feedback/src/components/common/TextButton.js
create mode 100644 packages/feedback/src/components/common/index.js
create mode 100644 packages/feedback/src/components/index.js
create mode 100644 packages/feedback/src/hooks/index.js
create mode 100644 packages/feedback/src/i18n/index.js
create mode 100644 packages/feedback/src/i18n/resources/en.js
create mode 100644 packages/feedback/src/i18n/resources/fr.js
create mode 100644 packages/feedback/src/i18n/resources/index.js
create mode 100644 packages/feedback/src/index.js
create mode 100644 src/screens/InspectionFeedback/index.js
create mode 100644 src/screens/InspectionFeedback/styles.js
create mode 100644 website/docs/feedback.md
diff --git a/.babelrc.json b/.babelrc.json
index 78f204fb8..99517340a 100644
--- a/.babelrc.json
+++ b/.babelrc.json
@@ -19,7 +19,8 @@
"@monkvision/sights": "./packages/sights",
"@monkvision/toolkit": "./packages/toolkit",
"@monkvision/visualization": "./packages/visualization",
- "@monkvision/inspection-report": "./packages/inspection-report"
+ "@monkvision/inspection-report": "./packages/inspection-report",
+ "@monkvision/feedback": "./packages/feedback"
}
}],
["babel-plugin-inline-import", { "extensions": [".svg"] }]
diff --git a/.github/workflows/camera-analyze.yml b/.github/workflows/camera-analyze.yml
index d4f3bbad2..176e132cb 100644
--- a/.github/workflows/camera-analyze.yml
+++ b/.github/workflows/camera-analyze.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
- node-version: '14'
+ node-version: '16'
cache: 'yarn'
- run: cd packages/camera && yarn install
- run: cd packages/camera && yarn lint
diff --git a/.github/workflows/corejs-analyze.yml b/.github/workflows/corejs-analyze.yml
index 462797576..833b8ae7f 100644
--- a/.github/workflows/corejs-analyze.yml
+++ b/.github/workflows/corejs-analyze.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
- node-version: '14'
+ node-version: '16'
cache: 'yarn'
- run: cd packages/corejs && yarn install
- run: cd packages/corejs && yarn lint
diff --git a/.github/workflows/feedback-analyze.yml b/.github/workflows/feedback-analyze.yml
new file mode 100644
index 000000000..f39e1a9ef
--- /dev/null
+++ b/.github/workflows/feedback-analyze.yml
@@ -0,0 +1,30 @@
+name: Check Feedback package
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+
+jobs:
+ analyze:
+ runs-on: ubuntu-latest
+ permissions:
+ actions: read
+ contents: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: [ 'javascript' ]
+
+ steps:
+ - uses: actions/checkout@v2
+ - uses: actions/setup-node@v2
+ with:
+ node-version: '16'
+ cache: 'yarn'
+ - run: cd packages/feedback && yarn install
+ - run: cd packages/feedback && yarn lint
+ - run: cd packages/feedback && yarn run build
diff --git a/.github/workflows/sights-analyze.yml b/.github/workflows/sights-analyze.yml
index 26b4dcf20..e350324b6 100644
--- a/.github/workflows/sights-analyze.yml
+++ b/.github/workflows/sights-analyze.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
- node-version: '14'
+ node-version: '16'
cache: 'yarn'
- run: cd packages/sights && yarn install
- run: cd packages/sights && yarn lint
diff --git a/.github/workflows/toolkit-analyze.yml b/.github/workflows/toolkit-analyze.yml
index 00c196b3f..6678aab86 100644
--- a/.github/workflows/toolkit-analyze.yml
+++ b/.github/workflows/toolkit-analyze.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
- node-version: '14'
+ node-version: '16'
cache: 'yarn'
- run: cd packages/toolkit && yarn install
- run: cd packages/toolkit && yarn lint
diff --git a/.github/workflows/ui-analyze.yml b/.github/workflows/ui-analyze.yml
index 60eefc6a5..2feedc616 100644
--- a/.github/workflows/ui-analyze.yml
+++ b/.github/workflows/ui-analyze.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
- node-version: '14'
+ node-version: '16'
cache: 'yarn'
- run: cd packages/ui && yarn install
- run: cd packages/ui && yarn lint
diff --git a/.github/workflows/visualization-analyze.yml b/.github/workflows/visualization-analyze.yml
index 2031f1d2d..f5e96c698 100644
--- a/.github/workflows/visualization-analyze.yml
+++ b/.github/workflows/visualization-analyze.yml
@@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
- node-version: '14'
+ node-version: '16'
cache: 'yarn'
- run: cd packages/visualization && yarn install
- run: cd packages/visualization && yarn lint
diff --git a/.github/workflows/website-deploy.yml b/.github/workflows/website-deploy.yml
index cd34594c0..fc85359aa 100644
--- a/.github/workflows/website-deploy.yml
+++ b/.github/workflows/website-deploy.yml
@@ -14,7 +14,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
- node-version: "14.x"
+ node-version: "16.x"
- name: Build Packages
run: |
yarn
@@ -36,7 +36,7 @@ jobs:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
- node-version: "14.x"
+ node-version: "16.x"
- uses: webfactory/ssh-agent@v0.5.0
with:
ssh-private-key: ${{ secrets.FUTURA_SECRET }}
diff --git a/metro.config.js b/metro.config.js
index d62bb8feb..8f2da1d2f 100644
--- a/metro.config.js
+++ b/metro.config.js
@@ -13,6 +13,7 @@ config.resolver = {
'@monkvision/toolkit',
'@monkvision/visualization',
'@monkvision/inspection-report',
+ '@monkvision/feedback',
],
};
diff --git a/package.json b/package.json
index a67706be3..0c2dd0b45 100644
--- a/package.json
+++ b/package.json
@@ -17,6 +17,7 @@
"start": "expo start --https",
"start:documentation": "cd website && yarn run docs:start",
"start:report": "cd services/inspection-report && yarn run start",
+ "start:feedback": "cd services/feedback && yarn run start",
"watch:ui": "cd ./packages/ui && yarn watch",
"watch:camera": "cd ./packages/camera && yarn watch",
"watch:visualization": "cd ./packages/visualization && yarn watch",
@@ -24,7 +25,8 @@
"watch:corejs": "cd ./packages/corejs && yarn watch",
"watch:sights": "cd ./packages/sights && yarn watch",
"watch:inspection-report": "cd ./packages/inspection-report && yarn watch",
- "watch:all": "concurrently \"yarn run watch:ui\" \"yarn run watch:toolkit\" \"yarn run watch:visualization\" \"yarn run watch:camera\" \"yarn run watch:corejs\" \"yarn run watch:sights\" \"yarn run watch:inspection-report\"",
+ "watch:feedback": "cd ./packages/feedback && yarn watch",
+ "watch:all": "concurrently \"yarn run watch:ui\" \"yarn run watch:toolkit\" \"yarn run watch:visualization\" \"yarn run watch:camera\" \"yarn run watch:corejs\" \"yarn run watch:sights\" \"yarn run watch:inspection-report\" \"yarn run watch:feedback\"",
"build:ui": "cd ./packages/ui && yarn run build",
"build:camera": "cd ./packages/camera && yarn run build",
"build:visualization": "cd ./packages/visualization && yarn run build",
@@ -32,7 +34,8 @@
"build:corejs": "cd ./packages/corejs && yarn run build",
"build:sights": "cd ./packages/sights && yarn run build",
"build:inspection-report": "cd ./packages/inspection-report && yarn run build",
- "build:all": "concurrently \"yarn run build:ui\" \"yarn run build:toolkit\" \"yarn run build:visualization\" \"yarn run build:camera\" \"yarn run build:corejs\" \"yarn run build:sights\" \"yarn run build:inspection-report\"",
+ "build:all": "concurrently \"yarn run build:ui\" \"yarn run build:toolkit\" \"yarn run build:visualization\" \"yarn run build:camera\" \"yarn run build:corejs\" \"yarn run build:sights\" \"yarn run build:inspection-report\" \"yarn run build:feedback\"",
+ "build:feedback": "cd ./packages/feedback && yarn run build",
"build:android": "expo build:android",
"build:ios": "expo build:ios",
"eject": "expo eject",
@@ -153,6 +156,7 @@
"@monkvision/ui": "*",
"@monkvision/visualization": "*",
"@monkvision/inspection-report": "*",
+ "@monkvision/feedback": "*",
"react-native-svg": "*"
},
"resolutions": {
diff --git a/packages/feedback/.editorconfig b/packages/feedback/.editorconfig
new file mode 100644
index 000000000..73db316c0
--- /dev/null
+++ b/packages/feedback/.editorconfig
@@ -0,0 +1,8 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/packages/feedback/.eslintignore b/packages/feedback/.eslintignore
new file mode 100644
index 000000000..375c30fe5
--- /dev/null
+++ b/packages/feedback/.eslintignore
@@ -0,0 +1,3 @@
+node_modules/
+commonjs/
+module/
diff --git a/packages/feedback/.eslintrc.json b/packages/feedback/.eslintrc.json
new file mode 100644
index 000000000..afd435d3a
--- /dev/null
+++ b/packages/feedback/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "root": false
+}
diff --git a/packages/feedback/.gitignore b/packages/feedback/.gitignore
new file mode 100644
index 000000000..1b8564d22
--- /dev/null
+++ b/packages/feedback/.gitignore
@@ -0,0 +1,29 @@
+# builds
+build/
+lib/
+dist/
+module/
+commonjs/
+typescript/
+web-build/
+
+# deploy
+.env*
+
+# modules
+node_modules/
+coverage/
+.expo/
+.docusaurus/
+
+# logs
+npm-debug.*
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# cache
+.eslintcache
+
+# misc
+.DS_Store
diff --git a/packages/feedback/.release-it.json b/packages/feedback/.release-it.json
new file mode 100644
index 000000000..5854004b4
--- /dev/null
+++ b/packages/feedback/.release-it.json
@@ -0,0 +1,5 @@
+{
+ "hooks": { "after:bump": ["npm run build"] },
+ "git": { "commit": false },
+ "github": { "release": false }
+}
diff --git a/packages/feedback/LICENSE b/packages/feedback/LICENSE
new file mode 100644
index 000000000..a3592ab9e
--- /dev/null
+++ b/packages/feedback/LICENSE
@@ -0,0 +1,32 @@
+The Clear BSD License
+
+Copyright (c) [2022] [Monk](http://monk.ai)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted (subject to the limitations in the disclaimer
+below) provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ * Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
+THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/packages/feedback/README.md b/packages/feedback/README.md
new file mode 100644
index 000000000..5606d3a1c
--- /dev/null
+++ b/packages/feedback/README.md
@@ -0,0 +1,13 @@
+# 👁️🗨️ @monkvision/feedback
+
+[![npm latest package](https://img.shields.io/npm/v/@monkvision/feedback/latest.svg)](https://www.npmjs.com/package/@monkvision/feedback)
+
+```yarn
+yarn add @monkvision/feedback
+```
+
+This project is licensed under the BSD-3-Clause-Clear license. See the [LICENSE](LICENSE) file for more info.
+
+---
+
+![Monk banner](https://raw.githubusercontent.com/monkvision/monkjs/main/assets/banner.png)
diff --git a/packages/feedback/babel.config.js b/packages/feedback/babel.config.js
new file mode 100644
index 000000000..f6d217d38
--- /dev/null
+++ b/packages/feedback/babel.config.js
@@ -0,0 +1,6 @@
+module.exports = (api) => {
+ api.cache(true);
+ return {
+ presets: ['babel-preset-expo'],
+ };
+};
diff --git a/packages/feedback/bob.config.js b/packages/feedback/bob.config.js
new file mode 100644
index 000000000..ac0924a8e
--- /dev/null
+++ b/packages/feedback/bob.config.js
@@ -0,0 +1,8 @@
+module.exports = {
+ source: 'src',
+ output: '.',
+ targets: [
+ ['commonjs', { copyFlow: true }],
+ ['module', { copyFlow: true }],
+ ],
+};
diff --git a/packages/feedback/jsconfig.json b/packages/feedback/jsconfig.json
new file mode 100644
index 000000000..51679b31c
--- /dev/null
+++ b/packages/feedback/jsconfig.json
@@ -0,0 +1,6 @@
+{
+ "compilerOptions": {
+ "baseUrl": "src/",
+ "target": "es2020"
+ }
+}
diff --git a/packages/feedback/package.json b/packages/feedback/package.json
new file mode 100644
index 000000000..8c979f79d
--- /dev/null
+++ b/packages/feedback/package.json
@@ -0,0 +1,62 @@
+{
+ "name": "@monkvision/feedback",
+ "author": "monkvision",
+ "license": "BSD-3-Clause-Clear",
+ "version": "3.8.4",
+ "private": false,
+ "description": "AI-powered vehicle damage detection for React Native",
+ "homepage": "https://github.com/monkvision/monkjs/packages/feedback/#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/monkvision/monkjs.git",
+ "directory": "packages/feedback"
+ },
+ "bugs": {
+ "url": "https://github.com/monkvision/monkjs/issues"
+ },
+ "keywords": [
+ "react native",
+ "inspection report",
+ "native components",
+ "vehicle damage detection"
+ ],
+ "main": "commonjs/index.js",
+ "module": "module/index.js",
+ "react-native": "src/index.js",
+ "files": [
+ "commonjs",
+ "module",
+ "src",
+ ".editorconfig",
+ "LICENSE",
+ "package.json",
+ "README.md"
+ ],
+ "scripts": {
+ "watch": "watch 'yarn run build' src",
+ "lint": "eslint src --cache",
+ "lint-fix": "eslint src --fix",
+ "build": "bob build",
+ "release": "release-it"
+ },
+ "dependencies": {
+ "@expo/vector-icons": "^12.0.5",
+ "@react-native-community/slider": "^4.4.2",
+ "i18next": "^21.8.13",
+ "react-i18next": "^11.18.0",
+ "react-native-element-dropdown": "^2.10.0"
+ },
+ "devDependencies": {
+ "prop-types": "^15.8.1",
+ "react-native-builder-bob": "^0.18.2",
+ "release-it": "*"
+ },
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*",
+ "react-native-svg": "*"
+ },
+ "publishConfig": {
+ "access": "public"
+ }
+}
diff --git a/packages/feedback/src/components/BuildQuestion/index.js b/packages/feedback/src/components/BuildQuestion/index.js
new file mode 100644
index 000000000..99eb6825a
--- /dev/null
+++ b/packages/feedback/src/components/BuildQuestion/index.js
@@ -0,0 +1,86 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import {
+ FreeTextInput,
+ RadioInput,
+ SelectInput,
+ TextButton,
+} from '../common';
+
+export default function BuildQuestion({
+ type,
+ question,
+ answer,
+ options,
+ onChange,
+ config,
+ inputProps,
+}) {
+ return (
+ <>
+ {
+ type === 'text' && (
+
+ )
+ }
+ {
+ type === 'radio' && (
+
+ )
+ }
+ {
+ type === 'select' && (
+
+ )
+ }
+ {
+ type === 'button' && (
+
+ )
+ }
+ >
+ );
+}
+
+BuildQuestion.propTypes = {
+ answer: PropTypes.any,
+ config: PropTypes.shape({
+ isMulti: PropTypes.bool,
+ }),
+ inputProps: PropTypes.object,
+ onChange: PropTypes.func,
+ options: PropTypes.arrayOf(PropTypes.shape({
+ label: PropTypes.string,
+ value: PropTypes.any,
+ })),
+ question: PropTypes.string.isRequired,
+ type: PropTypes.string.isRequired,
+};
+
+BuildQuestion.defaultProps = {
+ answer: '',
+ onChange: () => { },
+ config: {
+ isMulti: false,
+ },
+ inputProps: {},
+ options: [],
+};
diff --git a/packages/feedback/src/components/Feedback/Feedback.js b/packages/feedback/src/components/Feedback/Feedback.js
new file mode 100644
index 000000000..4b0d1d3dd
--- /dev/null
+++ b/packages/feedback/src/components/Feedback/Feedback.js
@@ -0,0 +1,42 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import { View } from 'react-native';
+import BuildQuestion from '../BuildQuestion';
+
+export default function Feedback({ questions }) {
+ return (
+ questions.map((question, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+
+
+ ))
+ );
+}
+
+Feedback.propTypes = {
+ questions: PropTypes.arrayOf(PropTypes.shape({
+ answer: PropTypes.any,
+ config: PropTypes.object,
+ inputProps: PropTypes.object,
+ onChange: PropTypes.func,
+ options: PropTypes.arrayOf(PropTypes.shape({
+ label: PropTypes.string,
+ value: PropTypes.any,
+ })),
+ question: PropTypes.string.isRequired,
+ type: PropTypes.string.isRequired,
+ })),
+};
+
+Feedback.defaultProps = {
+ questions: [],
+};
diff --git a/packages/feedback/src/components/Feedback/index.js b/packages/feedback/src/components/Feedback/index.js
new file mode 100644
index 000000000..caa95ab99
--- /dev/null
+++ b/packages/feedback/src/components/Feedback/index.js
@@ -0,0 +1,15 @@
+import React from 'react';
+import { I18nextProvider } from 'react-i18next';
+
+import i18n from '../../i18n';
+import Feedback from './Feedback';
+
+function FeedbackHOC(props) {
+ return (
+
+
+
+ );
+}
+
+export default FeedbackHOC;
diff --git a/packages/feedback/src/components/common/FreeTextInput.js b/packages/feedback/src/components/common/FreeTextInput.js
new file mode 100644
index 000000000..cbbce6e8a
--- /dev/null
+++ b/packages/feedback/src/components/common/FreeTextInput.js
@@ -0,0 +1,48 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { StyleSheet, Text, TextInput, View } from 'react-native';
+
+const styles = StyleSheet.create({
+ textLabel: {
+ color: '#fff',
+ fontSize: 16,
+ marginBottom: 10,
+ },
+ textInput: {
+ borderColor: '#fff',
+ borderRadius: 4,
+ borderWidth: 1,
+ color: '#fff',
+ padding: 10,
+ },
+});
+
+function FreeTextInput({ label, value, inputProps, onChange }) {
+ return (
+
+ {label}
+
+
+ );
+}
+
+FreeTextInput.propTypes = {
+ inputProps: PropTypes.object,
+ label: PropTypes.string,
+ onChange: PropTypes.func,
+ value: PropTypes.string,
+};
+
+FreeTextInput.defaultProps = {
+ inputProps: {},
+ label: '',
+ onChange: () => { },
+ value: '',
+};
+
+export default FreeTextInput;
diff --git a/packages/feedback/src/components/common/RadioInput.js b/packages/feedback/src/components/common/RadioInput.js
new file mode 100644
index 000000000..df0613e4e
--- /dev/null
+++ b/packages/feedback/src/components/common/RadioInput.js
@@ -0,0 +1,79 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+
+const styles = StyleSheet.create({
+ textLabel: {
+ color: '#fff',
+ fontSize: 16,
+ marginBottom: 10,
+ },
+ radioButtonContainer: {
+ alignItems: 'center',
+ flexDirection: 'row',
+ marginBottom: 10,
+ marginRight: 10,
+ },
+ radioButton: {
+ alignItems: 'center',
+ borderColor: '#fff',
+ borderRadius: 10,
+ borderWidth: 1,
+ height: 18,
+ justifyContent: 'center',
+ width: 18,
+ },
+ radioButtonIcon: {
+ backgroundColor: '#fff',
+ borderRadius: 7,
+ height: 12,
+ width: 12,
+ },
+ radioButtonText: {
+ color: '#fff',
+ fontSize: 16,
+ marginLeft: 10,
+ },
+});
+
+function RadioInput({ label, options, value, onChange }) {
+ return (
+ <>
+ {label}
+ 3 ? { flexDirection: 'column' } : { flexDirection: 'row' }}>
+ {
+ options.map((item, index) => (
+ // eslint-disable-next-line react/no-array-index-key
+
+ onChange(item)} style={styles.radioButton}>
+ {value === item.value ? : null}
+
+ onChange(item)}>
+ {item.label}
+
+
+ ))
+ }
+
+ >
+ );
+}
+
+RadioInput.propTypes = {
+ label: PropTypes.string,
+ onChange: PropTypes.func,
+ options: PropTypes.arrayOf(PropTypes.shape({
+ label: PropTypes.string,
+ value: PropTypes.any,
+ })),
+ value: PropTypes.any,
+};
+
+RadioInput.defaultProps = {
+ label: '',
+ value: '',
+ options: [],
+ onChange: () => { },
+};
+
+export default RadioInput;
diff --git a/packages/feedback/src/components/common/SelectInput.js b/packages/feedback/src/components/common/SelectInput.js
new file mode 100644
index 000000000..e78050522
--- /dev/null
+++ b/packages/feedback/src/components/common/SelectInput.js
@@ -0,0 +1,123 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { StyleSheet, Text } from 'react-native';
+import { Dropdown, MultiSelect } from 'react-native-element-dropdown';
+
+const styles = StyleSheet.create({
+ textLabel: {
+ color: '#fff',
+ fontSize: 16,
+ marginBottom: 10,
+ },
+ containerStyle: {
+ backgroundColor: '#121212',
+ },
+ dropdown: {
+ borderColor: '#fff',
+ borderRadius: 4,
+ borderWidth: 1,
+ height: 39,
+ padding: 12,
+ },
+ placeholderStyle: {
+ color: '#fff',
+ fontSize: 16,
+ },
+ selectedTextStyle: {
+ fontSize: 14,
+ color: '#fff',
+ },
+ iconStyle: {
+ height: 20,
+ width: 20,
+ },
+ itemTextStyle: {
+ color: '#fff',
+ },
+ inputSearchStyle: {
+ color: '#fff',
+ fontSize: 16,
+ outlineWidth: 0,
+ },
+ icon: {
+ marginRight: 5,
+ },
+});
+
+function SelectInput({ label, options, value, onChange, config, inputProps }) {
+ return (
+ <>
+ {label}
+ {
+ config.isMulti ? (
+ onChange(item)}
+ placeholderStyle={styles.placeholderStyle}
+ search
+ selectedTextStyle={styles.selectedTextStyle}
+ style={styles.dropdown}
+ value={value}
+ valueField="value"
+ />
+ ) : (
+ onChange(item)}
+ placeholderStyle={styles.placeholderStyle}
+ search
+ selectedTextStyle={styles.selectedTextStyle}
+ style={styles.dropdown}
+ value={value}
+ valueField="value"
+ />
+ )
+ }
+ >
+ );
+}
+
+SelectInput.propTypes = {
+ config: PropTypes.shape({
+ isMulti: PropTypes.bool,
+ }),
+ inputProps: PropTypes.object,
+ label: PropTypes.string,
+ onChange: PropTypes.func,
+ options: PropTypes.arrayOf(PropTypes.shape({
+ label: PropTypes.string,
+ value: PropTypes.any,
+ })),
+ value: PropTypes.any,
+};
+
+SelectInput.defaultProps = {
+ label: '',
+ value: '',
+ options: [],
+ onChange: () => { },
+ config: {
+ isMulti: false,
+ },
+ inputProps: {},
+};
+
+export default SelectInput;
diff --git a/packages/feedback/src/components/common/TextButton.js b/packages/feedback/src/components/common/TextButton.js
new file mode 100644
index 000000000..f4d5f0f69
--- /dev/null
+++ b/packages/feedback/src/components/common/TextButton.js
@@ -0,0 +1,40 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { StyleSheet, TouchableOpacity, Text } from 'react-native';
+
+const styles = StyleSheet.create({
+ container: {
+ display: 'flex',
+ justifyContent: 'center',
+ alignItems: 'center',
+ borderWidth: 2,
+ borderStyle: 'solid',
+ borderColor: '#5D5E67',
+ borderRadius: 28,
+ paddingHorizontal: 10,
+ paddingVertical: 10,
+ },
+ text: {
+ color: '#ffffff',
+ fontSize: 14,
+ },
+});
+
+function TextButton({ label, onPress }) {
+ return (
+
+ {label}
+
+ );
+}
+
+TextButton.propTypes = {
+ label: PropTypes.string,
+ onPress: PropTypes.func,
+};
+TextButton.defaultProps = {
+ label: '',
+ onPress: () => {},
+};
+
+export default TextButton;
diff --git a/packages/feedback/src/components/common/index.js b/packages/feedback/src/components/common/index.js
new file mode 100644
index 000000000..7909813e3
--- /dev/null
+++ b/packages/feedback/src/components/common/index.js
@@ -0,0 +1,11 @@
+import FreeTextInput from './FreeTextInput';
+import RadioInput from './RadioInput';
+import TextButton from './TextButton';
+import SelectInput from './SelectInput';
+
+export {
+ FreeTextInput,
+ RadioInput,
+ TextButton,
+ SelectInput,
+};
diff --git a/packages/feedback/src/components/index.js b/packages/feedback/src/components/index.js
new file mode 100644
index 000000000..202986754
--- /dev/null
+++ b/packages/feedback/src/components/index.js
@@ -0,0 +1,2 @@
+export { default as Feedback } from './Feedback';
+export { default as BuildQuestion } from './BuildQuestion';
diff --git a/packages/feedback/src/hooks/index.js b/packages/feedback/src/hooks/index.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/packages/feedback/src/i18n/index.js b/packages/feedback/src/i18n/index.js
new file mode 100644
index 000000000..21f5c3d62
--- /dev/null
+++ b/packages/feedback/src/i18n/index.js
@@ -0,0 +1,16 @@
+import { createInstance } from 'i18next';
+import { initReactI18next } from 'react-i18next';
+import resources from './resources';
+
+const i18n = createInstance({
+ compatibilityJSON: 'v3',
+ fallbackLng: 'en',
+ interpolation: {
+ escapeValue: false,
+ },
+ resources,
+});
+
+i18n.use(initReactI18next).init();
+
+export default i18n;
diff --git a/packages/feedback/src/i18n/resources/en.js b/packages/feedback/src/i18n/resources/en.js
new file mode 100644
index 000000000..a268e27f9
--- /dev/null
+++ b/packages/feedback/src/i18n/resources/en.js
@@ -0,0 +1,5 @@
+const en = {
+ translation: {},
+};
+
+export default en;
diff --git a/packages/feedback/src/i18n/resources/fr.js b/packages/feedback/src/i18n/resources/fr.js
new file mode 100644
index 000000000..6539a22ba
--- /dev/null
+++ b/packages/feedback/src/i18n/resources/fr.js
@@ -0,0 +1,5 @@
+const fr = {
+ translation: {},
+};
+
+export default fr;
diff --git a/packages/feedback/src/i18n/resources/index.js b/packages/feedback/src/i18n/resources/index.js
new file mode 100644
index 000000000..db9aa5ec3
--- /dev/null
+++ b/packages/feedback/src/i18n/resources/index.js
@@ -0,0 +1,6 @@
+import en from './en';
+import fr from './fr';
+
+const resources = { en, fr };
+
+export default resources;
diff --git a/packages/feedback/src/index.js b/packages/feedback/src/index.js
new file mode 100644
index 000000000..a5457872b
--- /dev/null
+++ b/packages/feedback/src/index.js
@@ -0,0 +1,2 @@
+export * from './components';
+export { default as i18nDamageReport } from './i18n';
diff --git a/src/config/Navigation.js b/src/config/Navigation.js
index 7eb1e1d2c..7db47e3d9 100644
--- a/src/config/Navigation.js
+++ b/src/config/Navigation.js
@@ -51,6 +51,11 @@ export default function Navigation() {
component={Screens.InspectionReport}
title="Monk - Inspection Report"
/>
+
);
diff --git a/src/screens/InspectionFeedback/index.js b/src/screens/InspectionFeedback/index.js
new file mode 100644
index 000000000..08989082e
--- /dev/null
+++ b/src/screens/InspectionFeedback/index.js
@@ -0,0 +1,104 @@
+import React, { useCallback, useState } from 'react';
+import { Feedback } from '@monkvision/feedback';
+import { View } from 'react-native';
+
+export default function InspectionFeedback() {
+ const [interior, setInterior] = useState('');
+ const [windShieldCondition, setWindShieldCondition] = useState('');
+ const [tireCondition, setTireCondition] = useState('');
+ const [tireConditionSingleSelect, setTireConditionSingleSelect] = useState('');
+ const [tireConditionMultiSelect, setTireConditionMultiSelect] = useState([]);
+ const [vehicleInterior, setVehicleInterior] = useState('');
+
+ const handleSubmit = useCallback(() => {
+ console.log('🚀 interior : ', interior);
+ console.log('🚀 windShieldCondition : ', windShieldCondition);
+ console.log('🚀 tireCondition : ', tireCondition);
+ console.log('🚀 tireConditionSingleSelect : ', tireConditionSingleSelect);
+ console.log('🚀 tireConditionMultiSelect : ', tireConditionMultiSelect);
+ console.log('🚀 vehicleInterior : ', vehicleInterior);
+ }, [
+ interior,
+ windShieldCondition,
+ tireCondition,
+ tireConditionSingleSelect,
+ tireConditionMultiSelect,
+ vehicleInterior
+ ]);
+
+ return (
+
+ setInterior(value)
+ }, {
+ type: 'radio',
+ question: 'Is the windshield in good condition?',
+ answer: windShieldCondition,
+ onChange: (data) => setWindShieldCondition(data.value),
+ options: [
+ { label: 'Y', value: true },
+ { label: 'N', value: false },
+ ],
+ }, {
+ type: 'select',
+ question: 'Is the tire condition normal (Single Select)?',
+ answer: tireConditionSingleSelect,
+ onChange: (data) => setTireConditionSingleSelect(data),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ { label: 'Great', value: 'Great' },
+ ],
+ }, {
+ type: 'select',
+ question: 'Is the tire condition normal (Multi Select)?',
+ answer: tireConditionMultiSelect,
+ config: {
+ isMulti: true,
+ },
+ onChange: (data) => setTireConditionMultiSelect(data),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ { label: 'Great', value: 'Great' },
+ ],
+ }, {
+ type: 'radio',
+ question: 'Is the tire condition normal?',
+ answer: tireCondition,
+ onChange: (data) => setTireCondition(data.value),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ { label: 'Great', value: 'Great' },
+ ],
+ }, {
+ type: 'radio',
+ question: 'How is the interior of the vehicle?',
+ answer: vehicleInterior,
+ onChange: (data) => setVehicleInterior(data.value),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ ],
+ }, {
+ type: 'button',
+ question: 'Submit',
+ onChange: () => handleSubmit()
+ }]}
+ />
+
+ );
+}
+
+InspectionFeedback.propTypes = {};
+
+InspectionFeedback.defaultProps = {};
diff --git a/src/screens/InspectionFeedback/styles.js b/src/screens/InspectionFeedback/styles.js
new file mode 100644
index 000000000..78c2ab86e
--- /dev/null
+++ b/src/screens/InspectionFeedback/styles.js
@@ -0,0 +1,3 @@
+import { StyleSheet } from 'react-native';
+
+export default StyleSheet.create({});
diff --git a/src/screens/index.js b/src/screens/index.js
index 9bdcf24e9..274746503 100644
--- a/src/screens/index.js
+++ b/src/screens/index.js
@@ -4,5 +4,6 @@ export { default as InspectionVehicleUpdate } from './InspectionVehicleUpdate';
export { default as InspectionList } from './InspectionList';
export { default as InspectionPrompt } from './InspectionPrompt';
export { default as InspectionReport } from './InspectionReport';
+export { default as InspectionFeedback } from './InspectionFeedback';
export { default as Landing } from './Landing';
export { default as SignIn } from './Authentication/SignIn';
diff --git a/src/screens/names.js b/src/screens/names.js
index e543ccdbb..3fd7e075a 100644
--- a/src/screens/names.js
+++ b/src/screens/names.js
@@ -3,6 +3,7 @@ export const INSPECTION_CREATE = 'inspectionCreate';
export const INSPECTION_VEHICLE_UPDATE = 'InspectionVehicleUpdate';
export const INSPECTION_LIST = 'inspectionList';
export const INSPECTION_PROMPT = 'inspectionPrompt';
+export const INSPECTION_FEEDBACK = 'inspectionFeedback';
export const INSPECTION_REPORT = 'inspectionReport';
export const LANDING = 'landing';
export const SIGN_IN = 'signIn';
diff --git a/webpack.config.js b/webpack.config.js
index 603eadfa0..99acb3369 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -22,6 +22,7 @@ module.exports = async function (env, argv) {
config.resolve.alias['@monkvision/toolkit'] = path.resolve(__dirname, './packages/toolkit');
config.resolve.alias['@monkvision/visualization'] = path.resolve(__dirname, './packages/visualization');
config.resolve.alias['@monkvision/inspection-report'] = path.resolve(__dirname, './packages/inspection-report');
+ config.resolve.alias['@monkvision/feedback'] = path.resolve(__dirname, './packages/feedback');
if (config.mode === 'development') {
config.devServer.compress = false;
diff --git a/website/docs.sidebars.js b/website/docs.sidebars.js
index 86769b545..d76aa371a 100644
--- a/website/docs.sidebars.js
+++ b/website/docs.sidebars.js
@@ -41,5 +41,6 @@ module.exports = {
'troubleshooting',
'monitoring',
'inspection-report',
+ 'feedback',
],
};
diff --git a/website/docs/feedback.md b/website/docs/feedback.md
new file mode 100644
index 000000000..04a291277
--- /dev/null
+++ b/website/docs/feedback.md
@@ -0,0 +1,159 @@
+---
+id: feedback
+title: "🧿 Feedback"
+slug: /feedback
+---
+
+![npm latest package](https://img.shields.io/npm/v/@monkvision/inspection-report/latest.svg)
+
+# Package Overview
+
+The Feedback package allows users to create a feedback page with different input controls such as free text, radio buttons, single / multi selection and button components.
+
+# Implementation Guide
+## Installation
+
+To install the package simply run the following command in your project :
+
+```bash
+yarn add @monkvision/feedback
+```
+
+## Basic Usage
+The `Feedback` component exported by the package is a single page component that will automatically display the entire form with all the questions assigned to the component. It takes only one parameter which is `questions` which will be an array of all the questions. The component will create an form using an `BuildQuestion` component.
+
+Here is a minimal working example :
+
+```javascript
+import React, { useState } from 'react';
+import { Feedback } from '@monkvision/feedback';
+
+export default function InspectionFeedback() {
+ const [interior, setInterior] = useState('');
+ const [windShieldCondition, setWindShieldCondition] = useState('');
+ const [tireCondition, setTireCondition] = useState('');
+ const [tireConditionSingleSelect, setTireConditionSingleSelect] = useState('');
+ const [tireConditionMultiSelect, setTireConditionMultiSelect] = useState([]);
+ const [vehicleInterior, setVehicleInterior] = useState('');
+
+ const handleSubmit = useCallback(() => {
+ // Further logic will be implemented here
+ }, [
+ interior,
+ windShieldCondition,
+ tireCondition,
+ tireConditionSingleSelect,
+ tireConditionMultiSelect,
+ vehicleInterior
+ ]);
+
+ return (
+ setInterior(value)
+ }, {
+ type: 'radio',
+ question: 'Is the windshield in good condition?',
+ answer: windShieldCondition,
+ onChange: (data) => setWindShieldCondition(data.value),
+ options: [
+ { label: 'Y', value: true },
+ { label: 'N', value: false },
+ ],
+ }, {
+ type: 'select',
+ question: 'Is the tire condition normal (Single Select)?',
+ answer: tireConditionSingleSelect,
+ onChange: (data) => setTireConditionSingleSelect(data),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ { label: 'Great', value: 'Great' },
+ ],
+ }, {
+ type: 'select',
+ question: 'Is the tire condition normal (Multi Select)?',
+ answer: tireConditionMultiSelect,
+ config: {
+ isMulti: true,
+ },
+ onChange: (data) => setTireConditionMultiSelect(data),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ { label: 'Great', value: 'Great' },
+ ],
+ }, {
+ type: 'radio',
+ question: 'Is the tire condition normal?',
+ answer: tireCondition,
+ onChange: (data) => setTireCondition(data.value),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ { label: 'Great', value: 'Great' },
+ ],
+ }, {
+ type: 'radio',
+ question: 'How is the interior of the vehicle?',
+ answer: vehicleInterior,
+ onChange: (data) => setVehicleInterior(data.value),
+ options: [
+ { label: 'Poor', value: 'Poor' },
+ { label: 'Medium', value: 'Medium' },
+ { label: 'Good', value: 'Good' },
+ ],
+ }, {
+ type: 'button',
+ question: 'Submit',
+ onChange: () => handleSubmit()
+ }]}
+ />
+ );
+}
+```
+
+# API
+## Components
+### Feedback
+#### Description
+```javascript
+import { Feedback } from '@monkvision/feedback';
+```
+
+This component is a single page component that uses `BuildQuestion` component to create an form.
+
+#### Props
+| Prop | Type | Description | Required | Default Value |
+|---------------------------|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|---------------|
+| `questions.answer` | `any` | The answer for the question. Which can be string, number, boolean, object. | ✔ | |
+| `questions.config` | `object` | The configuration for inputs such as `isMulti`. | ✔ | |
+| `questions.inputProps` | `any` | Any other configuration which can be supported by an input as it's going to override the default behaviour. | ✔ | |
+| `questions.onChange` | `Function` | A callback of change input data. | ✔ | () => {} |
+| `questions.question` | `string` | The label for the question. | ✔ | |
+| `questions.type` | `string` | The type of inputs which can be one of `radio`, `text`, `select`, `button`. | ✔ | |
+| `questions.options` | `object` | The list of options available for radio and select inputs. | ✔ | |
+
+### Feedback
+#### BuildQuestion
+```javascript
+import BuildQuestion from '../BuildQuestion';
+
+
+```
+
+This component is a question builder which helps to create / build input components. All the props are same as passed in feedback component.
diff --git a/yarn.lock b/yarn.lock
index 38300b31c..d062eb7a5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -14121,6 +14121,13 @@ react-native-codegen@^0.0.6:
jscodeshift "^0.11.0"
nullthrows "^1.1.1"
+react-native-element-dropdown@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/react-native-element-dropdown/-/react-native-element-dropdown-2.10.0.tgz#f4ec2310b37ff3ba64927286ab775c0ed28b681e"
+ integrity sha512-aFjw0JbUIKGkqklHxDm8aDCZW6Q1GICP7pIHc0sllvpWpEamItzOwAMV4G1mBIKxED77Mp+nkq9p0Dhsr/faVw==
+ dependencies:
+ lodash "^4.17.21"
+
react-native-gesture-handler@~1.10.2:
version "1.10.3"
resolved "https://registry.yarnpkg.com/react-native-gesture-handler/-/react-native-gesture-handler-1.10.3.tgz#942bbf2963bbf49fa79593600ee9d7b5dab3cfc0"