feat: added are you sure dialog

This commit is contained in:
Dan Ditomaso
2025-03-09 12:57:37 -04:00
parent 39f26f475b
commit eca5d780c1
26 changed files with 669 additions and 147 deletions
+21 -17
View File
@@ -19,28 +19,32 @@ export interface MultiSelectFieldProps<T> extends BaseFormBuilderProps<T> {
};
}
const formatEnumDisplay = (name: string): string => {
return name
.replace(/_/g, " ")
.toLowerCase()
.split(" ")
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
.join(" ");
};
export function MultiSelectInput<T extends FieldValues>({
field,
}: GenericFormElementProps<T, MultiSelectFieldProps<T>>) {
const { enumValue, formatEnumName, ...remainingProperties } =
field.properties;
// Make sure to filter out the UNSET value, as it shouldn't be shown in the UI
const optionsEnumValues = enumValue
? Object.entries(enumValue)
.filter((value) => typeof value[1] === "number")
.filter((value) => value[0] !== "UNSET")
: [];
const valueToKeyMap: Record<string, string> = {};
const optionsEnumValues: [string, number][] = [];
const formatName = (name: string) => {
if (!formatEnumName) return name;
return name
.replace(/_/g, " ")
.toLowerCase()
.split(" ")
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
.join(" ");
};
if (enumValue) {
Object.entries(enumValue).forEach(([key, val]) => {
if (typeof val === "number" && key !== "UNSET") {
valueToKeyMap[val.toString()] = key;
optionsEnumValues.push([key, val as number]);
}
});
}
return (
<MultiSelect {...remainingProperties}>
@@ -52,9 +56,9 @@ export function MultiSelectInput<T extends FieldValues>({
checked={field.isChecked(name)}
onCheckedChange={() => field.onValueChange(name)}
>
{formatEnumName ? formatName(name) : name}
{formatEnumName ? formatEnumDisplay(name) : name}
</MultiSelectItem>
))}
</MultiSelect>
);
}
}
+77 -47
View File
@@ -9,11 +9,12 @@ import {
SelectTrigger,
SelectValue,
} from "@components/UI/Select.tsx";
import { Controller, type FieldValues } from "react-hook-form";
import { useController, type FieldValues } from "react-hook-form";
export interface SelectFieldProps<T> extends BaseFormBuilderProps<T> {
type: "select";
selectChange?: (e: string) => void;
selectChange?: (e: string, name: string) => void;
onBeforeChange?: (newValue: string, prevValue: string) => Promise<string | false>;
properties: BaseFormBuilderProps<T>["properties"] & {
enumValue: {
[s: string]: string | number;
@@ -22,56 +23,85 @@ export interface SelectFieldProps<T> extends BaseFormBuilderProps<T> {
};
}
const formatEnumDisplay = (name: string): string => {
return name
.replace(/_/g, " ")
.toLowerCase()
.split(" ")
.map((s) => s.charAt(0).toUpperCase() + s.substring(1))
.join(" ");
};
export function SelectInput<T extends FieldValues>({
control,
disabled,
field,
}: GenericFormElementProps<T, SelectFieldProps<T>>) {
const {
field: { value, onChange, ...rest },
} = useController({
name: field.name,
control,
});
const { enumValue, formatEnumName, ...remainingProperties } = field.properties;
const valueToKeyMap: Record<string, string> = {};
const keyToValueMap: Record<string, number> = {};
const optionsEnumValues: [string, number][] = [];
if (enumValue) {
Object.entries(enumValue).forEach(([key, val]) => {
if (typeof val === "number") {
valueToKeyMap[val.toString()] = key; // Map enum value to key
keyToValueMap[key] = val; // Map key to enum value
optionsEnumValues.push([key, val]);
}
});
}
const handleValueChange = async (newValue: string) => {
const selectedKey = valueToKeyMap[newValue];
if (!selectedKey) return;
if (field.onBeforeChange) {
try {
const result = await field.onBeforeChange(selectedKey, valueToKeyMap[value?.toString()]);
if (result === false) return;
const updatedValue = keyToValueMap[result];
if (updatedValue !== undefined) {
if (field.selectChange) field.selectChange(updatedValue.toString(), result);
onChange(updatedValue);
}
} catch (error) {
console.error("Error in onBeforeChange function:", error);
}
} else {
if (field.selectChange) field.selectChange(newValue, selectedKey);
onChange(Number.parseInt(newValue));
}
};
return (
<Controller
name={field.name}
control={control}
render={({ field: { value, onChange, ...rest } }) => {
const { enumValue, formatEnumName, ...remainingProperties } =
field.properties;
const optionsEnumValues = enumValue
? Object.entries(enumValue).filter(
(value) => typeof value[1] === "number",
)
: [];
return (
<Select
onValueChange={(e) => {
if (field.selectChange) field.selectChange(e);
onChange(Number.parseInt(e));
}}
disabled={disabled}
value={value?.toString()}
{...remainingProperties}
{...rest}
>
<SelectTrigger id={field.name}>
<SelectValue />
</SelectTrigger>
<SelectContent>
{optionsEnumValues.map(([name, value]) => (
<SelectItem key={name} value={value.toString()}>
{formatEnumName
? name
.replace(/_/g, " ")
.toLowerCase()
.split(" ")
.map((s) =>
s.charAt(0).toUpperCase() + s.substring(1)
)
.join(" ")
: name}
</SelectItem>
))}
</SelectContent>
</Select>
);
}}
/>
<Select
onValueChange={handleValueChange}
disabled={disabled}
value={value?.toString()}
{...remainingProperties}
{...rest}
>
<SelectTrigger id={field.name}>
<SelectValue />
</SelectTrigger>
<SelectContent>
{optionsEnumValues.map(([name, val]) => (
<SelectItem key={name} value={val.toString()}>
{formatEnumName ? formatEnumDisplay(name) : name}
</SelectItem>
))}
</SelectContent>
</Select>
);
}