UNPKG

@e-group/material-module

Version:
454 lines (419 loc) 14.1 kB
import _extends from "@babel/runtime/helpers/esm/extends"; import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray"; import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties"; import React, { useState, useEffect } from 'react'; import isLength from 'validator/lib/isLength'; import clsx from 'clsx'; import useInputActions from '@e-group/hooks/useInputActions'; import { makeStyles } from '@material-ui/core'; import Tooltip from '@material-ui/core/Tooltip'; import Paper from '@material-ui/core/Paper'; import Grid from '@material-ui/core/Grid'; import Typography from '@material-ui/core/Typography'; import MenuItem from '@material-ui/core/MenuItem'; import Divider from '@material-ui/core/Divider'; import InputAdornment from '@material-ui/core/InputAdornment'; import IconButton from '@material-ui/core/IconButton'; import TextField from '@e-group/material/TextField'; import Icomoon from '@e-group/material/Icomoon'; import Switch from '@e-group/material/Switch'; import TitleIcon from '@material-ui/icons/Title'; import ShortTextIcon from '@material-ui/icons/ShortText'; import SubjectIcon from '@material-ui/icons/Subject'; import RadioButtonCheckedIcon from '@material-ui/icons/RadioButtonChecked'; import CheckboxIcon from '@material-ui/icons/CheckBox'; import ArrowDropDownCircleIcon from '@material-ui/icons/ArrowDropDownCircle'; import LinearScaleIcon from '@material-ui/icons/LinearScale'; import InsertInvitationIcon from '@material-ui/icons/InsertInvitation'; import EmailIcon from '@material-ui/icons/Email'; import QuestionOptionsEditable from '../QuestionOptionsEditable'; import QuestionRatingEditable from '../QuestionRatingEditable'; import QuestionDragHandle from '../QuestionDragHandle'; const useStyles = makeStyles(theme => ({ root: { margin: theme.spacing(1.5, 0), boxShadow: theme.egShadows[3], border: "1px solid #e3e6f0", borderRadius: "0.35rem", position: 'relative', overflow: 'hidden' }, active: { position: 'absolute', top: 0, left: 0, bottom: 0, width: 6, backgroundColor: theme.egPalette.info[1] }, main: { padding: theme.spacing(0, 3) }, content: { marginBottom: theme.spacing(4) }, actions: { padding: theme.spacing(1, 0), display: 'flex', justifyContent: 'flex-end', alignItems: 'center' }, select: { paddingTop: theme.spacing(2), paddingBottom: theme.spacing(2), lineHeight: "".concat(theme.spacing(3), "px") }, menuItem: { padding: theme.spacing(1, 2), '& .MuiTypography-root': { lineHeight: "".concat(theme.spacing(4), "px"), minWidth: theme.spacing(17) } }, option: { display: 'flex', alignItems: 'center' }, icon: { marginRight: theme.spacing(2) }, divider: { margin: theme.spacing(1, 0) }, text: { width: '50%', marginBottom: theme.spacing(2) }, textarea: { width: '85%', marginBottom: theme.spacing(2) }, vertical: { margin: theme.spacing(0, 2), height: theme.spacing(4) }, switch: { margin: 0 } })); const MAX_NAME = 50; const MAX_DESC = 100; const optionMap = { titleBlock: { name: '標題區塊', icon: TitleIcon }, text: { name: '簡答', icon: ShortTextIcon }, textarea: { name: '段落', icon: SubjectIcon }, choiceone: { name: '選擇題', icon: RadioButtonCheckedIcon }, choicemulti: { name: '核取方塊', icon: CheckboxIcon }, select: { name: '下拉式選單', icon: ArrowDropDownCircleIcon }, rating: { name: '線性刻度', icon: LinearScaleIcon }, date: { name: '日期', icon: InsertInvitationIcon }, email: { name: '電子郵件', icon: EmailIcon } }; const QuestionEditable = (_ref) => { let question = _ref.question, className = _ref.className, DragHandleProps = _ref.DragHandleProps, _ref$optionTypes = _ref.optionTypes, optionTypes = _ref$optionTypes === void 0 ? ['titleBlock', '|', 'text', 'textarea', '|', 'choiceone', 'choicemulti', 'select', '|', 'rating', '|', 'date', '|', 'email'] : _ref$optionTypes, autoFocusOptionIndex = _ref.autoFocusOptionIndex, autoFocusName = _ref.autoFocusName, onDescChange = _ref.onDescChange, onNameChange = _ref.onNameChange, onNameClick = _ref.onNameClick, onTypeChange = _ref.onTypeChange, onRequiredChange = _ref.onRequiredChange, onDelete = _ref.onDelete, onOptionChange = _ref.onOptionChange, onOptionDelete = _ref.onOptionDelete, onOptionDragEnd = _ref.onOptionDragEnd, onOptionCreate = _ref.onOptionCreate, onOptionCreateOther = _ref.onOptionCreateOther, onRatingStartChange = _ref.onRatingStartChange, onRatingEndChange = _ref.onRatingEndChange, onRatingStartInputChange = _ref.onRatingStartInputChange, onRatingEndInputChange = _ref.onRatingEndInputChange, other = _objectWithoutProperties(_ref, ["question", "className", "DragHandleProps", "optionTypes", "autoFocusOptionIndex", "autoFocusName", "onDescChange", "onNameChange", "onNameClick", "onTypeChange", "onRequiredChange", "onDelete", "onOptionChange", "onOptionDelete", "onOptionDragEnd", "onOptionCreate", "onOptionCreateOther", "onRatingStartChange", "onRatingEndChange", "onRatingStartInputChange", "onRatingEndInputChange"]); const classes = useStyles(); const _useState = useState(question.questionName), _useState2 = _slicedToArray(_useState, 2), name = _useState2[0], setName = _useState2[1]; const _useState3 = useState(question.questionType), _useState4 = _slicedToArray(_useState3, 2), type = _useState4[0], setType = _useState4[1]; const _useState5 = useState(question.questionDescription), _useState6 = _slicedToArray(_useState5, 2), desc = _useState6[0], setDesc = _useState6[1]; const _useState7 = useState(Boolean(question.isRequired)), _useState8 = _slicedToArray(_useState7, 2), isRequired = _useState8[0], setIsRequired = _useState8[1]; const _useInputActions = useInputActions(), inputEl = _useInputActions.inputEl, select = _useInputActions.select; const isNameError = !isLength(name || '', { min: 0, max: MAX_NAME }); const isDescError = !isLength(desc || '', { min: 0, max: MAX_DESC }); useEffect(() => { if (autoFocusName) { select(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleNameChange = e => { setName(e.target.value); if (onNameChange && isLength(e.target.value, { min: 0, max: MAX_NAME })) { onNameChange(e, question); } }; const handleNameClick = e => { if (onNameClick) { onNameClick(e, question); } }; const handleDescChange = e => { setDesc(e.target.value); if (onDescChange && isLength(e.target.value, { min: 0, max: MAX_DESC })) { onDescChange(e, question); } }; const handleTypeChange = e => { setType(e.target.value); if (onTypeChange) { onTypeChange(e, question); } }; const handleIsRequiredChange = (e, checked) => { setIsRequired(checked); if (onRequiredChange) { onRequiredChange(e, question); } }; const handleDelete = e => { if (onDelete) { onDelete(e, question); } }; const getNameLabel = () => { if (type === 'titleBlock') return '標題'; return '問題'; }; const renderContent = () => { switch (type) { case 'titleBlock': return /*#__PURE__*/React.createElement(TextField, { className: classes.textarea, label: "\u5340\u584A\u63CF\u8FF0", multiline: true, value: desc, onChange: handleDescChange, error: isDescError, helperText: isDescError ? "\u5340\u584A\u63CF\u8FF0\u8ACB\u52FF\u8D85\u904E ".concat(MAX_DESC, " \u500B\u5B57\u5143") : undefined }); case 'text': return /*#__PURE__*/React.createElement(TextField, { className: classes.text, label: "\u7C21\u7B54\u6587\u5B57", disabled: true }); case 'textarea': return /*#__PURE__*/React.createElement(TextField, { className: classes.textarea, label: "\u8A73\u7B54\u6587\u5B57", disabled: true }); case 'choiceone': return /*#__PURE__*/React.createElement(QuestionOptionsEditable, { type: "radio", onChange: onOptionChange, onCreate: onOptionCreate, onCreateOther: onOptionCreateOther, onDelete: onOptionDelete, onDragEnd: onOptionDragEnd, question: question, autoFocusIndex: autoFocusOptionIndex }); case 'choicemulti': return /*#__PURE__*/React.createElement(QuestionOptionsEditable, { type: "checkbox", onChange: onOptionChange, onCreate: onOptionCreate, onCreateOther: onOptionCreateOther, onDelete: onOptionDelete, onDragEnd: onOptionDragEnd, question: question, autoFocusIndex: autoFocusOptionIndex }); case 'select': return /*#__PURE__*/React.createElement(QuestionOptionsEditable, { type: "select", onChange: onOptionChange, onCreate: onOptionCreate, onCreateOther: onOptionCreateOther, onDelete: onOptionDelete, onDragEnd: onOptionDragEnd, question: question, autoFocusIndex: autoFocusOptionIndex }); case 'rating': return /*#__PURE__*/React.createElement(QuestionRatingEditable, { question: question, onStartChange: onRatingStartChange, onEndChange: onRatingEndChange, onStartInputChange: onRatingStartInputChange, onEndInputChange: onRatingEndInputChange }); case 'email': return /*#__PURE__*/React.createElement(TextField, { className: classes.text, label: "\u96FB\u5B50\u90F5\u4EF6", disabled: true }); case 'date': return /*#__PURE__*/React.createElement(TextField, { className: classes.text, label: "\u5E74/\u6708/\u65E5", disabled: true, InputProps: { endAdornment: /*#__PURE__*/React.createElement(InputAdornment, { position: "end" }, /*#__PURE__*/React.createElement(InsertInvitationIcon, null)) } }); default: return undefined; } }; return /*#__PURE__*/React.createElement(Paper, _extends({ className: clsx(className, classes.root) }, other), /*#__PURE__*/React.createElement(QuestionDragHandle, { DragHandleProps: DragHandleProps }), /*#__PURE__*/React.createElement("div", { className: classes.active }), /*#__PURE__*/React.createElement("div", { className: classes.main }, /*#__PURE__*/React.createElement(Grid, { className: classes.content, container: true, spacing: 1, alignItems: "flex-start" }, /*#__PURE__*/React.createElement(Grid, { item: true, xs: 12, sm: 9 }, /*#__PURE__*/React.createElement(TextField, { inputRef: inputEl, multiline: true, autoFocus: autoFocusName, onChange: handleNameChange, onClick: handleNameClick, fullWidth: true, value: name, label: getNameLabel(), error: isNameError, helperText: isNameError ? "".concat(getNameLabel(), "\u8ACB\u52FF\u8D85\u904E ").concat(MAX_NAME, " \u500B\u5B57\u5143") : undefined })), /*#__PURE__*/React.createElement(Grid, { item: true, xs: 12, sm: 3 }, /*#__PURE__*/React.createElement(TextField, { SelectProps: { classes: { root: classes.select } }, fullWidth: true, select: true, variant: "outlined", rounded: true, value: type, onChange: handleTypeChange }, optionTypes.map((type, index) => { var _optionMap$type$icon, _optionMap$type, _optionMap$type2; if (type === '|') { // eslint-disable-next-line react/no-array-index-key return /*#__PURE__*/React.createElement(Divider, { key: index, className: classes.divider }); } if (!optionMap[type]) { return undefined; } const OptionIcon = (_optionMap$type$icon = (_optionMap$type = optionMap[type]) === null || _optionMap$type === void 0 ? void 0 : _optionMap$type.icon) !== null && _optionMap$type$icon !== void 0 ? _optionMap$type$icon : 'div'; return /*#__PURE__*/React.createElement(MenuItem // eslint-disable-next-line react/no-array-index-key , { key: index, className: classes.menuItem, value: type }, /*#__PURE__*/React.createElement("div", { className: classes.option }, /*#__PURE__*/React.createElement(OptionIcon, { className: classes.icon }), /*#__PURE__*/React.createElement(Typography, { variant: "body2", display: "inline" }, (_optionMap$type2 = optionMap[type]) === null || _optionMap$type2 === void 0 ? void 0 : _optionMap$type2.name))); }))), /*#__PURE__*/React.createElement(Grid, { item: true, xs: 12 }, renderContent())), /*#__PURE__*/React.createElement(Divider, null), /*#__PURE__*/React.createElement("div", { className: classes.actions }, /*#__PURE__*/React.createElement(Tooltip, { title: "\u522A\u9664" }, /*#__PURE__*/React.createElement(IconButton, { onClick: handleDelete }, /*#__PURE__*/React.createElement(Icomoon, { type: "delete_1", fontSize: "large" }))), type !== 'titleBlock' && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Divider, { className: classes.vertical, orientation: "vertical" }), /*#__PURE__*/React.createElement(Switch, { className: classes.switch, checked: isRequired, onChange: handleIsRequiredChange, labelPlacement: "start", label: "\u5FC5\u586B" }))))); }; export default QuestionEditable;