| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- "use client";
- import { Controller, FieldValues, useForm } from "react-hook-form";
- import { cn } from "@heroui/theme";
- import { Radio, RadioGroup } from "@heroui/radio";
- import { useState } from "react";
- import { useCustomToast } from "@utils/hooks/useToast";
- import { useCheckout } from "@utils/hooks/useCheckout";
- import { ProceedToCheckout } from "../ProceedToCheckout";
- import { CustomRadioProps } from "@components/checkout/type";
- import { useDispatch } from "react-redux";
- import { updateCart } from "@/store/slices/cart-slice";
- export default function PaymentMethod({
- selectedPayment,
- methods,
- currentStep,
- }: {
- selectedPayment?: string;
- methods: any;
- currentStep?: string;
- }) {
- const { showToast } = useCustomToast();
- const { isPaymentLoading, saveCheckoutPayment } = useCheckout();
- const [isOpen, setIsOpen] = useState(currentStep !== "payment");
- const [prevValues, setPrevValues] = useState({
- currentStep,
- selectedPayment,
- });
- if (
- currentStep !== prevValues.currentStep ||
- selectedPayment !== prevValues.selectedPayment
- ) {
- setPrevValues({ currentStep, selectedPayment });
- if (currentStep === "payment") {
- setIsOpen(false);
- } else if (selectedPayment) {
- setIsOpen(true);
- }
- }
- const { handleSubmit, control } = useForm({
- mode: "onSubmit",
- defaultValues: {
- method: selectedPayment ?? "",
- },
- });
- const selectedMethodLabelPrior = methods?.find(
- (method: any) => method?.method === selectedPayment,
- )?.title;
- const dispatch = useDispatch();
- const onSubmit = async (data: FieldValues) => {
- if (!data?.method) {
- showToast("Please Choose the Payment Method", "warning");
- return;
- }
- try {
- const selectedMethod = methods?.find(
- (m: any) => m?.method === data?.method,
- );
- if (selectedMethod) {
- dispatch(
- updateCart({
- paymentMethod: selectedMethod?.method || "",
- paymentMethodTitle: selectedMethod?.title || "",
- }),
- );
- }
- await saveCheckoutPayment(data.method);
- } catch {
- showToast("Failed to save payment method. Please try again.");
- }
- };
- return (
- <>
- {selectedPayment ? (
- isOpen ? (
- <>
- <div className="mt-4 justify-between hidden sm:flex ">
- <div className="flex">
- <p className="w-auto text-base font-normal text-black/60 dark:text-white/60 sm:w-[192px]">
- Payment Method
- </p>
- <p className="text-base font-normal">
- {selectedMethodLabelPrior as string}
- </p>
- </div>
- <button
- onClick={() => {
- setIsOpen(false);
- }}
- className="cursor-pointer text-base font-normal text-black/60 underline dark:text-neutral-300"
- >
- Change
- </button>
- </div>
- <div className="mt-4 flex sm:hidden justify-between relative">
- <div className="flex justify-between justify-between flex-1 wrap">
- <p className="w-auto text-base font-normal text-black/60 dark:text-white/60 sm:w-[192px]">
- Payment Method
- </p>
- <p className="text-base font-normal">
- {selectedMethodLabelPrior as string}
- </p>
- </div>
- <button
- onClick={() => {
- setIsOpen(false);
- }}
- className="cursor-pointer absolute right-0 text-base font-normal text-black/60 underline dark:text-neutral-300"
- style={{ top: "-36px" }}
- >
- Change
- </button>
- </div>
- </>
- ) : (
- <div className="mt-6">
- <form onSubmit={handleSubmit(onSubmit)}>
- <Controller
- control={control}
- name="method"
- render={({ field }) => (
- <RadioGroup
- {...field}
- label=""
- value={field.value ?? ""}
- onValueChange={field.onChange}
- >
- {methods?.map((method: any) => (
- <CustomRadio
- key={method?.method}
- className="my-1 border border-solid border-neutral-300 dark:border-neutral-500"
- description={method?.description}
- value={method?.method}
- >
- <span className="text-neutral-700 dark:text-white">
- {method?.title}
- </span>
- </CustomRadio>
- ))}
- </RadioGroup>
- )}
- />
- <div className="my-6 justify-self-end">
- <ProceedToCheckout
- buttonName="Pay Now"
- pending={isPaymentLoading}
- />
- </div>
- </form>
- </div>
- )
- ) : (
- <div className="mt-6">
- <form onSubmit={handleSubmit(onSubmit)}>
- <Controller
- control={control}
- name="method"
- render={({ field }) => (
- <RadioGroup
- {...field}
- label=""
- value={field.value ?? ""}
- onValueChange={field.onChange}
- >
- {methods?.map((method: any) => (
- <CustomRadio
- key={method?.method}
- className="my-1 border border-solid border-neutral-300 dark:border-neutral-500"
- description={method?.description}
- value={method?.method}
- >
- <span className="text-neutral-700 dark:text-white">
- {method?.title}
- </span>
- </CustomRadio>
- ))}
- </RadioGroup>
- )}
- />
- <div className="my-6 justify-self-end">
- <ProceedToCheckout
- buttonName="Pay Now"
- pending={isPaymentLoading}
- />
- </div>
- </form>
- </div>
- )}
- </>
- );
- }
- const CustomRadio = (props: CustomRadioProps) => {
- const { children, ...otherProps } = props;
- return (
- <Radio
- {...otherProps}
- classNames={{
- base: cn(
- "inline-flex m-0 bg-transparent hover:bg-transparent items-center",
- "flex-row items-baseline max-w-full cursor-pointer rounded-lg gap-4 p-4 border-2 border-transparent",
- "data-[selected=true]:border-primary",
- ),
- hiddenInput: "peer absolute h-0 w-0 opacity-0",
- }}
- >
- {children}
- </Radio>
- );
- };
|