| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- "use client";
- import clsx from "clsx";
- import { useEffect, useImperativeHandle, type Ref } from "react";
- import { useForm, get } from "react-hook-form";
- import type {CheckoutShippingRate} from "@/types/checkout/type";
- import CheckoutShippingMethodLoading from "./CheckoutShippingMethodLoading";
- /**
- * 关于如何确定默认选中哪个运输方式:
- * 1. 从购物车详情中获取运输方式 A,运输方式列表中有A,那么把A标记为默认选中;如果运输方式列表中没有A,看运输方式列表中有没有免费的,如果有那么把免费的运输方式标记为选中,如果没有,不标记选中,让用户自己选
- * 2. 购物车详情中没有运输方式,那么看运输方式列表中有没有免费的,如果有那么把免费的运输方式标记为选中,如果没有,不标记选中,让用户自己选
- *
- */
- export interface RefShippingMethodsHandle {
- getSelectShipMethod: () => string;
- validateShipMethod: () => Promise<boolean>;
- }
- export function ShippingMethodCheckout({
- ref,
- errorMsg,
- shipMethods,
- selectedShippingRate,
- shippingMethodLoading,
- onShipMethodChange
- }: {
- ref: Ref<RefShippingMethodsHandle>;
- errorMsg: string | null;
- shipMethods: CheckoutShippingRate[];
- selectedShippingRate: string | null;
- shippingMethodLoading: boolean;
- onShipMethodChange: (value: string) => void;
- }) {
- const {
- register,
- reset,
- getValues,
- trigger,
- formState: { errors }
- } = useForm({
- mode: "onChange",
- reValidateMode: "onChange",
- });
- // 参考 https://github.com/react-hook-form/error-message/blob/master/src/ErrorMessage.tsx
- const shippingMethodError = get(errors, "shippingMethod");
- useImperativeHandle(ref, () => {
- return {
- // 获取用户选择的运输方式
- getSelectShipMethod: () => {
- return getValues('shippingMethod');
- },
- // 触发校验
- validateShipMethod: () => {
- return trigger();
- }
- }
-
- },[]);
-
- useEffect(() => {
- if(shipMethods.length > 0 ) {
- let defaultValue = '';
- let findItem: CheckoutShippingRate | undefined;
- if(selectedShippingRate) {
- findItem = shipMethods.find((item) => item.method === selectedShippingRate);
- if(findItem !== undefined) {
- defaultValue = selectedShippingRate;
- }
- }
- if(defaultValue) {
- reset({ shippingMethod: defaultValue });
- }
- /*
- if(!defaultValue) {
- findItem = shipMethods.find((item) => item.price === 0) || shipMethods[0];
- defaultValue = findItem.method;
- }
- console.log('ShippingMethodCheckout' + ' useEffect ++++++++++++++++++++++++++++ ', defaultValue,selectedShippingRate);
- reset({ shippingMethod: defaultValue });
- if(defaultValue !== selectedShippingRate) {
- onShipMethodChange(defaultValue);
- }
- */
- }
-
- }, [shipMethods,selectedShippingRate]);
-
- return (<>
-
- {shippingMethodLoading && <CheckoutShippingMethodLoading />}
-
- <form name="shipping method" className={clsx("w-full mt-3",{
- "hidden": shippingMethodLoading
- })}>
- {errorMsg && <p className="text-red-500 text-ly-12">{errorMsg}</p>}
- {shipMethods.length === 0 && <p className="text-red-500 text-ly-12">Please complete address data to get shipping methods list.</p>}
- <div className="w-full">
-
- {shipMethods.map((method) => {
- return (
- <label htmlFor={"shippingmethod-" + method._id} key={method._id}
- className="group block relative box-border mt-3 p-3 border-1 rounded-sm has-checked:border-ly-green"
- >
- <p className="text-ly-13">
- { method.method === 'free_free' && <span className="text-ly-13 text-ly-green font-bold mr-1">FREE</span>}
- <span>{method.label}</span>
- </p>
- <p className="text-ly-12 text-ly-placeholder mt-1">{method.description}</p>
- <div className="absolute top-1/2 -translate-y-1/2 right-3 flex items-center">
- <span className="text-ly-14 font-medium mr-4">{method.formattedPrice}</span>
- <svg className="check w-4 h-4 hidden group-has-[:checked]:block" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="1" y="1" width="14" height="14" rx="1" fill="#000000" ></rect><path stroke="rgba(255, 255, 255, 1)" strokeWidth="1.5" strokeLinecap="square" d="M5.3335 8L7.3335 10L11.3335 6"></path></svg>
- <svg className="uncheck w-4 h-4 block group-has-[:checked]:hidden" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16" fill="none"><rect x="1" y="1" width="14" height="14" rx="1" fill="#FFFFFF" ></rect><path fill="rgba(0, 0, 0, 1)" d="M2 0.5L14 0.5C14.8284 0.5 15.5 1.17157 15.5 2L15.5 14C15.5 14.8284 14.8284 15.5 14 15.5L2 15.5C1.17157 15.5 0.5 14.8284 0.5 14L0.5 2C0.5 1.17157 1.17157 0.5 2 0.5ZM2 1.5C1.72386 1.5 1.5 1.72386 1.5 2L1.5 14C1.5 14.2761 1.72386 14.5 2 14.5L14 14.5C14.2761 14.5 14.5 14.2761 14.5 14L14.5 2C14.5 1.72386 14.2761 1.5 14 1.5L2 1.5Z"></path></svg>
- </div>
- <input id={"shippingmethod-" + method._id}
- className="absolute w-6 h-6 opacity-0"
- type="radio"
- value={method.method}
- {...register('shippingMethod', {
- required: 'Please select a shipping method.',
- onChange: (event) => {
- console.log(event.target.value);
- onShipMethodChange(event.target.value);
- },
- })}
- />
- </label>
- )
- })}
-
- {shippingMethodError && <p className="text-red-500 text-ly-12">{shippingMethodError.message}</p>}
- </div>
-
- </form>
- </>);
-
- }
|