Untitled

mail@pastecode.io avatar
unknown
typescript
2 months ago
6.6 kB
1
Indexable
Never
import Scrollbars from "react-custom-scrollbars";

import { Button, Divider, Form } from "antd";
import { FormContainer } from "components/shared-components/Form";
import { format } from "date-fns";
import { useMessages } from "hooks/useMessages";
import { Fragment, useEffect, useMemo, useRef, useState } from "react";
import { useLazyGetPaymentMethodQuery, useLazyGetPaymentMethodsQuery } from "store/services/client/file/paymentMethodsApiSlice";
import { AccountPayableType } from "types/client/financial/AccountPayableType";
import { abntRounding } from "utils/abntRounding";
import { FormRow } from "components/shared-components/Form/components/FormRow";
import { InputFormItem } from "components/shared-components/Form/FormInputs/InputFormItem";
import { CurrencyFormItem } from "components/shared-components/Form/FormInputs/CurrencyFormItem";
import { SelectAsyncFormItem } from "components/shared-components/Form/FormInputs/SelectAsyncFormItem";
import { PaymentMethodsResume } from "./PaymentMethodsResume";
import { DeleteOutlined, PlusOutlined } from "@ant-design/icons";
import { debounce } from "lodash";

interface PaymentFormProps {
  rowKeys: string[];
  sumPayable: number;
}

interface PaymentMethod {
  payment_method: string;
  value_paid: number;
}

export function PaymentForm({ rowKeys, sumPayable }: PaymentFormProps) {
  const [form] = Form.useForm();

  const { onFormValidation, formErrors } = useMessages();

  const [getPaymentMethods] = useLazyGetPaymentMethodsQuery();
  const [getPaymentMethod] = useLazyGetPaymentMethodQuery();

  const [paymentMethodsResume, setPaymentMethodsResume] = useState<{
    total: number;
    remaining: number;
  }>({
    total: 0,
    remaining: 0,
  });

  const scrollbarsRef = useRef<Scrollbars>(null);
  const paymentMethodsWatch: PaymentMethod[] = Form.useWatch("payment_methods", form) ?? [];

  function calculateRemainingValue() {
    console.log('OK');

    const sumPaymentMethods = paymentMethodsWatch.reduce((acc, curr) => abntRounding(acc + Number(curr?.value_paid ?? 0)), 0);
    const remaining = abntRounding(sumPayable - sumPaymentMethods);

    setPaymentMethodsResume({
      total: sumPaymentMethods,
      remaining,
    });
  }

  function onFinish(values: any) {
    if (paymentMethodsResume.total > values.total) {
      onFormValidation("O somatório das formas de pagamento ultrapassou o valor a pagar");
      return;
    }

    const mergePaymentMethods = {};

    values.payment_methods.forEach((paymentMethod: PaymentMethod) => {
      if (paymentMethod.payment_method in mergePaymentMethods) {
        mergePaymentMethods[paymentMethod.payment_method] += paymentMethod.value_paid;
      } else {
        mergePaymentMethods[paymentMethod.payment_method] = paymentMethod.value_paid;
      }
    });

    const paymentMethods = Object.keys(mergePaymentMethods).map(payment_method => {
      return { payment_method, value_paid: mergePaymentMethods[payment_method] };
    });

    console.log({
      ...values,
      payment_methods: paymentMethods,
    });
  }

  function scrollToBottom() {
    if (scrollbarsRef.current) {
      scrollbarsRef.current.scrollToBottom();
    }
  };

  useEffect(() => {
    calculateRemainingValue();
    form.setFieldValue("total", sumPayable);
  }, [sumPayable]);

  useEffect(() => {
    scrollToBottom();
  }, [paymentMethodsWatch]);

  return (
    <FormContainer
      form={form}
      onFinish={onFinish}
      saveDraft={false}
      defaultValues={{}}
      formErrors={formErrors}
      removeMarginTop
      id={"modalForm"}
      alertErrors={{ removeMarginTop: true, withMarginBottom: true }}
      initialValues={{
        payment_date: format(new Date(), "yyyy-MM-dd")
      }}
    >
      <FormRow>
        <InputFormItem span={12} name={"payment_date"} label="Data de pagamento" type="date" />
        <CurrencyFormItem span={12} name={"total"} label="Total a pagar" disabled />
      </FormRow>

      <Divider orientation="left" style={{ marginTop: 0, marginBottom: 12 }}>
        <span className="font-weight-semibold font-size-base">Formas de pagamento</span>
      </Divider>

      <Scrollbars autoHeight style={{ marginBottom: 0 }} ref={scrollbarsRef}>
        <Form.List name={"payment_methods"}>
          {(fields, { add, remove }) => (
            <Fragment>
              {fields.map((field, index) => (
                <div key={field.key} style={{ display: "flex", marginBottom: 12, marginRight: 24, alignItems: "center", gap: 8 }}>
                  <span>{index + 1}. </span>

                  <FormRow>
                    <SelectAsyncFormItem
                      span={16}
                      name={[field.name, "payment_method"]}
                      label={`Forma de pagamento (${index + 1})`}
                      noStyle
                      rules={[{ required: true }]}
                      style={{ width: "100%" }}

                      fetchData={(props) => getPaymentMethods(props).unwrap()}
                      fetchItem={(paymentMethodId) => getPaymentMethod({ paymentMethodId }).unwrap()}
                      columnsToSearch={["name"]}
                      fieldsLabel={["name"]}
                    />

                    <CurrencyFormItem
                      span={8}
                      name={[field.name, "value_paid"]}
                      formListName={["payment_methods", field.name, "value_paid"]}
                      label={`Valor (${index + 1})`}
                      rules={[{ required: true }]}
                      noStyle
                      onBlur={calculateRemainingValue}
                    />
                  </FormRow>

                  <DeleteOutlined style={{ color: "#e74c3c" }} onClick={() => remove(field.name)} />
                </div>
              ))}

              <Form.Item noStyle>
                <Button size="small" type="link" style={{ padding: 0 }} onClick={() => add()} icon={<PlusOutlined />}>
                  Adicionar novo método de pagamento
                </Button>
              </Form.Item>
            </Fragment>
          )}
        </Form.List>
      </Scrollbars>

      <Divider orientation="left" style={{ marginTop: 12, marginBottom: 12 }}>
        <span className="font-weight-semibold font-size-base">???</span>
      </Divider>

      <PaymentMethodsResume paymentMethodsResume={paymentMethodsResume} />
    </FormContainer>
  );
}
Leave a Comment