Source: data/Form.js

import React, { useRef, useState } from "react";
import { useReactorNavigation } from "../../_core";
import { booleanString, FormContext, useValidationSchema, useWebAuthn } from "../..";
import { FormExt } from ".";
import { getFormData } from "./FormExt";

/**
 * Componente que renderiza un formulario html.
 * Todos los input dentro de Form deben contener la propiedad name con el identificador del campo.
 * Si se incluye la propiedad to, se va a rendericar un <a href="Reactor.Components.Data.FormExt.html">FormExt</a>
 * @name Reactor.Components.Data.Form
 * @param {string} action Nombre de la operación de destino
 * @param {JsonString} data Datos que se agregan al post del form para evitar inputs de tipo hidden
 * @param {NavigationTarget} target Destino del resultado 
 * @param {DirectionType} direction Dirección en la que va a mostrarse el menú
 * @param {string} offcanvas_class Clase css que se va a dar al menú 
 * @param {BooleanString} [debug = "false"] Establece modo de depuracion
 * @param {BooleanString} [webauthn_check = "false"] Establece si debe requerir autenticacion por medio de webauthn para ejecutar el evento submit
 * @class
 * @example
<form action="ProductoDepositar" target="menu" direction="bottom" offcanvas_class="rounded-m"> 
  <div class="menu-size" style="height:auto;" >
    <div class="content mt-0 mb-2">
      <div class="form-custom form-label form-icon">
        <i class="bi bi-check-circle font-13"></i>
        <select class="form-select rounded-xs" name="medioPago" value="{{opcionSeleccionada}}" aria-label="">
          <optgroup label="Medios de Pago">          
            {{opciones|OpcionCombo}}
          </optgroup>
        </select>
        <label for="medioPago" class="form-label-always-active color-highlight font-11">Medio de pago</label>
      </div>
      <div class="pb-3"></div>
      <div class="form-custom form-label form-icon">
        <i class="bi bi-hash font-14"></i>
        <input type="number" class="form-control rounded-xs" name="importe" placeholder="ingrese el monto">
        <label for="importe" class="form-label-always-active color-highlight font-11">Importe</label>
        <span class="font-10">( Moneda: $ ARG )</span>
      </div>
      <div class="pb-3"></div>
      <input type="submit" class="form-control rounded-xs btn btn-full gradient-highlight shadow-bg shadow-bg-s" value="Depositar" offcanvas_class="rounded-m">
    </div>
  </div>
</form>
 */


export const Form = ({ action, direction, target, children, offcanvas_class, data = "{}", debug = "false", webauthn_check = "false", ...props }) => {

  const [formInputData, setFormInputData ] = useState({})
  const navigation = useReactorNavigation({target, to: action, direction, offcanvasClass: offcanvas_class});
  const ref = useRef();
  const { assertionCheck } = useWebAuthn();

  if(props.to) return <FormExt {...{action, direction, target, children, offcanvas_class, data, debug, ...props}} />

  const isValid = (data, fn) => {
    fn(data);
    /*
    if(validation.validationSchema){
      validation.isValid({data})
        .then(()=>{
          fn(data);
        })
        .catch(()=>{})
    }else{
      fn(data);
    }*/
  }

  const submit = () => {
    if(booleanString(debug)){
      console.log({action, direction, target, children, offcanvas_class, data , debug, props})
    }
    const allData = {...getFormData(ref.current), ...JSON.parse(data)};
    if(booleanString(debug)){
      console.log({allData})
    }
    navigation.execute(allData);
  }

  const handleSubmit = (event) => {
    event?.preventDefault();
    event?.stopPropagation();
    if(booleanString(webauthn_check)){
      assertionCheck()
        .then(()=>{
          submit();
        })
        .catch(()=>{});
    }else{
      submit();
    }    
  }

  const handleChange = (event) => {
    setFormInputData({...getFormData(ref.current), ...JSON.parse(data), event: "change", element: event.target.name});
  }

  return (
    <FormContext.Provider value={{submit: handleSubmit, change: handleChange, formInputData}}>
      <form 
        ref={ref}
        onSubmit={handleSubmit}
        onChange={handleChange}
      >
        {children}
      </form>
    </FormContext.Provider>
  )

}