diff --git a/src/components/EditFieldForm/EditFieldDate.tsx b/src/components/EditFieldForm/EditFieldDate.tsx index f79564f..f8e928f 100644 --- a/src/components/EditFieldForm/EditFieldDate.tsx +++ b/src/components/EditFieldForm/EditFieldDate.tsx @@ -3,6 +3,8 @@ import { Accordion } from "react-bootstrap"; import { TypeOptionSelect } from "./TypeOptionSelect"; import { FormikProps } from "formik"; +export const DARTE_FIELD_OPTIONS = "Date Field Options"; + export interface EditFieldTextProps extends FormikProps<{ [key: string]: string }> {} @@ -13,7 +15,7 @@ export const EditFieldDate: FC = (props): ReactElement => { -
Date Field Options
+
{DARTE_FIELD_OPTIONS}
diff --git a/src/components/EditFieldForm/EditFieldForm.tsx b/src/components/EditFieldForm/EditFieldForm.tsx index 3d3459d..cbf9d5b 100644 --- a/src/components/EditFieldForm/EditFieldForm.tsx +++ b/src/components/EditFieldForm/EditFieldForm.tsx @@ -17,6 +17,42 @@ import { EditFieldNumber } from "./EditFieldNumber"; import { EditFieldDate } from "./EditFieldDate"; import "./editFieldForm.scss"; import { EditFieldSelect } from "./EditFieldSelect"; +import { + ADD, + BOOLEAN, + BOOLEAN_LABEL, + CANCEL, + CREATE_LABEL, + DATE, + DATE_LABEL, + FIELD, + NUMBER, + NUMBER_LABEL, + PRIMARY, + REQUIRED_LABEL, + RESET, + SECONDARY, + SELECT, + SELECT_LABEL, + SUBMIT, + SWITCH, + TEXT, + TEXT_DANGER, + TEXT_LABEL, + TEXT_MUTED, + TYPE, + UPDATE_LABEL, +} from "../../strings"; + +export const NAME = "name"; +export const REQUIRED = "required"; + +export const FIELD_NAME_LABEL = "Field Name"; +export const FIELD_NAME_PLACEHOLDER = "Enter field name"; +export const FIELD_NAME_HELP_TEXT = "What is the name of this field?"; +export const FIELD_TYPE_LABEL = "Field Type"; +export const FIELD_TYPE_HELP_TEXT = "What type of field is this?"; +export const FIELD_REQUIRED_HELP_TEXT = "Is this field required?"; export interface HandleFieldsFunction { (values: { [key: string]: string }, log: Log, field: LogFields): void; @@ -70,11 +106,11 @@ export const EditFieldForm: FC = ({ ...fieldState, }} validationSchema={Yup.object({ - name: Yup.string().required("Required"), - type: Yup.string().required("Required"), - option: Yup.string().when("type", { - is: "select", - then: Yup.string().required("Required"), + name: Yup.string().required(REQUIRED_LABEL), + type: Yup.string().required(REQUIRED_LABEL), + option: Yup.string().when(TYPE, { + is: SELECT, + then: Yup.string().required(REQUIRED_LABEL), }), })} onSubmit={(values: { [key: string]: string }) => { @@ -96,30 +132,30 @@ export const EditFieldForm: FC = ({
{/* Name, Type, and Required inputs */} - Field Name + {FIELD_NAME_LABEL} {(touched.name && errors.name && ( - {errors.name} + {errors.name} )) || ( - - This is the name of the field + + {FIELD_NAME_HELP_TEXT} )} - Field Type + {FIELD_TYPE_LABEL} { handleChange(e); const prevValues = { ...values }; @@ -140,51 +176,51 @@ export const EditFieldForm: FC = ({ onBlur={handleBlur} value={values.type} > - - - - + + + + {/* */} - + {(touched.type && errors.type && ( - {errors.type} + {errors.type} )) || ( - - This is the type of the field. + + {FIELD_TYPE_HELP_TEXT} )} - Required + {REQUIRED_LABEL} {(touched.required && errors.required && ( - + {errors.required} )) || ( - - Is this field required? + + {FIELD_REQUIRED_HELP_TEXT} )} - {values.type === "text" && } + {values.type === TEXT && } - {values.type === "number" && } + {values.type === NUMBER && } - {values.type === "date" && } + {values.type === DATE && } - {values.type === "select" && } + {values.type === SELECT && }
{/* Cancel and Submit Buttons */} @@ -192,19 +228,21 @@ export const EditFieldForm: FC = ({ - diff --git a/src/components/EditFieldForm/EditFieldNumber.tsx b/src/components/EditFieldForm/EditFieldNumber.tsx index a8e7908..90a94d0 100644 --- a/src/components/EditFieldForm/EditFieldNumber.tsx +++ b/src/components/EditFieldForm/EditFieldNumber.tsx @@ -2,6 +2,28 @@ import React, { FC, ReactElement } from "react"; import { Accordion, Col, Form, Row } from "react-bootstrap"; import { FormikProps } from "formik"; import { TypeOptionSelect } from "./TypeOptionSelect"; +import { + DEFAULT, + MAX, + MIN, + NONE_LABEL, + NUMBER, + STEP, + STEPS_LABEL, + TEXT, + TEXT_DANGER, + TEXT_MUTED, +} from "../../strings"; + +export const NUMBER_FIELD_OPTIONS = "Number Field Options"; +export const MIN_VALUE = "Min Value"; +export const MAX_VALUE = "Max Value"; +export const UNIT = "unit"; +export const UNIT_LABEL = "Unit"; +export const UNIT_PLACEHOLDER = "Degrees, meters, etc."; +export const DEFAULT_VALUE = "defaultValue"; +export const DEFAULT_VALUE_LABEL = "Default Value"; +export const DEFAULT_VALUE_TEXT = "This is the default value of the field"; export interface EditFieldTextProps extends FormikProps<{ [key: string]: string }> {} @@ -17,7 +39,7 @@ export const EditFieldNumber: FC = ( -
Number Field Options
+
{NUMBER_FIELD_OPTIONS}
@@ -25,36 +47,36 @@ export const EditFieldNumber: FC = ( - {"Min Value"} + {MIN_VALUE} {(touched.min && errors.min && ( - {errors.min} + {errors.min} )) || ( - {"Default: 0"} + {`${DEFAULT}0`} )} - {"Max Value"} + {MAX_VALUE} {(touched.max && errors.max && ( - {errors.max} + {errors.max} )) || ( - - {"Default: 100"} + + {`${DEFAULT}100`} )} @@ -64,36 +86,37 @@ export const EditFieldNumber: FC = ( - {"Steps"} + {STEPS_LABEL} {(touched.step && errors.step && ( - {errors.step} + {errors.step} )) || ( - {"Default: 1"} + {`${DEFAULT}1`} )} - {"Unit"} + {UNIT_LABEL} {(touched.unit && errors.unit && ( - {errors.unit} + {errors.unit} )) || ( - - {"Default: None"} + + {`${DEFAULT}${NONE_LABEL}`} )} @@ -101,22 +124,21 @@ export const EditFieldNumber: FC = ( - {"Default Value"} + {DEFAULT_VALUE_LABEL} {(touched.defaultValue && errors.defaultValue && ( - + {errors.defaultValue} )) || ( - - {"This is the default value of the field"} + + {DEFAULT_VALUE_TEXT} )} diff --git a/src/components/EditFieldForm/EditFieldSelect.tsx b/src/components/EditFieldForm/EditFieldSelect.tsx index 9f3aa6b..8a19a56 100644 --- a/src/components/EditFieldForm/EditFieldSelect.tsx +++ b/src/components/EditFieldForm/EditFieldSelect.tsx @@ -2,10 +2,21 @@ import React, { FC, ReactElement } from "react"; import { Accordion, Col, Form, Row } from "react-bootstrap"; import { FormikProps } from "formik"; import { TypeOptionSelect } from "./TypeOptionSelect"; +import { TEXTAREA, TEXT_DANGER, TEXT_MUTED } from "../../strings"; -export interface EditFieldSelectProps extends FormikProps<{ [key: string]: string }> {} +export const OPTIONS = "options"; -export const EditFieldSelect: FC = (formikProps): ReactElement => { +export const SELECT_FIELD_OPTIONS = "Select Field Options"; +export const SELECT_OPTIONS = "Select Options"; +export const OPTIONS_PLACEHOLDER = "Option1, Option2, Option3"; +export const OPTIONS_LABEL = "Enter options separated by commas"; + +export interface EditFieldSelectProps + extends FormikProps<{ [key: string]: string }> {} + +export const EditFieldSelect: FC = ( + formikProps +): ReactElement => { const { values, errors, touched, handleChange, handleBlur } = formikProps; return ( @@ -14,7 +25,7 @@ export const EditFieldSelect: FC = (formikProps): ReactEle -
Select Field Options
+
{SELECT_FIELD_OPTIONS}
@@ -22,21 +33,23 @@ export const EditFieldSelect: FC = (formikProps): ReactEle - {"Select Options"} + {SELECT_OPTIONS} {(touched.option && errors.option && ( - {errors.option} + + {errors.option} + )) || ( - - {"Enter options separated by commas"} + + {OPTIONS_LABEL} )} @@ -47,4 +60,4 @@ export const EditFieldSelect: FC = (formikProps): ReactEle
); -} \ No newline at end of file +}; diff --git a/src/components/EditFieldForm/EditFieldText.tsx b/src/components/EditFieldForm/EditFieldText.tsx index abc0da2..701ac3f 100644 --- a/src/components/EditFieldForm/EditFieldText.tsx +++ b/src/components/EditFieldForm/EditFieldText.tsx @@ -2,6 +2,26 @@ import React, { FC, ReactElement } from "react"; import { Accordion, Col, Form, Row } from "react-bootstrap"; import { TypeOptionSelect } from "./TypeOptionSelect"; import { FormikProps } from "formik"; +import { + NUMBER, + MAX, + MIN, + DEFAULT, + NONE_LABEL, + NONE, + TEXT, + TEXT_DANGER, + TEXT_MUTED, +} from "../../strings"; + +export const TEXT_FIELD_OPTIONS = "Text Field Options"; +export const MIN_LENGTH = "Min Length"; +export const MAX_LENGTH = "Max Length"; +export const DEFAULT_VALUE = "defaultValue"; +export const DEFAULT_VALUE_LABEL = "Default Value"; +export const DEFAULT_TEXT_VALUE_PLACEHOLDER = + "Enter the default text for this field"; +export const DEFAULT_TEXT_LABEL = "This is the default value of the field"; export interface EditFieldTextProps extends FormikProps<{ [key: string]: string }> {} @@ -14,42 +34,44 @@ export const EditFieldText: FC = (props): ReactElement => { -
Text Field Options
+
{TEXT_FIELD_OPTIONS}
- {"Min Length"} + {MIN_LENGTH} {(touched.min && errors.min && ( - {errors.min} + {errors.min} )) || ( - {"Default: 0"} + {`${DEFAULT}0`} )} - {"Max Length"} + {MAX_LENGTH} {(touched.max && errors.max && ( - {errors.max} + {errors.max} )) || ( - - {"Default: 0 (none)"} + + {`${DEFAULT}0 (${NONE})`} )} @@ -57,22 +79,22 @@ export const EditFieldText: FC = (props): ReactElement => { - {"Default Value"} + {DEFAULT_VALUE_LABEL} {(touched.defaultValue && errors.defaultValue && ( - + {errors.defaultValue} )) || ( - - {"This is the default value of the field"} + + {DEFAULT_TEXT_LABEL} )} diff --git a/src/components/EditFieldForm/TypeOptionSelect.tsx b/src/components/EditFieldForm/TypeOptionSelect.tsx index 2f24f5d..1e43d16 100644 --- a/src/components/EditFieldForm/TypeOptionSelect.tsx +++ b/src/components/EditFieldForm/TypeOptionSelect.tsx @@ -2,8 +2,12 @@ import { FormikProps } from "formik"; import React, { FC, ReactElement } from "react"; import { Form } from "react-bootstrap"; import { initialFieldStates } from "../../store/Log"; +import { SELECT, TEXT_DANGER, TEXT_MUTED } from "../../strings"; import { capitalizeFirstLetter } from "./../../utils"; +export const OPTION = "option"; +export const FIELD_TYPE = " Field Type"; + export interface TypeOptionSelectProps extends FormikProps<{ [key: string]: string }> {} @@ -19,10 +23,13 @@ export const TypeOptionSelect: FC = ({ return ( - {capitalizeFirstLetter(values.type)} Field Type + + {capitalizeFirstLetter(values.type)} + {FIELD_TYPE} + = ({ })} {(touched.option && errors.option && ( - {errors.option} + {errors.option} )) || ( - + {`What type of ${values.type} field is this?`} )} diff --git a/src/components/EditFieldsTable/EditFieldsTable.tsx b/src/components/EditFieldsTable/EditFieldsTable.tsx index 2280c26..fcf7610 100644 --- a/src/components/EditFieldsTable/EditFieldsTable.tsx +++ b/src/components/EditFieldsTable/EditFieldsTable.tsx @@ -1,6 +1,22 @@ import React, { FC, ReactElement } from "react"; import { Dropdown } from "react-bootstrap"; import { initialFieldStates, LogFields } from "../../store/Log"; +import { + ACTIONS, + DELETE, + EDIT_LABEL, + MIDDLE, + NAME_LABEL, + REQUIRED_LABEL, + SECONDARY, + SM, + TEXT_DANGER, + TYPE_LABEL, + TYPE_OPTION_LABEL, +} from "../../strings"; + +export const YES = "Yes"; +export const NO = "No"; interface EditFieldClickFunction { (e: React.MouseEvent, field: LogFields): void; @@ -24,32 +40,32 @@ export const EditFieldsTable: FC = ({ - - - - + + + + {fields.map((field: LogFields) => ( - + - + - @@ -166,7 +192,7 @@ export const Edit: FC = (): ReactElement => { - Field Settings + {FIELD_SETTINGS} { const navigate = useNavigate(); @@ -16,15 +26,15 @@ export const Home: FC = (): ReactElement => { -

Tracker Keeper

-
-

Your logs

+

{TRACKER_KEEPER}

+
+

{YOUR_LOGS}

NameTypeType OptionRequired{NAME_LABEL}{TYPE_LABEL}{TYPE_OPTION_LABEL}{REQUIRED_LABEL} - Actions + {ACTIONS}
{field.name} {field.type} {initialFieldStates[field.type].typeOptions ? field.option : ""} {field.required ? "Yes" : "No"}{field.required ? YES : NO} - Actions + {ACTIONS} = ({ onEditClick(e, field); }} > - Edit + {EDIT_LABEL} { e.preventDefault(); onDeleteClick(e, field.id); }} > - Delete + {DELETE} diff --git a/src/components/EditLabelForm/EditLabelForm.tsx b/src/components/EditLabelForm/EditLabelForm.tsx index 6769fb3..ecfc19f 100644 --- a/src/components/EditLabelForm/EditLabelForm.tsx +++ b/src/components/EditLabelForm/EditLabelForm.tsx @@ -2,6 +2,21 @@ import React, { FC, ReactElement } from "react"; import { Formik } from "formik"; import { InputGroup, Form, Button } from "react-bootstrap"; import { Log, LogFields } from "../../store/Log"; +import { + DATE, + DATE_LABEL, + DEFAULTS, + FIELDS, + LABEL_OPTIONS, + PRIMARY, + SAVE, + SELECT, + SUBMIT, + TEXT, + TEXT_LABEL, +} from "../../strings"; + +export const ENTRY_LABEL = "Entry Label"; export interface EditLabelFormProps { log: Log; @@ -14,7 +29,7 @@ export const EditLabelForm: FC = ({ }): ReactElement => { const { fields } = log as Log; const initialValues = { - labelOption: log.labelOption || "date", + labelOption: log.labelOption || DATE, } as Log & { [key: string]: string }; const logFields: LogFields[] = Object.values(fields || {}); return ( @@ -25,21 +40,21 @@ export const EditLabelForm: FC = ({ {(formikProps) => { return ( - Entry Label + {ENTRY_LABEL} - - - + + + - + {logFields.map((field) => ( diff --git a/src/components/FieldBoolean/FieldBoolean.tsx b/src/components/FieldBoolean/FieldBoolean.tsx index c02b45c..f8e24be 100644 --- a/src/components/FieldBoolean/FieldBoolean.tsx +++ b/src/components/FieldBoolean/FieldBoolean.tsx @@ -2,6 +2,15 @@ import React, { FC, ReactElement } from "react"; import { Form } from "react-bootstrap"; import { FormikProps } from "formik"; import { BooleanLogField } from "../../store/Log"; +import { + ASTERISK, + DEFAULT, + EMPTY, + SWITCH, + TEXT_DANGER, + TEXT_MUTED, + UNDEFINED, +} from "../../strings"; export interface FieldBooleanProps extends FormikProps<{ [key: string]: string }> { @@ -12,9 +21,9 @@ export const FieldBoolean: FC = (props): ReactElement => { const { values, errors, touched, handleChange, handleBlur } = props; const { id: fieldId, name, required, defaultValue } = props.field; - const fieldLabel = `${name}${required ? "*" : ""}`; - const defaultValueString = `Default: ${ - typeof defaultValue === "undefined" ? false : defaultValue + const fieldLabel = `${name}${required ? ASTERISK : EMPTY}`; + const defaultValueString = `${DEFAULT}${ + typeof defaultValue === UNDEFINED ? false : defaultValue }`; return ( @@ -22,7 +31,7 @@ export const FieldBoolean: FC = (props): ReactElement => { {fieldLabel} = (props): ReactElement => { /> {(touched[fieldId] && errors[fieldId] && ( - {errors[fieldId]} + {errors[fieldId]} )) || ( - {defaultValueString} + {defaultValueString} )} diff --git a/src/components/FieldDate/FieldDate.tsx b/src/components/FieldDate/FieldDate.tsx index fb3522a..b290783 100644 --- a/src/components/FieldDate/FieldDate.tsx +++ b/src/components/FieldDate/FieldDate.tsx @@ -2,6 +2,15 @@ import React, { FC, ReactElement } from "react"; import { FormikProps } from "formik"; import { Form } from "react-bootstrap"; import { DateLogField } from "../../store/Log"; +import { + ASTERISK, + DEFAULT, + EMPTY, + NONE, + TEXT_DANGER, + TEXT_MUTED, + UNDEFINED, +} from "../../strings"; export interface FieldDateProps extends FormikProps<{ [key: string]: string }> { field: DateLogField; @@ -11,10 +20,10 @@ export const FieldDate: FC = (props): ReactElement => { const { values, errors, touched, handleChange, handleBlur } = props; const { id: fieldId, name, required, defaultValue, option } = props.field; - const defaultValueString = `Default: ${ - typeof defaultValue === "undefined" ? "none" : defaultValue + const defaultValueString = `${DEFAULT}${ + typeof defaultValue === UNDEFINED ? NONE : defaultValue }`; - const fieldLabel = `${name}${required ? "*" : ""}`; + const fieldLabel = `${name}${required ? ASTERISK : EMPTY}`; return ( <> @@ -25,13 +34,13 @@ export const FieldDate: FC = (props): ReactElement => { name={fieldId} onChange={handleChange} onBlur={handleBlur} - value={values[fieldId] || ""} + value={values[fieldId] || EMPTY} required={required} /> {(touched[fieldId] && errors[fieldId] && ( - {errors[fieldId]} + {errors[fieldId]} )) || ( - {defaultValueString} + {defaultValueString} )} diff --git a/src/components/FieldNumber/FieldNumber.tsx b/src/components/FieldNumber/FieldNumber.tsx index 5b252a6..2f2cd91 100644 --- a/src/components/FieldNumber/FieldNumber.tsx +++ b/src/components/FieldNumber/FieldNumber.tsx @@ -2,6 +2,18 @@ import React, { FC, ReactElement } from "react"; import { FormikProps } from "formik"; import { Form, InputGroup } from "react-bootstrap"; import { NumberLogField } from "../../store/Log"; +import { + ASTERISK, + EMPTY, + NUMBER, + RANGE, + TEXT_DANGER, + TEXT_MUTED, +} from "../../strings"; + +export const VALUE = "Value: "; +export const MIN = "Min: "; +export const MAX = "Max: "; export interface FieldNumberProps extends FormikProps<{ [key: string]: string }> { @@ -21,10 +33,12 @@ export const FieldNumber: FC = (props): ReactElement => { unit, } = props.field; - const fieldLabel = `${name}${required ? "*" : ""}${unit ? ` (${unit})` : ""}`; - const valueLabel = `Value: ${values[fieldId]}`; - const minMaxLabel = `Min: ${min}; Max: ${max};`; - const isRange = option === "range"; + const fieldLabel = `${name}${required ? ASTERISK : EMPTY}${ + unit ? ` (${unit})` : EMPTY + }`; + const valueLabel = `${VALUE}${values[fieldId]}`; + const minMaxLabel = `${MIN}${min}; ${MAX}${max};`; + const isRange = option === RANGE; return ( <> @@ -47,7 +61,7 @@ export const FieldNumber: FC = (props): ReactElement => { )) || ( = (props): ReactElement => { )} {(touched[fieldId] && errors[fieldId] && ( - {errors[fieldId]} + {errors[fieldId]} )) || ( - + {isRange ? valueLabel : minMaxLabel} )} diff --git a/src/components/FieldSelect/FieldSelect.tsx b/src/components/FieldSelect/FieldSelect.tsx index 54cc5c2..a3b6cfd 100644 --- a/src/components/FieldSelect/FieldSelect.tsx +++ b/src/components/FieldSelect/FieldSelect.tsx @@ -2,6 +2,17 @@ import React, { FC, ReactElement } from "react"; import { FormikProps } from "formik"; import { Form } from "react-bootstrap"; import { SelectLogField } from "../../store/Log"; +import { + ASTERISK, + COMMA, + EMPTY, + HYPHEN, + MANY, + TEXT_DANGER, + TEXT_MUTED, +} from "../../strings"; + +export const SELECT_AN_OPTION = "Select an option"; export interface EditFieldSelectProps extends FormikProps<{ [key: string]: string }> { @@ -11,9 +22,9 @@ export interface EditFieldSelectProps export const FieldSelect: FC = (props): ReactElement => { const { values, errors, touched, handleChange, handleBlur } = props; const { id: fieldId, name, required, option, options } = props.field; - const fieldLabel = `${name}${required ? "*" : ""}`; - const selectOptions = options.split(",").map((option) => option.trim()); - const isMulti = option === "many"; + const fieldLabel = `${name}${required ? ASTERISK : EMPTY}`; + const selectOptions = options.split(COMMA).map((option) => option.trim()); + const isMulti = option === MANY; return ( <> @@ -28,7 +39,7 @@ export const FieldSelect: FC = (props): ReactElement => { > {selectOptions.map((option) => ( ); diff --git a/src/components/FieldText/FieldText.tsx b/src/components/FieldText/FieldText.tsx index 6f5673b..cc9f22e 100644 --- a/src/components/FieldText/FieldText.tsx +++ b/src/components/FieldText/FieldText.tsx @@ -2,6 +2,18 @@ import React, { FC, ReactElement } from "react"; import { FormikProps } from "formik"; import { Form } from "react-bootstrap"; import { TextLogField } from "../../store/Log"; +import { + ASTERISK, + DEFAULT, + EMPTY, + INPUT, + NONE, + TEXT, + TEXTAREA, + TEXT_DANGER, + TEXT_MUTED, + UNDEFINED, +} from "../../strings"; export interface FieldTextProps extends FormikProps<{ [key: string]: string }> { field: TextLogField; @@ -11,10 +23,10 @@ export const FieldText: FC = (props): ReactElement => { const { values, errors, touched, handleChange, handleBlur } = props; const { id: fieldId, option, name, required, defaultValue } = props.field; - const inputAs = (option === "textarea" && "textarea") || "input"; - const fieldLabel = `${name}${required ? "*" : ""}`; - const defaultValueString = `Default: ${ - typeof defaultValue === "undefined" ? "none" : defaultValue + const inputAs = (option === TEXTAREA && TEXTAREA) || INPUT; + const fieldLabel = `${name}${required ? ASTERISK : EMPTY}`; + const defaultValueString = `${DEFAULT} ${ + typeof defaultValue === UNDEFINED ? NONE : defaultValue }`; return ( @@ -22,18 +34,18 @@ export const FieldText: FC = (props): ReactElement => { {fieldLabel} {(touched[fieldId] && errors[fieldId] && ( - {errors[fieldId]} + {errors[fieldId]} )) || ( - {defaultValueString} + {defaultValueString} )} diff --git a/src/components/LogNameForm/LogNameForm.tsx b/src/components/LogNameForm/LogNameForm.tsx index 584b671..f9fc420 100644 --- a/src/components/LogNameForm/LogNameForm.tsx +++ b/src/components/LogNameForm/LogNameForm.tsx @@ -3,21 +3,28 @@ import { Formik } from "formik"; import * as yup from "yup"; import { Form, Button, InputGroup } from "react-bootstrap"; import { Log } from "../../store/Log"; +import { EMPTY, PRIMARY, SAVE, SUBMIT, TEXT, TEXT_DANGER } from "../../strings"; + +export const NAME = "name"; + +export const NAME_IS_REQUIRED = "Name is required"; +export const NAME_IS_SPACES = "Name cannot be spaces"; +export const LOG_NAME = "Log Name"; export const LogNameFormValidationSchema = yup.object().shape({ name: yup .string() - .required("Name is required") + .required(NAME_IS_REQUIRED) .test( "is-valid-name", - "Name cannot just be spaces", + NAME_IS_SPACES, (value) => typeof value !== "undefined" && value.trim().length > 0 ), }); export interface LogNameFormProps { log: Log; - onSubmit: (log:Log, values:any) => void; + onSubmit: (log: Log, values: any) => void; } export interface LogNameFormValues { @@ -28,18 +35,13 @@ export const LogNameForm: FC = ({ onSubmit, log, }): ReactElement => { - if (!onSubmit) { - throw new Error("onSubmit is required"); - } const initialValues = { - name: log.name || "", + name: log.name || EMPTY, } as LogNameFormValues; return ( onSubmit(log, values)} + initialValues={initialValues} + onSubmit={(values: any) => onSubmit(log, values)} validationSchema={LogNameFormValidationSchema} > {({ @@ -51,28 +53,28 @@ export const LogNameForm: FC = ({ handleSubmit, }) => (
- Log Name + {LOG_NAME} - {(touched.name && errors.name && ( - {errors.name} - ))} + {touched.name && errors.name && ( + {errors.name} + )}
)}
diff --git a/src/containers/Edit/Edit.tsx b/src/containers/Edit/Edit.tsx index 3c84dfa..2b6ab52 100644 --- a/src/containers/Edit/Edit.tsx +++ b/src/containers/Edit/Edit.tsx @@ -16,6 +16,29 @@ import { LogNameForm } from "../../components/LogNameForm"; import { EditFieldsTable } from "../../components/EditFieldsTable/EditFieldsTable"; import { EditFieldForm } from "../../components/EditFieldForm"; import { EditLabelForm } from "../../components/EditLabelForm"; +import { + ADD, + ADD_ENTRY, + DANGER, + DARK, + HOME, + MODAL, + PRIMARY, + SECONDARY, + SUBMIT, + VIEW_LOG, +} from "../../strings"; + +export const NEW = "new"; +export const EDIT = "edit"; + +export const EDIT_HEADER = "Edit: "; +export const LOG_FIELDS = "Log Fields"; +export const NO_FIELDS_YET = "No fields yet."; +export const ADD_NEW_FIELD = "Add a new field..."; +export const LOG_SETTINGS = "Log Settings"; +export const DELETE_LOG = "Delete Log"; +export const FIELD_SETTINGS = "Field Settings"; export const onUpdateLog = (log: Log, values: any): void => { const updatedLog: Log = { @@ -49,14 +72,14 @@ export const Edit: FC = (): ReactElement => { const [showModal, setShowModal] = React.useState(fid ? true : false); const [modalMode, setModalMode] = React.useState( - fid && fid !== "new" ? "edit" : "add" + fid && fid !== NEW ? EDIT : ADD ); // "add" or "edit" const [fieldId, setFieldId] = React.useState(fid && fid !== "new" ? fid : ""); const resetModal = () => { setShowModal(false); navigate(`/log/${id}/edit`); - setModalMode("add"); + setModalMode(ADD); setFieldId(""); }; @@ -66,14 +89,14 @@ export const Edit: FC = (): ReactElement => { ) => { navigate(`/log/${log.id}/edit/field/${field.id}`); setShowModal(true); - setModalMode("edit"); + setModalMode(EDIT); setFieldId(field.id); }; const onAddField = () => { navigate(`/log/${log.id}/edit/field/new`); setShowModal(true); - setModalMode("add"); + setModalMode(ADD); setFieldId(""); }; @@ -82,7 +105,10 @@ export const Edit: FC = (): ReactElement => { return ( <> -

{`Edit: ${log.name}`}

+

+ {EDIT_HEADER} + {log.name} +

{ > -

Log Fields

+

{LOG_FIELDS}

{fields && fields.length ? ( @@ -105,23 +131,23 @@ export const Edit: FC = (): ReactElement => { onEditClick={onEditField} /> ) : ( -

No fields yet.

+

{NO_FIELDS_YET}

)}
-

Log Settings

+

{LOG_SETTINGS}

@@ -129,11 +155,11 @@ export const Edit: FC = (): ReactElement => {
@@ -141,24 +167,24 @@ export const Edit: FC = (): ReactElement => {
- - + + @@ -42,14 +52,14 @@ export const Home: FC = (): ReactElement => { className="table__dropdown_button" > @@ -58,7 +68,7 @@ export const Home: FC = (): ReactElement => { navigate(`/log/${log.id}/edit`)} > - Edit + {EDIT} { store.dispatch(removeLog({ logId: log.id })); }} > - Delete + {DELETE} @@ -76,16 +86,16 @@ export const Home: FC = (): ReactElement => { ))}
LogActions{LOG}{ACTIONS}
- {logs && logs.length === 0 &&

No logs yet.

} + {logs && logs.length === 0 &&

{NO_LOGS_YET}

}
diff --git a/src/containers/Log/Log.tsx b/src/containers/Log/Log.tsx index e606506..b7c442a 100644 --- a/src/containers/Log/Log.tsx +++ b/src/containers/Log/Log.tsx @@ -17,6 +17,26 @@ import { LogEntry, } from "../../store/Log"; import "./log.scss"; +import { + ACTIONS, + ADD_ENTRY, + BOOLEAN, + DARK, + DATE, + DELETE_ENTRY, + EDIT_ENTRY, + EDIT_LOG, + FALSE, + HOME, + HYPHEN, + PRIMARY, + SECONDARY, + SELECT, + TEXT, +} from "../../strings"; + +export const ENTRIES_HEADER = "Entries "; +export const NO_ENTRIES = "No entries"; export const onDeleteEntry = (log: LogType, entryId: string) => { store.dispatch(removeLogEntry({ logId: log.id, entryId })); @@ -29,8 +49,8 @@ export const Log: FC = (): ReactElement => { const { name, fields, labelOption } = log; const entries: LogEntry[] = Object.values(log.entries || {}); const hasEntries = entries.length > 0; - const isLabelDate = labelOption === "date"; - const isLabelText = labelOption === "text"; + const isLabelDate = labelOption === DATE; + const isLabelText = labelOption === TEXT; return ( @@ -41,13 +61,19 @@ export const Log: FC = (): ReactElement => {
-

{`Entries (${entries.length})`}

+

+ {ENTRIES_HEADER} + {`(${entries.length})`} +

{hasEntries ? ( entries .filter((entry: LogEntry) => entry && entry.values) .sort((a: LogEntry, b: LogEntry) => { // Sort by date created - return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(); + return ( + new Date(b.createdAt).getTime() - + new Date(a.createdAt).getTime() + ); }) .map((entry: LogEntry) => { const labelText = isLabelDate @@ -57,7 +83,7 @@ export const Log: FC = (): ReactElement => { : entry.values[labelOption as string]; return ( - + {labelText} @@ -66,17 +92,19 @@ export const Log: FC = (): ReactElement => { .map((fieldId: string) => { let value; switch (fields[fieldId].type) { - case "date": + case DATE: value = new Date( entry.values[fieldId] as string ).toLocaleString(); break; - case "boolean": - value = entry.values[fieldId] || "false"; + case BOOLEAN: + value = entry.values[fieldId] || FALSE; break; - case "select": + case SELECT: value = Array.isArray(entry.values[fieldId]) - ? ((entry.values[fieldId] as []) || []).join(", ") + ? ((entry.values[fieldId] as []) || []).join( + ", " + ) : entry.values[fieldId]; break; default: @@ -85,7 +113,7 @@ export const Log: FC = (): ReactElement => { return (
{fields[fieldId].name}: @@ -95,8 +123,8 @@ export const Log: FC = (): ReactElement => { })} { navigate(`/log/${id}/entry/${entry.id}`) } > - Edit Entry + {EDIT_ENTRY} onDeleteEntry(log, entry.id)} > - Delete Entry + {DELETE_ENTRY} @@ -117,7 +145,7 @@ export const Log: FC = (): ReactElement => { ); }) ) : ( -

No entries

+

{NO_ENTRIES}

)} @@ -125,30 +153,30 @@ export const Log: FC = (): ReactElement => { diff --git a/src/containers/LogEntry/LogEntry.tsx b/src/containers/LogEntry/LogEntry.tsx index 8d18181..8037316 100644 --- a/src/containers/LogEntry/LogEntry.tsx +++ b/src/containers/LogEntry/LogEntry.tsx @@ -21,6 +21,25 @@ import { FieldNumber } from "../../components/FieldNumber"; import { FieldDate } from "../../components/FieldDate"; import { FieldBoolean } from "../../components/FieldBoolean"; import { FieldSelect } from "../../components/FieldSelect"; +import { + BOOLEAN, + CANCEL, + DATE, + NUMBER, + PRIMARY, + RESET, + SECONDARY, + SELECT, + SUBMIT, + SUBMIT_STRING, + TEXT, + UNDEFINED, +} from "../../strings"; + +export const LABEL = "label"; + +export const ENTRY_HEADER = " Entry"; +export const ENTRY_LABEL = "Entry Label"; export const onLogEntrySubmit = ( values: { [fieldId: string]: FieldValue; label: string }, @@ -60,7 +79,7 @@ export const LogEntry: FC = (): ReactElement | null => { const entry: LogEntryType = useGetLogEntry(logId, entryId); const [cancel, setCancel] = React.useState(false); const [isNewEntry] = React.useState( - typeof entryId === "undefined" || typeof entry === "undefined" + typeof entryId === UNDEFINED || typeof entry === UNDEFINED ); const { name, fields, labelOption } = log; @@ -91,7 +110,10 @@ export const LogEntry: FC = (): ReactElement | null => { -

{`${name} Entry`}

+

+ {name} + {ENTRY_HEADER} +


@@ -103,7 +125,7 @@ export const LogEntry: FC = (): ReactElement | null => { }} > {(formikProps) => { - const isTextLabel = labelOption === "text"; + const isTextLabel = labelOption === TEXT; return (
{ {isTextLabel && ( - Entry Label + {ENTRY_LABEL} { return ( - {type === "text" && ( + {type === TEXT && ( )} - {type === "number" && ( + {type === NUMBER && ( )} - {type === "date" && ( + {type === DATE && ( )} - {type === "boolean" && ( + {type === BOOLEAN && ( )} - {type === "select" && ( + {type === SELECT && ( )} @@ -152,16 +174,16 @@ export const LogEntry: FC = (): ReactElement | null => { - diff --git a/src/containers/New/New.tsx b/src/containers/New/New.tsx index fdf466e..5f4216e 100644 --- a/src/containers/New/New.tsx +++ b/src/containers/New/New.tsx @@ -10,6 +10,13 @@ import { Form, Button } from "react-bootstrap"; import { NavigateFunction, useNavigate } from "react-router-dom"; import store from "../../store/store"; import { addLog } from "../../store/Log"; +import { CANCEL, PRIMARY, SECONDARY, SUBMIT, TEXT, TEXT_MUTED } from "../../strings"; + +export const NEW_LOG = "New Log"; +export const LOG_NAME_LABEL = "Log Name"; +export const LOG_NAME_PLACEHOLDER = "Enter log name"; +export const LOG_NAME_HELP_TEXT = "What is the name of this log?"; +export const CREATE_LOG = "Create Log"; export const onCreateLog = (e: any, navigate: NavigateFunction) => { e.preventDefault(); @@ -30,28 +37,30 @@ export const New: FC = (): ReactElement => { -

New Log

+

{NEW_LOG}

- Log Name - - - This is the name of the log. + {LOG_NAME_LABEL} + + + {LOG_NAME_HELP_TEXT}
+ > + {CANCEL} +   diff --git a/src/index.tsx b/src/index.tsx index 9a76fad..34c3c7d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,11 +6,12 @@ import { PersistGate } from "reduxjs-toolkit-persist/integration/react"; import { App } from "./App"; import reportWebVitals from "./reportWebVitals"; -import * as serviceWorkerRegistration from './serviceWorkerRegistration'; - +import * as serviceWorkerRegistration from "./serviceWorkerRegistration"; +import { FALSE } from "./strings"; +const ROOT: string = "root"; const root: ReactDOM.Root = ReactDOM.createRoot( - document.getElementById("root") as Element | DocumentFragment + document.getElementById(ROOT) as Element | DocumentFragment ); root.render( @@ -30,5 +31,5 @@ serviceWorkerRegistration.register(); // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals reportWebVitals(); -// -document.getElementById("root")?.setAttribute("aria-busy", "false"); +// +document.getElementById(ROOT)?.setAttribute("aria-busy", FALSE); diff --git a/src/strings.ts b/src/strings.ts new file mode 100644 index 0000000..f7761fa --- /dev/null +++ b/src/strings.ts @@ -0,0 +1,68 @@ +// Magic Strings +export const PRIMARY = "primary"; +export const SECONDARY = "secondary"; +export const DANGER = "danger"; +export const DARK = "dark"; +export const TEXT_DANGER = "text-danger"; +export const TEXT_MUTED = "text-muted"; +export const TYPE = "type"; +export const SUBMIT = "submit"; +export const RESET = "reset"; +export const MODAL = "modal"; +export const DATE = "date"; +export const TEXT = "text"; +export const TEXTAREA = "textarea"; +export const INPUT = "input"; +export const NUMBER = "number"; +export const RANGE = "range"; +export const BOOLEAN = "boolean"; +export const SWITCH = "switch"; +export const SELECT = "select"; +export const TRUE = "true"; +export const FALSE = "false"; +export const EMPTY = ""; +export const ASTERISK = "*"; +export const HYPHEN = "-"; +export const UNDEFINED = "undefined"; +export const NONE = "none"; +export const MANY = "many"; +export const LABEL_OPTIONS = "labelOptions"; +export const MIDDLE = "middle"; +export const SM = "sm"; +export const MIN = "min"; +export const MAX = "max"; +export const STEP = "step"; +export const COMMA = ","; +export const COMMA_SPACE = ", "; +export const ADD = "add"; + +// Display Strings +export const HOME = "Home"; +export const EDIT_LOG = "Edit Log"; +export const VIEW_LOG = "View Log"; +export const ADD_ENTRY = "Add Entry"; +export const EDIT_ENTRY = "Edit Entry"; +export const DELETE_ENTRY = "Delete Entry"; +export const ACTIONS = "Actions"; +export const SUBMIT_STRING = "Submit"; +export const SAVE = "Save"; +export const CANCEL = "Cancel"; +export const DELETE = "Delete"; +export const DEFAULT = "Default: "; +export const DEFAULTS = "Defaults"; +export const FIELD = "Field"; +export const FIELDS = "Fields"; +export const NAME_LABEL = "Name"; +export const DATE_LABEL = "Date"; +export const TEXT_LABEL = "Text"; +export const NUMBER_LABEL = "Number"; +export const SELECT_LABEL = "Select"; +export const BOOLEAN_LABEL = "Boolean"; +export const TYPE_LABEL = "Type"; +export const TYPE_OPTION_LABEL = "Type Option"; +export const REQUIRED_LABEL = "Required"; +export const EDIT_LABEL = "Edit"; +export const NONE_LABEL = "None"; +export const STEPS_LABEL = "Steps"; +export const CREATE_LABEL = "Create"; +export const UPDATE_LABEL = "Update";