Joanna Kokot
☕ Frontend Developer @ webco.design
After the approval (switch to true), the date of this operation is stored in a hidden field.
import React from "react";
import { FormBuilderInput } from "@sanity/form-builder/lib/FormBuilderInput";
import Fieldset from "part:@sanity/components/fieldsets/default";
import { setIfMissing } from "@sanity/form-builder/PatchEvent";
import { set, unset } from "part:@sanity/form-builder/patch-event";
import { PatchEvent } from "part:@sanity/form-builder";
const getNow = () => {
return new Date().toISOString();
};
const IsPostApproved = React.forwardRef((props, ref) => {
const {
compareValue,
focusPath,
onBlur,
onChange,
onFocus,
type,
value,
level,
} = props;
const switchInput = React.createRef();
const isApprovedValue = value === undefined ? false : value["isApproved"];
const isDateToUnset =
value === undefined
? false
: value && value["isApproved"] && !isApprovedValue;
const handleFieldChange = React.useCallback(
(field, fieldPatchEvent) => {
onChange(
fieldPatchEvent
.prefixAll(field.name)
.prepend(setIfMissing({ _type: type.name }))
);
!isDateToUnset
? onChange(PatchEvent.from([set(getNow(), ["isApprovedDate"])]))
: onChange(PatchEvent.from([unset(["isApprovedDate"])]));
},
[onChange]
);
const fieldNames = type.fields.map((f) => f.name);
const childPresence =
presence.length === 0 ? presence : presence.filter((item) => fieldNames.includes(item.path[0]));
const childMarkers =
markers.length === 0 ? markers : markers.filter((item) => fieldNames.includes(item.path[0]));
return (
<Fieldset
level={level}
legend={type.title}
description={type.description}
markers={childMarkers}
presence={childPresence}
{type.fields.map((field, i) => {
const fieldMarkers = markers.filter((marker) => marker.path.includes(field.name));
return (
<div key={i}>
<FormBuilderInput
level={level + 1}
ref={i === 0 ? switchInput : null}
key={field.name}
type={field.type}
value={
field.name === "isApproved"
? isApprovedValue
: value && value["isApprovedDate"]
}
onChange={(patchEvent) => handleFieldChange(field, patchEvent)}
path={[field.name]}
focusPath={focusPath}
onFocus={onFocus}
onBlur={onBlur}
compareValue={compareValue}
markers={fieldMarkers}
presence={presence}
/>
</div>
);
})}
</Fieldset>
);
});
export default IsPostApproved;
import React from "react";
import IsPostApproved from "./IsPostApproved";
export default {
name: "post",
title: "Post",
type: "document",
fields: [
{
name: "title",
title: "Title",
type: "string",
},
{
title: "Quality control",
name: "isPostApproved",
type: "object",
inputComponent: IsPostApproved,
fields: [
{
name: "isApproved",
title: "Approve this post",
type: "boolean",
},
{
name: "isApprovedDate",
title: "Approved date",
type: "datetime",
},
],
},
],
};
:global([data-testid='input-isApprovedDate']) {
display: none;
}
The scheme is useful for documents that require information about changes within one specific field (in this example for switch
).
Information about the exact date and time when switch
was set to true
is saved. You can also use the snippet below in the style.css
to hide the field with the visible date and not clutter the user's view in Sanity.
Date and time can be read via queries.
☕ Frontend Developer @ webco.design