fix admin save state architecture

This commit is contained in:
MOH
2026-03-10 05:24:50 +01:00
parent e219295327
commit f2b5a15191
12 changed files with 123 additions and 38 deletions
+7 -2
View File
@@ -5,22 +5,27 @@ import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check } from "lucide-react";
import { cn } from "@/lib/utils";
import { useHiddenInputSync } from "@/components/ui/use-hidden-input-sync";
type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> & {
name?: string;
checkedValue?: string;
uncheckedValue?: string;
};
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
CheckboxProps
>(({ className, name, checked, defaultChecked, onCheckedChange, ...props }, ref) => {
>(({ className, name, checked, defaultChecked, onCheckedChange, checkedValue = "on", uncheckedValue = "false", ...props }, ref) => {
const [internalChecked, setInternalChecked] = React.useState(defaultChecked === true);
const isControlled = checked !== undefined;
const currentChecked = isControlled ? checked === true : internalChecked;
const hiddenValue = currentChecked ? checkedValue : uncheckedValue;
const hiddenInputRef = useHiddenInputSync(hiddenValue);
return (
<>
{name ? <input type="hidden" name={name} value={currentChecked ? "on" : "false"} /> : null}
{name ? <input ref={hiddenInputRef} type="hidden" name={name} value={hiddenValue} /> : null}
<CheckboxPrimitive.Root
ref={ref}
checked={checked}
+3 -1
View File
@@ -5,6 +5,7 @@ import * as SelectPrimitive from "@radix-ui/react-select";
import { Check, ChevronDown, ChevronUp } from "lucide-react";
import { cn } from "@/lib/utils";
import { useHiddenInputSync } from "@/components/ui/use-hidden-input-sync";
type SelectProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {
name?: string;
@@ -23,10 +24,11 @@ function Select({
const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");
const isControlled = value !== undefined;
const currentValue = (isControlled ? value : internalValue) as string;
const hiddenInputRef = useHiddenInputSync(currentValue);
return (
<>
{name ? <input type="hidden" name={name} value={currentValue} required={required} /> : null}
{name ? <input ref={hiddenInputRef} type="hidden" name={name} value={currentValue} required={required} /> : null}
<SelectPrimitive.Root
value={value}
defaultValue={defaultValue}
+26
View File
@@ -0,0 +1,26 @@
"use client";
import * as React from "react";
export function useHiddenInputSync(value: string) {
const inputRef = React.useRef<HTMLInputElement | null>(null);
const mountedRef = React.useRef(false);
React.useEffect(() => {
const input = inputRef.current;
if (!input) {
return;
}
if (!mountedRef.current) {
mountedRef.current = true;
return;
}
input.dispatchEvent(new Event("input", { bubbles: true }));
input.dispatchEvent(new Event("change", { bubbles: true }));
}, [value]);
return inputRef;
}