react-native-surveys
Version:
Build your own forms, surveys and polls for your React Native apps.
294 lines (253 loc) • 6.76 kB
JavaScript
import React from "react";
import { Platform } from "react-native";
import Description from "./Description";
import Open from "./Open";
import SingleSelection from "./SingleSelection";
import MultiSelection from "./MultiSelection";
import NumberScale from "./NumberScale";
import Stars from "./Stars";
import Contact from "./Contact";
import FilesUploadWeb from "./FilesUpload/Web";
import FilesUploadMobile from "./FilesUpload/Mobile";
import Date from "./Date";
export function clearFormValues(form) {
const pages = form.pages || [];
pages.forEach(page => {
const blocks = page.blocks || [];
blocks.forEach(block => clearBlock(block));
});
}
export function clearBlock(block) {
if (Array.isArray(block.value)) {
if (block.value[0] && (block.value[0].type || block.value[0].question)) {
block.value.forEach(field => {
if (field.value) {
field.value = "";
}
});
} else {
if (block.value.length > 0) {
block.value = [];
}
}
} else {
if (block.value) {
block.value = "";
}
if (block.files) {
delete block.files;
}
if (block.time) {
delete block.time;
}
if (block.timezone) {
delete block.timezone;
}
}
}
export function getTypeLabel(type) {
switch (type) {
case "contact":
return "Contact Form";
case "files":
return "File Upload";
case "date":
return "Date Picker";
case "open":
return "Open-ended";
case "number-scale":
return "Net Promoter Score";
case "single-selection":
return "Single-selection";
case "stars":
return "Stars Rating";
case "multi-selection":
return "Multiple-selection";
case "description":
return "Description";
default:
return type;
}
}
export const returnQuestionNumber = (blockIndex, pageIndex, pages) => {
let questionNumber = blockIndex + 1;
for (let i = 0; i < pageIndex; i++) {
questionNumber += pages[i].blocks.length;
}
return questionNumber;
};
export const returnFormData = form => {
const pages = form.pages || [];
let formData = {};
pages.forEach(page => {
const blocks = page.blocks || [];
blocks.forEach(block => {
if (block.type === "contact") {
const fields = block.value || [];
fields.forEach(field => {
const { value } = returnBlockValue(field);
if (!value) return;
formData[field.question] = value;
});
return;
}
const { value } = returnBlockValue(block);
if (!value) return;
formData[block.question] = value;
});
});
if (form.extraData) {
Object.keys(form.extraData).forEach(key => {
if (typeof form.extraData[key] !== "string") {
console.error(`${key} has invalid data format. Should be string.`);
return;
}
formData[key] = form.extraData[key];
});
}
return formData;
};
export function returnBlockValue(block) {
if (Array.isArray(block.value)) {
if (block.value[0] && (block.value[0].type || block.value[0].question)) {
let canSend = true;
block.value.forEach(field => {
if (field.isRequired && !field.value) {
canSend = false;
}
});
return {
value: block.value
.filter(field => field.value)
.map(f => "\n" + f.question + ": " + f.value)
.join(", "),
hasValue: block.value.filter(field => field.value).length > 0,
canSend
};
} else {
block.value = block.value.filter(value => value);
return {
canSend: block.isRequired ? block.value.length > 0 : true,
hasValue: block.value.length > 0,
value: block.value.join(", ")
};
}
}
return {
canSend: block.isRequired ? block.value : true,
hasValue: block.value,
value: block.value
};
}
export function returnPageCompletionStatus(page) {
const blocks = page.blocks || [];
let isCompleted = true;
let hasValues = false;
blocks.forEach(block => {
const { canSend, hasValue } = returnBlockValue(block);
if (!hasValues && hasValue) {
hasValues = true;
}
if (!canSend) {
isCompleted = false;
}
});
return {
isCompleted,
hasValues
};
}
export function returnQuestionsCount(pages = []) {
let count = 0;
pages.forEach(page => {
if (page.blocks) {
page.blocks.forEach(block => {
if (block.type === "contact") {
const fields = block.value || [];
count += fields.length;
return;
}
count += 1;
});
}
});
return count;
}
export function getDefaultBadge(badge, type) {
if (badge) return badge;
switch (type) {
case "contact":
return "FILL IN FIELDS BELOW";
case "files":
return "DROP FILES IN THE BOX BELOW";
case "date":
return "SELECT DATE";
case "open":
return "WRITE IN THE BOX BELOW";
case "number-scale":
return "PICK NUMBER";
case "single-selection":
return "SELECT ONE";
case "stars":
return "TAP STARS TO RATE";
case "multi-selection":
return "SELECT ONE OR MORE";
default:
return "";
}
}
export function renderBlocks({
page,
form,
isPreview,
currentPageIndex,
onFocus,
onBlur
}) {
const pages = form.pages || [];
const allBlocks = [];
pages.forEach(page => allBlocks.push(...page.blocks));
const pageBlocks = page.blocks || [];
return pageBlocks.map((block, blockIndex) => {
block.badge = getDefaultBadge(block.badge, block.type);
const props = {
form,
block,
page,
isPreview,
currentPageIndex,
blockIndex,
allBlocks,
onFocus,
onBlur,
key: block.type + currentPageIndex + "block" + blockIndex
};
return renderBlock(block.type, props);
});
}
export const renderBlock = (type, props) => {
switch (type) {
case "description":
return React.createElement(Description, props);
case "number-scale":
return React.createElement(NumberScale, props);
case "stars":
return React.createElement(Stars, props);
case "contact":
return React.createElement(Contact, props);
case "open":
return React.createElement(Open, props);
case "single-selection":
return React.createElement(SingleSelection, props);
case "multi-selection":
return React.createElement(MultiSelection, props);
case "date":
return React.createElement(Date, props);
case "files":
return Platform.OS === "web"
? React.createElement(FilesUploadWeb, props)
: React.createElement(FilesUploadMobile, props);
default:
return null;
}
};