Skip to content

Commit

Permalink
add deal reg form handler; fix various form issues
Browse files Browse the repository at this point in the history
  • Loading branch information
thatmattlove committed Aug 14, 2024
1 parent 9feee84 commit b1fe57f
Show file tree
Hide file tree
Showing 11 changed files with 81 additions and 29 deletions.
21 changes: 12 additions & 9 deletions lib/address-types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export interface SearchResult {
address: string;
name: string;
displayName: string;
description: string;
formValue: string;
}

export interface SearchError {
Expand All @@ -18,10 +19,12 @@ export function isSearchResults(data: unknown): data is SearchResult[] {
return (
typeof data[0] === "object" &&
data[0] !== null &&
"address" in data[0] &&
"name" in data[0] &&
typeof data[0].address === "string" &&
typeof data[0].name === "string"
"displayName" in data[0] &&
"formValue" in data[0] &&
"description" in data[0] &&
typeof data[0].displayName === "string" &&
typeof data[0].formValue === "string" &&
typeof data[0].description === "string"
);
}
return Array.isArray(data);
Expand All @@ -43,14 +46,14 @@ export function isMapboxCity(data: Suggestion): boolean {
}

export function formatCity(data: Suggestion): SearchResult {
const name = [data.name, data.context.region.region_code].join(", ");
const displayName = [data.name, data.context.region.region_code].join(", ");
let addressParts: string[] = [];
if (typeof data.context.district !== "undefined") {
addressParts = [...addressParts, data.context.district.name];
}
addressParts = [...addressParts, data.context.region.name, data.context.country.name];
const address = addressParts.join(", ");
return { name, address };
const description = addressParts.join(", ");
return { displayName, description, formValue: displayName };
}

export interface MapboxSearchResult {
Expand Down
21 changes: 21 additions & 0 deletions lib/api/form/deal-registration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isbot } from "isbot";
import type { NextApiRequest } from "next";
import { isValidJsonRequest } from "~/lib";

export async function handleDealRegistrationForm(request: NextApiRequest): Promise<Response> {
if (!isValidJsonRequest(request)) {
throw new Error("Invalid request payload");
}
if (isbot(request.headers["user-agent"])) {
throw new Error("You seem like a robot");
}
let form = "unknown";
if (typeof request.url !== "undefined") {
const [withoutQuery] = request.url.split("?");
const paths = withoutQuery.split("/");
form = paths[paths.length - 1];
}
const data = request.body;
console.log(form, data);
return new Response("neat", { status: 200 });
}
1 change: 1 addition & 0 deletions lib/api/form/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./deal-registration";
export * from "./partnership";
export * from "./sales";
export * from "./subscribe";
Expand Down
5 changes: 3 additions & 2 deletions lib/server/address.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ export async function search(
return results;
}
const results: SearchResult[] = data.suggestions.map(suggestion => ({
address: suggestion.full_address,
name: suggestion.name,
displayName: suggestion.name,
formValue: suggestion.full_address,
description: suggestion.full_address,
}));
return results;
}
2 changes: 2 additions & 0 deletions pages/api/form/[name].ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
handleDealRegistrationForm,
handlePartnershipForm,
handleSalesForm,
handleSubscribe,
Expand All @@ -18,6 +19,7 @@ const FORM_MAP = new Map<FormKeys | string, FormHandler>([
["security-demo", handleSalesForm],
["trial", handleTrialForm],
["partnership-inquiry", handlePartnershipForm],
["deal-registration", handleDealRegistrationForm],
]);

