React Native modal TextInput doesn’t work

The keyboard does not appear and I cannot add quantity.

View:

import React, { useState, useEffect } from "react";
import {
  View,
  Text,
  TouchableOpacity,
  ActivityIndicator,
  Modal,
  StyleSheet,
  Alert
} from "react-native";
import { globalStyles } from "../globalStyles.js";
import { styles } from "./styles.js"; // Importamos los estilos desde styles.js
import * as RootNavigation from "../../utils/navigator/RootNavigation.js";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { PedidosComercialLogic } from "./PedidosComercialLogic";
import { Button } from "@rneui/themed";
import { FlashList } from "@shopify/flash-list";
import { SearchInput } from "../otros/SearchInput";
import { useGlobalContext } from "../../utils/context/GlobalContextProvider.js";
import { useInternetContext } from "../../utils/context/InternetContextProvider.js";
import { PdaUser } from "../../class/PdaUser.class";
import QuantitySelector from "../otros/QuantitySelector.jsx";
import { HOME } from "../../utils/const/navigatorConst.js";
import { getSecureStoreData } from "../../utils/gettersAndSetters/getters.js";
import { SHOW_PRICE_WITH_TAX } from "../../utils/const/secureStoreConst.js";
import PdfTabNavigator from "../otros/pdfView/PdfTabNavigator.jsx";
import ListadoPedidos from "../pedidos/ListadoPedidos.jsx";

