import { Box, Button } from "@prismicio/editor-ui"; import { Field, Form, Formik } from "formik"; import { camelCase } from "lodash"; import React, { useEffect, useState } from "react"; import Select from "react-select"; import { Input, Label, Text } from "theme-ui"; import Card from "@/legacy/components/Card/Default"; import SliceMachineModal from "@/legacy/components/SliceMachineModal"; import { VariationSM } from "@/legacy/lib/models/common/Slice"; const Error = ({ msg }: { msg?: string }) => ( {/* eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/prefer-nullish-coalescing */} {msg || "Error!"} ); const AddVariationModal: React.FunctionComponent<{ isOpen: boolean; loading?: boolean; // eslint-disable-next-line @typescript-eslint/no-explicit-any onClose: () => any; onSubmit: ( id: string, name: string, copiedVariation: VariationSM, ) => Promise; initialVariation: VariationSM; variations: ReadonlyArray; }> = ({ isOpen, onClose, onSubmit, initialVariation, variations }) => { const [errors, setErrors] = useState<{ [fieldKey: string]: string }>({}); const [generatedId, setGeneratedId] = useState(""); const [isGeneratedFromName, setIsGeneratedFromName] = useState(true); const [name, setName] = useState(""); const [origin, setOrigin] = useState<{ value: string; label: string }>({ value: initialVariation.id, label: initialVariation.name, }); const [isAddingVariation, setIsAddingVariation] = useState(false); function validateForm({ id, name, origin, }: { id?: string; name?: string; origin: { value: string }; }) { // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions const idError = !(id && id.length) ? { id: "Required!" } : null; const existingIdError = variations.find((v) => v.id === id) ? { id: "This id already exists!" } : null; // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions const nameError = !(name && name.length) ? { name: "Required!" } : null; const originError = !( origin.value.length && variations.find((v) => v.id === origin.value) ) ? { id: "You must select an existing variation!" } : null; // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions const invalidIdError = id && id.length && !/^[A-Za-z0-9]+([A-Za-z0-9]+)*$/.exec(id) && { id: "No special characters allowed", }; return { ...idError, ...existingIdError, ...nameError, ...originError, ...invalidIdError, }; } function generateId(str: string) { const slug = camelCase(str); setGeneratedId(slug); } function changeName(str: string) { setName(str); if (isGeneratedFromName) generateId(str); } function changeId(str: string) { setIsGeneratedFromName(false); generateId(str); } function handleClose() { reset(); onClose(); } function reset() { setGeneratedId(""); setName(""); setErrors({}); setIsGeneratedFromName(true); setOrigin({ value: initialVariation.id, label: initialVariation.name }); } useEffect(() => { reset(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [initialVariation, isOpen]); // eslint-disable-next-line @typescript-eslint/require-await async function handleSubmit() { const data = { id: generatedId, name, origin }; const errors = validateForm(data); if (Object.keys(errors).length) setErrors(errors); else { const copiedVariation = variations.find((v) => v.id === origin.value); if (copiedVariation) { setIsAddingVariation(true); await onSubmit(generatedId, name, copiedVariation); setIsAddingVariation(false); handleClose(); } } } return ( handleClose()} contentLabel="Widget Form Modal" style={{ content: { maxWidth: "700px", }, }} >
{ if (e.key === "Enter") { e.preventDefault(); // eslint-disable-next-line @typescript-eslint/no-floating-promises handleSubmit(); } }} > Add new Variation} FooterContent={ } close={handleClose} > ) => changeName(e.currentTarget.value) } /> It will appear here in Slice Machine, and in the page editor in Prismic ) => changeId(e.currentTarget.value) } /> It's generated automatically based on the variation name and will appear in the API responses.