function isValidForm(form: unknown): form is FormKeys {
Expand Down
2 changes: 1 addition & 1 deletion src/components/form/checkbox-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const CheckboxField = <V extends FieldValues>(
</Stack>
</CheckboxGroup>
) : (
<RadioGroup {...rest}>
<RadioGroup defaultValue={opts[0].value} {...rest}>
<Stack spacing={[1, 5]} direction={["column", "row"]}>
{opts.map(opt => (
<Radio
Expand Down
2 changes: 1 addition & 1 deletion src/components/form/currency-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const CurrencyField = <V extends FieldValues>(
<InputLeftElement pointerEvents="none" opacity={0.5} fontSize="large">
{field.unitSymbol}
</InputLeftElement>
<NumberInput min={1} precision={2}>
<NumberInput min={0} precision={2}>
<NumberInputField
pl={8}
{...register(name, { required: field.required, ...rules })}
Expand Down
10 changes: 4 additions & 6 deletions src/components/form/date-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,20 @@ export const DateField = <V extends FieldValues>(props: DateFieldProps<CalendarP
const { onClose, isOpen, onOpen } = useDisclosure();

const [dates, setDates] = useState<CalendarValues>({});
const [formValue, setFormValue] = useState("");
const [displayValue, setDisplayValue] = useState<string>();
const initialRef = useRef(null);

const { control } = useFormContext<V>();
const { control, register } = useFormContext<V>();

const {
field: { onChange, ref },
field: { onChange },
fieldState: { error },
} = useController<V>({ name, control, rules: { required }, defaultValue });

const onDateChange = (changed: CalendarDate | CalendarValues): void => {
if (changed instanceof Date) {
setDisplayValue(changed.toLocaleDateString(undefined, { dateStyle: "full" }));
setFormValue(changed.toISOString());
onChange(formValue);
onChange(changed);
onClose();
setDates({ start: changed, end: changed });
}
Expand All @@ -79,7 +77,7 @@ export const DateField = <V extends FieldValues>(props: DateFieldProps<CalendarP
>
<FormLabel as="legend">{label ? label : displayName}</FormLabel>
<Input readOnly value={displayValue} placeholder="Select Date" />
<input readOnly name={name} ref={ref} hidden value={formValue} />
<input readOnly hidden {...register(name, { required: field.required, ...rules })} />
<FormErrorMessage>{typeof error !== "undefined" && error.message}</FormErrorMessage>
</FormControl>
</PopoverTrigger>
Expand Down
27 changes: 22 additions & 5 deletions src/components/form/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { TextInputValidationType } from "~/types";
import {
isAddressSearchField,
isCheckboxField,
isCurrencyField,
isDateField,
isSelectField,
isTextAreaField,
Expand Down Expand Up @@ -62,12 +63,19 @@ export function createSchema<Fields extends BaseFormField[]>(

// Checkbox or Select
if (isCheckboxField(fieldConfig) || isSelectField(fieldConfig)) {
value = z.array(z.string());
if (fieldConfig.multiple) {
value = z.array(z.string());

if (fieldConfig.required) {
value = createRequiredArray(fieldConfig);
}
if (fieldConfig.required) {
value = createRequiredArray(fieldConfig);
}
} else {
value = z.string();

if (fieldConfig.required) {
value = createRequiredString(fieldConfig);
}
}
// Add field to schema
is(value) && (final[fieldConfig.formId] = value);
return final;
Expand All @@ -80,7 +88,16 @@ export function createSchema<Fields extends BaseFormField[]>(
value = z.date();
is(value) && (final[fieldConfig.formId] = value);
return final;
} // Text Area
} // Currency Field
else if (isCurrencyField(fieldConfig)) {
value = z.coerce.number();
if (fieldConfig.required) {
value = value.min(1);
}
is(value) && (final[fieldConfig.formId] = value);
return final;
}
// Text Area
else if (isTextAreaField(fieldConfig)) {
value = z.string();

Expand Down
13 changes: 9 additions & 4 deletions src/components/form/select-field.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,19 @@ export const SelectField = (props: SelectFieldProps) => {

const handleSelect = useCallback(
(values: readonly SelectOptionSingle[]) => {
if (values.length === 0) {
if (values.length === 0 || values === null) {
setValue(name, defaultValue);
onChange(defaultValue);
return;
}
const labels = values.filter(v => !!v.label).map(v => v.label);
setValue(name, labels);
onChange(labels);
if (isMulti) {
const labels = values.filter(v => !!v.label).map(v => v.label);
setValue(name, labels);
onChange(labels);
} else {
setValue(name, values[0].label);
onChange(values[0].label);
}
},
[name, setValue],
);
Expand Down
6 changes: 5 additions & 1 deletion src/hooks/use-address-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ async function queryFn(search: string, locationType: LocationType): Promise<Sele
throw new Error(data.error);
}
if (isSearchResults(data)) {
return data.map(d => ({ label: d.name, value: d.address, description: d.address }));
return data.map(d => ({
label: d.displayName,
value: d.formValue,
description: d.description,
}));
}
throw new Error(data);
}
Expand Down

0 comments on commit b1fe57f

Please sign in to comment.