const PedidosComercialScreenView = (props) => {
  const [clientProducts, setClientProducts] = useState([]);
  const [products, setProducts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [user, setUser] = useState(new PdaUser());
  const [globalState, setGlobalState] = useGlobalContext();
  const [searchText, setSearchText] = useState("");
  const selectedClientId = props.cliente.client;
  const [showAllProducts, setShowAllProducts] = useState(false);
  const [showCobros, setShowCobros] = useState(false);
  const [allProducts, setAllProducts] = useState([]);
  const [quantities, setQuantities] = useState({});
  const [isQuantityModalVisible, setQuantityModalVisible] = useState(false);
  const [selectedProduct, setSelectedProduct] = useState(null);
  const [isPurchaseModalVisible, setPurchaseModalVisible] = useState(false);
  const [totalPurchase, setTotalPurchase] = useState(0);
  const [showFinalizeOptionsModal, setShowFinalizeOptionsModal] =
    useState(false);
  const [internetState, setInternetState] = useInternetContext();
  const [showPriceWithTax, setShowPriceWithTax] = useState(false);
  const [visibleData, setVisibleData] = useState([]);
  const [pdfUrls, setPdfUrls] = useState([]);
  const [pendingPayments, setPendingPayments] = useState([]);
  const [isPendingPaymentsModalVisible, setPendingPaymentsModalVisible] =
    useState(false);
  const itemsPerPage = 10;
  const [page, setPage] = useState(1);

  var DEV = new PedidosComercialLogic({
    clientProducts,
    setClientProducts,
    products,
    setProducts,
    setLoading,
    setUser,
    user,
    setGlobalState,
    globalState,
    selectedClientId,
  });

  useEffect(() => {
    async function fetchData() {
      const showPriceWithTax = await getSecureStoreData(SHOW_PRICE_WITH_TAX);
      setShowPriceWithTax(showPriceWithTax === "true");
      await DEV.init();
      if (internetState.isConnected) {
        try {
          await DEV.getProductsByOrders(props.cliente.client);
          await DEV.getProducts();
        } catch (error) {
          console.error("Error al cargar clientes:", error);
        }
      } else {
        try {
          await DEV.getLocalProductsByOrders();
          await DEV.getLocalProducts();
        } catch (error) {
          console.error("Error al cargar clientes:", error);
        }
      }

      try {
        const totalDue = await DEV.getTotalDueByClient(props.cliente.client);
        setPendingPayments(totalDue);
        setPendingPaymentsModalVisible(true);
      } catch (error) {
        console.error("Error fetching total due:", error);
        Alert.alert("Error", "Problemas al obtener los pagos pendientes.");
      }
    }
    fetchData();
  }, []);

  useEffect(() => {
    mergeProducts(clientProducts, products);
  }, [products, clientProducts]);

  useEffect(() => {
    setVisibleData(filteredProducts.slice(0, itemsPerPage));
    setPage(1);
  }, [allProducts, showAllProducts, filteredProducts]);

  useEffect(() => {
    const filtered = allProducts.filter(
      (product) =>
        (product.label || "")
          .toLowerCase()
          .includes(searchText.toLowerCase()) &&
        (showAllProducts ? product.client === 0 : product.client === 1)
    );
    setVisibleData(filtered.slice(0, itemsPerPage));
    setPage(1);
  }, [searchText, allProducts, showAllProducts]);

  const loadMoreData = () => {
    const filtered = allProducts.filter(
      (product) =>
        (product.label || "")
          .toLowerCase()
          .includes(searchText.toLowerCase()) &&
        (showAllProducts ? product.client === 0 : product.client === 1)
    );
    const startIndex = page * itemsPerPage;
    const endIndex = startIndex + itemsPerPage;
    const newData = filtered.slice(startIndex, endIndex);

    setPage(page + 1);
    setVisibleData((prevData) => [...prevData, ...newData]);
  };

  const mergeProducts = async (clientProducts, products) => {
    const productMap = new Map();
    products.forEach((product) => {
      if (product.fkProduct != null) {
        productMap.set(product.fkProduct, {
          ...product,
          client: 0,
          quantity: 0,
          productStock: product.productStock || 0,
        });
      }
    });

    clientProducts.forEach((product) => {
      if (product.fkProduct != null) {
        const existingProduct = productMap.get(product.fkProduct);
        if (existingProduct) {
          productMap.set(product.fkProduct, {
            ...existingProduct,
            ...product,
            productStock:
              product.productStock || existingProduct.productStock || 0,
            client: 1,
          });
        } else {
          productMap.set(product.fkProduct, {
            ...product,
            client: 1,
            productStock: product.productStock || 0,
          });
        }
      }
    });

    const arrayMerge = Array.from(productMap.values());
    setAllProducts(arrayMerge);

    if (internetState.isConnected) {
      await DEV.saveProductsLocal(arrayMerge);
    }

    setLoading(false);
  };

  const handleSearch = (text) => {
    setSearchText(text);
  };

  const toggleProductList = () => {
    setLoading(true);
    setShowAllProducts(!showAllProducts);
    setLoading(false);
  };

  const addProductToClient = (product) => {
    setSelectedProduct(product);
    setQuantityModalVisible(true);
  };

  const handleQuantitySave = (quantity, subprice, discount) => {
    console.log("CANTIDAD", subprice)
    setQuantities((prevQuantities) => ({
      ...prevQuantities,
      [selectedProduct.fkProduct]: quantity,
    }));

    const updatedClientProducts = clientProducts.map((product) => {
      if (product.fkProduct === selectedProduct.fkProduct) {
        return {
          ...product,
          quantity,
          subprice: subprice,
          remise_percent: discount,
          client: 1,
        };
      }
      return product;
    });

    if (
      !updatedClientProducts.find(
        (product) => product.fkProduct === selectedProduct.fkProduct
      )
    ) {
      updatedClientProducts.push({
        ...selectedProduct,
        quantity,
        subprice: subprice,
        remise_percent: discount,
        client: 1,
      });
    }

    setClientProducts(updatedClientProducts);
    mergeProducts(updatedClientProducts, products);
    setQuantityModalVisible(false);
  };

  const removeProductFromClient = (fkProduct) => {
    setLoading(true);

    const remainingClientProducts = clientProducts.filter(
      (product) => product.fkProduct !== fkProduct
    );
    const updatedProducts = products.map((product) => {
      if (product.fkProduct === fkProduct) {
        return { ...product, client: 0, quantity: 0 };
      }
      return product;
    });

    setClientProducts(remainingClientProducts);
    setProducts(updatedProducts);
    mergeProducts(remainingClientProducts, updatedProducts);
    setLoading(false);
  };

  const handleQuantityChange = (fkProduct, newQuantity) => {
    setQuantities((currentQuantities) => ({
      ...currentQuantities,
      [fkProduct]: newQuantity,
    }));

    if (newQuantity === 0) {
      removeProductFromClient(fkProduct);
    } else {
      const updatedClientProducts = clientProducts.map((product) =>
        product.fkProduct === fkProduct
          ? { ...product, quantity: newQuantity }
          : product
      );
      setClientProducts(updatedClientProducts);
      mergeProducts(updatedClientProducts, products);
    }
  };

  const filteredProducts = allProducts.filter(
    (product) =>
      (product.label || "").toLowerCase().includes(searchText.toLowerCase()) &&
      (showAllProducts ? product.client === 0 : product.client === 1)
  );

  const countProductsWithQuantity = () => {
    return allProducts.filter(
      (product) => product.client === 1 && quantities[product.fkProduct] > 0
    ).length;
  };

  const calculateTotalPurchase = () => {
    return allProducts
      .reduce((acc, product) => {
        if (product.client === 1 && quantities[product.fkProduct]) {
          const priceWithDiscount =
            product.subprice * (1 - product.remise_percent / 100);

          return acc + priceWithDiscount * quantities[product.fkProduct];
        }
        return acc;
      }, 0)
      .toFixed(2);
  };

  const finalizePurchase = async () => {
    let filteredProducts = allProducts.filter(
      (product) =>
        product.client === 1 &&
        !Number.isNaN(parseInt(product.quantity)) &&
        parseInt(product.quantity) > 0 &&
        product.fkProduct != null
    );
  
    let pdfUrlsArray = [];
  
    if (!internetState.isConnected) {
      await DEV.saveOrderLocally(props.cliente.clientId, filteredProducts, 0);
      success = true;
    } else {
      if (props.cliente.client != null) {
        const totalPurchase = filteredProducts.reduce(
          (acc, product) =>
            acc + parseFloat(product.price) * parseInt(product.quantity),
          0
        );
        setTotalPurchase(totalPurchase.toFixed(2));
  
        const response = await DEV.createOrderFromClient(
          props.cliente.client,
          filteredProducts.map(product => ({
            ...product,
            price: parseFloat(product.price)  // Ensure the price is always multiprices["1"]
          })),
          0
        );
  
        if (response) {
          pdfUrlsArray.push(response);
        } else {
          console.error(
            "Error al realizar la compra:",
            response.error
          );
        }
      } else {
        console.log("El ID del cliente es nulo.");
      }
    }
  
    if (pdfUrlsArray.length > 0) {
      setPdfUrls(pdfUrlsArray);
      setPurchaseModalVisible(true);
    }
  };
  
  

  const calculateProductPrice = (subprice_ttc, subprice, tva_tx, showPriceWithTax) => {
    if (showPriceWithTax) {
      return parseFloat(subprice_ttc).toFixed(2);
    } else {
      return parseFloat(subprice).toFixed(2);
    }
  };

  if(showCobros){
    return <ListadoPedidos cliente={props.cliente}/>
  }

  return (
    <View style={[{ flex: 1, padding: 2 }, globalStyles.container]}>
      <View style={styles.headerContainer}>
        <View style={styles.headerContent}>
          <Icon
            name={showAllProducts ? "arrow-left" : "cart-plus"}
            size={40}
            onPress={toggleProductList}
          />
          <View style={styles.headerTitle}>
            <Text style={styles.headerTitleText}>{props.cliente.name}</Text>
            <Text
              style={styles.headerTitleText}
            >{`TOTAL CARRITO SIN IVA: ${calculateTotalPurchase()} €`}</Text>
          </View>
          {!showAllProducts ? (
            <Icon
              name="content-save"
              size={40}
              onPress={() => setShowFinalizeOptionsModal(true)}
            />
          ) : (
            <Icon
              name="content-save"
              size={40}
              onPress={toggleProductList}
            />
          )}
        </View>
        <View style={styles.buscarStyle}>
          <SearchInput
            placeholder="Buscar producto..."
            onSearch={handleSearch}
          />
        </View>
      </View>
      {loading ? (
        <>
        <ActivityIndicator size="large" />
        </>
        
      ) : (
        <FlashList
          keyboardDismissMode="interactive"
          keyboardShouldPersistTaps="handled"
          data={visibleData}
          renderItem={({ item }) => (
            <TouchableOpacity onPress={() => addProductToClient(item)}>
              <View
                style={[
                  styles.productContainer,
                  {
                    backgroundColor: item.client === 1 ? "#2271b3" : "#FDFD96",
                  },
                ]}
              >
                <View style={styles.productHeader}>
                  <View style={styles.productHeaderTitle}>
                    <Text style={styles.productHeaderText}>{item.label}</Text>
                  </View>
                  <Icon
                    name="calculator"
                    size={50}
                    onPress={() => addProductToClient(item)}
                  />
                </View>
                <View style={styles.containerRow}>
                  <View style={styles.priceContainer}>
                    {!showAllProducts ? (
                      <>
                        <View style={styles.priceColumn}>
                          <Text style={styles.priceText}>
                            Precio histórico{" "}
                            {showPriceWithTax ? "IVA" : "SIN IVA"}:{" "}
                            {`${calculateProductPrice(
                              item.subprice,
                              item.subprice_ttc,
                              item.tva_tx,
                              showPriceWithTax
                            )} €`}
                          </Text>
                        </View>
                        <View style={styles.priceColumn}>
                          {item.realPrice !== 0 ? (
                            <Text style={styles.priceText}>
                              Precio {showPriceWithTax ? "IVA" : "SIN IVA"}:{" "}
                              {`${calculateProductPrice(
                                item.price,
                                item.subprice,
                                item.tva_tx,
                                showPriceWithTax
                              )} €`}
                            </Text>
                          ) : null}
                        </View>
                      </>
                    ) : (
                      <>
                        <Text style={styles.priceText}>
                          Precio venta {showPriceWithTax ? "IVA" : "SIN IVA"}:{" "}
                          {`${calculateProductPrice(
                            item.subprice,
                            item.subprice,
                            item.tva_tx,
                            showPriceWithTax
                          )} €`}
                        </Text>
                      </>
                    )}
                    <Text style={styles.priceText}>
                      Precio Total:{" "}
                      {`${
                        (
                          parseFloat(item.subprice || 0) *
                          (quantities[item.fkProduct] || 0) *
                          (1 - parseFloat(item.remise_percent || 0) / 100)
                        ).toFixed(2) || 0
                      } €`}
                    </Text>
                    <Text style={styles.priceText}>
                      Stock actual: {item.productStock || 0}
                    </Text>
                  </View>
                  <View style={styles.stockContainer}>
                    <Text style={styles.stockText}>
                      Unidades/caja: {item.options_unidades || 0}
                    </Text>
                    <Text style={styles.stockText}>
                      Unidades : {quantities[item.fkProduct] || 0} uds 
                    </Text>
                    {!showAllProducts ? (
                      <Text style={styles.stockText}>
                        Descuento: {item.remise_percent || 0}%
                      </Text>
                    ) : (
                      <></>
                    )}
                  </View>
                </View>
              </View>
            </TouchableOpacity>
          )}
          keyExtractor={(item) => item.fkProduct.toString()}
          onEndReached={loadMoreData}
          onEndReachedThreshold={0.1}
          estimatedItemSize={200}
          threshold={5}
        />
      )}
      <View style={styles.footerContainer}>
        <Text
          style={styles.footerText}
        >{`Productos seleccionados: ${countProductsWithQuantity()}`}</Text>
      </View>
      <Modal
        animationType="slide"
        transparent={true}
        visible={isQuantityModalVisible}
        onRequestClose={() => setQuantityModalVisible(!isQuantityModalVisible)}
      >
        <QuantitySelector
          isVisible={isQuantityModalVisible}
          onClose={() => setQuantityModalVisible(false)}
          onSave={handleQuantitySave}
          product={selectedProduct}
          showPriceWithTax={showPriceWithTax} 

        />
      </Modal>
      <Modal
        animationType="slide"
        transparent={true}
        visible={showFinalizeOptionsModal}
        onRequestClose={() => setShowFinalizeOptionsModal(false)}
      >
        <View style={styles.modalContainer}>
          <View style={styles.modalContent}>
            <Text style={styles.modalTitle}>
              FINALIZACIÓN DEL PEDIDO
            </Text>
            <Button
              buttonStyle={styles.buttonStyle}
              title="Crear pedido completo"
              onPress={() => {
                finalizePurchase(false);
                setShowFinalizeOptionsModal(false);
              }}
            />
            <Button
              buttonStyle={styles.buttonStyle}
              title="Cancelar"
              onPress={() => setShowFinalizeOptionsModal(false)}
            />
          </View>
        </View>
      </Modal>
      <Modal
        animationType="slide"
        transparent={true}
        visible={isPurchaseModalVisible}
        onRequestClose={() => setPurchaseModalVisible(false)}
      >
        <View style={styles.modalContainer}>
          <View style={styles.modalContent}>
            <Text style={styles.modalTitle}>Pedido creado correctamente</Text>
            <Text style={styles.modalSubTitle}>
              Total: €{calculateTotalPurchase()}
            </Text>
            {/* {pdfUrls.length > 0 &&
              (console.log("VEAMOS si hay pdfs o no", pdfUrls),
              (<PdfTabNavigator pdfUrls={pdfUrls} />))} */}
            <Button
              buttonStyle={styles.buttonStyle}
              title="Ver cobros"
              onPress={() => {
                setPurchaseModalVisible(false);
                props.navigation.navigate("NuevaPantalla"); 
              }}
            />
            <Button
              buttonStyle={styles.buttonStyle}
              title="Home"
              onPress={() => {
                setPurchaseModalVisible(false);
                RootNavigation.navigate(HOME);
              }}
            />
          </View>
        </View>
      </Modal>
      <Modal
        animationType="slide"
        transparent={true}
        visible={isPendingPaymentsModalVisible}
        onRequestClose={() => setPendingPaymentsModalVisible(false)}
      >
        <View style={modalStyles.modalContainer}>
          <View style={modalStyles.modalContent}>
            <Text style={modalStyles.modalTitle}>PAGOS PENDIENTES</Text>
            {pendingPayments.total_due > 0 ? (
                <View>
                  <Text style={modalStyles.modalSubTitle}>
                    TOTAL : €{pendingPayments.total_due.toFixed(2) }
                  </Text>
                </View>
            ) : (
              <Text style={modalStyles.modalSubTitle}>
                No hay pagos pendientes.
              </Text>
            )}
            <Button
              buttonStyle={modalStyles.buttonStyle}
              title="Ver cobros"
              onPress={() => setShowCobros(true)}
            />
            <Button
              buttonStyle={modalStyles.buttonStyle}
              title="Cerrar"
              onPress={() => setPendingPaymentsModalVisible(false)}
            />
          </View>
        </View>
      </Modal>
    </View>
  );
};

export default PedidosComercialScreenView;

Quantity selector

import React, { useState, useEffect } from "react";
import {
  View,
  Text,
  Button,
  Modal,
  StyleSheet,
  TouchableOpacity,
  TextInput,
  KeyboardAvoidingView,
  Platform,
  TouchableWithoutFeedback,
  Keyboard
} from "react-native";
import { getSecureStoreData } from "../../utils/gettersAndSetters/getters.js"; // Asegúrate de que la ruta sea correcta
import { SHOW_PRICE_WITH_TAX } from "../../utils/const/secureStoreConst.js";

const QuantitySelector = ({ isVisible, onClose, onSave, product }) => {
  const [quantity, setQuantity] = useState("0");
  const [unitType, setUnitType] = useState("units"); // 'units' or 'pack'
  const [unitsPerPack, setUnitsPerPack] = useState(1);
  const [price, setPrice] = useState('0.00');
  const [discount, setDiscount] = useState("0");
  const [showPriceWithTax, setShowPriceWithTax] = useState(false);

  useEffect(() => {
    const fetchShowPriceWithTax = async () => {
      const showPriceWithTax = await getSecureStoreData(SHOW_PRICE_WITH_TAX);
      setShowPriceWithTax(showPriceWithTax === "true");
    };

    fetchShowPriceWithTax();

    if (product && product.options_unidades) {
      setUnitsPerPack(product.options_unidades);
    }
    if (product) {
      if (showPriceWithTax) {
        setPrice(parseFloat(product.subprice_ttc).toFixed(2));
      } else {
        setPrice(parseFloat(product.subprice).toFixed(2));
      }
    }
  }, [product, showPriceWithTax]);

  const handleSave = () => {
    const finalQuantity =
      unitType === "pack"
        ? parseInt(quantity, 10) * unitsPerPack
        : parseInt(quantity, 10);
    const finalPrice = parseFloat(price).toFixed(2);
    const finalDiscount = parseFloat(discount).toFixed(2);
    onSave(finalQuantity, finalPrice, finalDiscount);
  };

---

  const handleNumberPress = (number) => {
    setQuantity((prevQuantity) =>
      prevQuantity === "0"
        ? number.toString()
        : prevQuantity + number.toString()
    );
  };

  const handleClear = () => {
    setQuantity("0");
  };

  const handleBackspace = () => {
    setQuantity((prevQuantity) =>
      prevQuantity.length > 1 ? prevQuantity.slice(0, -1) : "0"
    );
  };

  const handlePriceChange = (text) => {
    const parsed = text.replace(/[^0-9.]/g, "");
    setPrice(parsed);
  };

  const handleDiscountChange = (text) => {
    const parsed = text.replace(/[^0-9.]/g, "");
    setDiscount(parsed);
  };

  return (
    <Modal visible={isVisible} transparent={true} animationType="slide">
      <KeyboardAvoidingView
        behavior={Platform.OS === "ios" ? "padding" : "height"}
        style={styles.modalContainer}
      >
        <TouchableWithoutFeedback onPress={Keyboard.dismiss}>
          <View style={styles.modalContent}>
            <Text style={styles.productText}>Producto {product?.label}</Text>
            <View style={styles.switchContainer}>
              <TouchableOpacity
                style={[
                  styles.switchButton,
                  unitType === "units" ? styles.active : styles.inactive,
                ]}
                onPress={() => setUnitType("units")}
              >
                <Text style={styles.switchText}>Unidades</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={[
                  styles.switchButton,
                  unitType === "pack" ? styles.active : styles.inactive,
                ]}
                onPress={() => setUnitType("pack")}
              >
                <Text style={styles.switchText}>Envases</Text>
              </TouchableOpacity>
            </View>
            <Text style={styles.quantityDisplay}>{quantity}</Text>
            <View style={styles.calculatorContainer}>
              {[1, 2, 3, 4, 5, 6, 7, 8, 9, 0].map((number) => (
                <TouchableOpacity
                  key={number}
                  style={styles.calculatorButton}
                  onPress={() => handleNumberPress(number)}
                >
                  <Text style={styles.calculatorButtonText}>{number}</Text>
                </TouchableOpacity>
              ))}
              <TouchableOpacity
                style={styles.calculatorButton}
                onPress={handleBackspace}
              >
                <Text style={styles.calculatorButtonText}>⌫</Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={styles.calculatorButton}
                onPress={handleClear}
              >
                <Text style={styles.calculatorButtonText}>CE</Text>
              </TouchableOpacity>
            </View>
            <View style={styles.inputContainer}>
              <Text style={styles.inputLabel}>
                Precio de venta {showPriceWithTax ? "CON IVA" : "SIN IVA"}:
              </Text>
              <TextInput
                style={styles.input}
                keyboardType="numeric"
                value={price}
                onChangeText={handlePriceChange}
                placeholder="0.00"
                placeholderTextColor="#aaa"
                clearButtonMode="always"
              />
            </View>
            <View style={styles.inputContainer}>
              <Text style={styles.inputLabel}>Descuento (%):</Text>
              <TextInput
                style={styles.input}
                keyboardType="numeric"
                value={discount}
                onChangeText={handleDiscountChange}
                placeholder="0"
                placeholderTextColor="#aaa"
                clearButtonMode="always"
              />
            </View>
            <View style={styles.buttonContainer}>
              <Button title="Guardar" onPress={handleSave} />
              <Button title="Cancelar" onPress={onClose} />
            </View>
          </View>
        </TouchableWithoutFeedback>
      </KeyboardAvoidingView>
    </Modal>
  );
};
export default QuantitySelector;