Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
18 kB
4
Indexable
Never
//TODO : Fix eslint error
/* eslint-disable @typescript-eslint/no-explicit-any */
import { zodResolver } from "@hookform/resolvers/zod";
import axios from "axios";
import Image from "next/image";
import { useEffect, useRef, useState } from "react";
import { useForm } from "react-hook-form";
import { z } from "zod";
import { Button } from "~/components/ui/button";
import { Card, CardContent } from "~/components/ui/card";
import { SelectItem } from "~/components/ui/customselect";
import {
  Form,
  FormControl,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "~/components/ui/form";
import { Input } from "~/components/ui/input";
import {
  Select,
  SelectContent,
  SelectGroup,
  SelectLabel,
  SelectTrigger,
  SelectValue,
} from "~/components/ui/select";
import { Separator } from "~/components/ui/separator";
import { Textarea } from "~/components/ui/textarea";
import useHandleBackProduct from "~/utils/hooks/handleBackProduct";

export type DataShippingProps = {
  name: string;
  phone: number;
  email: string;
  postalCode: string;
  prefectures: string;
  address: string;
  note: string;
};

export type ShippingProps = {
  onPrevStep?: () => void;
  onNextStep: () => void;
  setIsCancelShipping?: any;
  activeStep?: number;
  handleGetDataShipping?: (e: any) => void;
  dataShipping?: DataShippingProps;
};

export const iFormInfoShippingSchema = z.object({
  name: z.string().max(100).nonempty(),
  phone: z.string().nonempty(),
  email: z.string().email().nonempty(),
  postalCode: z.string().nonempty(),
  prefectures: z.string().nonempty(),
  address: z.string().nonempty(),
  note: z.string().max(355),
});

function loadAsyncScript(src) {
  return new Promise((resolve) => {
    const script = document.createElement("script");
    Object.assign(script, {
      type: "text/javascript",
      async: true,
      src,
    });
    script.addEventListener("load", () => resolve(script));
    document.head.appendChild(script);
  });
}

const StepOne = ({ handleGetDataShipping, dataShipping }: ShippingProps) => {
  const methods = useForm<z.infer<typeof iFormInfoShippingSchema>>({
    defaultValues: {
      name: dataShipping?.name || "",
      phone: dataShipping?.phone?.toString() || "",
      email: dataShipping?.email || "",
      postalCode: dataShipping?.postalCode || "",
      prefectures: dataShipping?.prefectures || "",
      address: dataShipping?.address || "",
      note: dataShipping?.note || "",
    },
    resolver: zodResolver(iFormInfoShippingSchema),
  });

  const {
    register,
    handleSubmit,
    control,
    formState: { errors, isValid },
    setValue,
    watch,
  } = methods;

console.log("watch",watch("address"))
  const onSubmit = (data: z.infer<typeof iFormInfoShippingSchema>) => {
    handleGetDataShipping && handleGetDataShipping(data);
  };

  const searchInput = useRef(null);

  const [address, setAddress] = useState({});
  const { handleBackProduct } = useHandleBackProduct({
    isSell: false,
    url: "sell",
  });



  const mapApiJs = "https://maps.googleapis.com/maps/api/js";

  // init gmap script
  const initMapScript = () => {
    // if script already loaded
    if (window.google) {
      return Promise.resolve();
    }

    const src = `${mapApiJs}?key=${process.env.NEXT_PUBLIC_GOOGLE_PLACE}&libraries=places&v=weekly&language=ja&types=regions`;
    return loadAsyncScript(src);
  };
  // do something on address change
  const onChangeAddress = (autocomplete) => {
    const place = autocomplete.getPlace();
console.log("place",place)
    setAddress(extractAddress(place));
  };

  const [cityAddress, setCityAddress] = useState([]);
  // init autocomplete
  const initAutocomplete = () => {
    if (!searchInput.current) return;

    const autocomplete: google.maps.Map = new google.maps.places.Autocomplete(
      searchInput.current,
    ) as HTMLElement;
console.log("autocomplete",autocomplete)
    autocomplete.setFields(["address_component", "geometry"]);
    autocomplete.addListener("place_changed", () =>
      onChangeAddress(autocomplete),
    );
  };
  useEffect(() => {
    async function fetchData() {
      try {
        const result = await axios.get(
          "https://geolonia.github.io/japanese-addresses/api/ja.json",
        );
        const keys = Object.keys(result.data);
        setCityAddress(keys);
      } catch (error) {
        console.error("Error fetching data:", error);
      }
    }

    fetchData();
  }, []);

  const extractAddress = (place) => {
    const address = {
      city: "",
      keys: "",
      zip: "",
      country: "",
    };

    if (!Array.isArray(place?.address_components)) {
      return address;
    }

    place.address_components.forEach((component) => {
      const types = component.types;
      const value = component.long_name;
console.log("value",value)
      if (types.includes("locality")) {
        address.city = value;
      }

      if (types.includes("administrative_area_level_1")) {
        address.state = value;
      }

      if (types.includes("postal_code")) {
        address.zip = value;
      }
      setValue("postalCode", address.zip);
      setValue("address", address.city);
      setValue("prefectures", address.state);
      if (types.includes("country")) {
        address.country = value;
      }
    });

    return address;
  };

  // load map script after mounted
  useEffect(() => {
    initMapScript().then(() => initAutocomplete());
  }, []);

  return (
    <div className="flex w-full flex-col gap-12">
      <Card className="border-none bg-gray-1400 px-14 py-11 mobile:px-6 mobile:py-4">
        <CardContent className="flex  flex-col gap-4 p-0">
          <div className="flex flex-col gap-2">
            <h4 className="font-bold">商品情報</h4>
            <Separator className="mb-3 bg-green-400"></Separator>
            <div className="my-4 flex flex-col gap-4">
              <div className="flex">
                <div className="min-h-[10rem] max-w-full ">
                  <Image
                    src="/assets/images/shochu.webp"
                    width={296}
                    height={250}
                    alt={"3443"}
                    className="rounded-[20px] bg-white"
                  ></Image>
                </div>

                <div className="w-full pl-8">
                  <h3 className="pt-2 text-4xl font-bold">松竹梅 #929</h3>
                  <p className="pt-4 font-bold">
                    所有者<span className="pl-4 underline">所有者</span>
                  </p>

                  <div>
                    <h3 className="py-3 font-bold">詳細情報</h3>
                    <Separator className="mb-3 bg-green-400"></Separator>
                    <div className="grid grid-cols-2 gap-3">
                      <div className="text-sm font-bold">アルコール度数</div>
                      <div className="text-right text-sm font-thin">15%</div>
                      <div className="text-sm font-bold">内容量</div>
                      <div className="text-right text-sm font-thin">
                        1,000ml
                      </div>
                      <div className="text-sm font-bold">製品サイズ</div>
                      <div className="text-right text-sm font-thin">京都</div>
                      <div className="text-sm font-bold">産地(地方)</div>
                      <div className="text-right text-sm font-thin">
                        関西地方
                      </div>
                      <div className="text-sm font-bold">生産年</div>
                      <div className="text-right text-sm font-thin">
                        日本円決済
                      </div>
                    </div>
                  </div>

                  <div className="pt-4">
                    <h3 className="py-3 font-bold">オプション</h3>
                    <Separator className="mb-3 bg-green-400"></Separator>
                    <div className="grid grid-cols-2 gap-3">
                      <div className="text-sm font-bold">保管方法</div>
                      <div className="text-right text-sm font-thin">
                        熟成保管%
                      </div>
                      <div className="text-sm font-bold">最大保管期間</div>
                      <div className="text-right text-sm font-thin">+10年</div>
                      <div className="text-sm font-bold">決済方法</div>
                      <div className="text-right text-sm font-thin">
                        日本円決済
                      </div>
                    </div>
                  </div>

                  <div className="pt-4">
                    <h3 className="py-3 font-bold">発送依頼</h3>
                    <Separator className="mb-3 bg-green-400"></Separator>
                    <div className="grid grid-cols-2 gap-3">
                      <div className="text-sm font-bold">発送依頼期限</div>
                      <div className="text-right text-sm font-thin">
                        2025年3月31日
                      </div>
                    </div>
                    <div className="pt-1 text-right text-sm font-medium text-red-500">
                      発送依頼期限を過ぎたNFTは発送依頼を行うことができません。
                    </div>
                  </div>
                </div>
              </div>
              <h4 className="font-bold">出品情報</h4>
              <Separator className="bg-green-400"></Separator>
              <p>
                上撰松竹梅は、長年の酒造りの歴史のなか、酒蔵で育まれた「蔵付半兵衛酵母」により仕込んでおります。当社のある、酒どころ伏見・竹中町は安土桃山時代に軍師「竹中半兵衛」の一族の屋敷があったことに由来しており、松竹梅の蔵付き酵母はこの軍師の名にちなんでいます。
              </p>
            </div>
          </div>
        </CardContent>
      </Card>

      <div className="border-none">
        <div className="flex flex-col py-11">
          <div className="flex flex-col gap-4">
            <h4 className="font-bold">発送先情報</h4>
            <Separator></Separator>
            <div className="mt-4">
              <Form {...methods}>
                <form className="flex flex-col gap-2">
                  <FormField
                    name="name"
                    // control={field}
                    defaultValue=""
                    render={({ field }) => (
                      <FormItem className="mb-4">
                        <FormLabel>
                          氏名
                          <FormLabel className="text-red-500">
                            【必須】
                          </FormLabel>
                        </FormLabel>
                        <FormControl>
                          <Input placeholder="氏名" {...field} />
                        </FormControl>
                        <FormMessage>{errors.name?.message}</FormMessage>
                      </FormItem>
                    )}
                  />
                  <FormField
                    name="phone"
                    control={control}
                    defaultValue=""
                    render={({ field }) => (
                      <FormItem className="mb-4">
                        <FormLabel>
                          電話番号
                          <FormLabel className="text-red-500">
                            【必須】
                          </FormLabel>
                        </FormLabel>
                        <FormControl>
                          <Input
                            value="number"
                            placeholder="000-0000-0000"
                            {...field}
                          />
                        </FormControl>
                        <FormMessage>{errors.phone?.message}</FormMessage>
                      </FormItem>
                    )}
                  />
                  <FormField
                    control={control}
                    name="email"
                    render={({ field }) => (
                      <FormItem className="mb-4">
                        <FormLabel>
                          メールアドレス
                          <FormLabel className="text-red-500">
                            【必須】
                          </FormLabel>
                        </FormLabel>
                        <FormControl>
                          <Input placeholder="example@sample.com" {...field} />
                        </FormControl>
                        <FormMessage></FormMessage>
                      </FormItem>
                    )}
                  />
                  <FormField
                    control={control}
                    name="postalCode"
                    render={() => (
                      <FormItem className="mb-4">
                        <FormLabel>
                          発送先住所
                          <FormLabel className="text-red-500">
                            【必須】
                          </FormLabel>
                        </FormLabel>

                        <FormControl>
                          <div className="">
                            <Input
                              placeholder="〒郵便番号"
                              className=" focus-visible:ring-none w-full focus:border focus:border-gray-1300 focus:outline-none focus-visible:ring-0 "
                              ref={searchInput}
                            />
                          </div>
                        </FormControl>

                        <FormMessage />
                      </FormItem>
                    )}
                  />
                  <FormField
                    control={control}
                    name="prefectures"
                    render={({ field }) => (
                      <Select
                        value={field.value}
                        onValueChange={(value) => {
                          setValue("prefectures", value);
                        }}
                      >
                        <SelectTrigger className="w-full border border-gray-1300 ">
                          {/* <SelectValue className="!bg-red-500" placeholder="都道府県"/> */}
                          <SelectGroup>
                            {searchInput.current?.value === "" && (
                              <SelectLabel className="pl-0 font-normal text-gray-1300">
                                都道府県
                              </SelectLabel>
                            )}
                            <SelectValue className="!bg-red-500" />
                          </SelectGroup>
                        </SelectTrigger>

                        <SelectContent className="scrollbar max-h-[300px] w-[320px] py-2 pl-0.5 pr-2.5">
                          {cityAddress.map((item, key) => {
                            return (
                              <SelectItem
                                key={key}
                                value={item}
                                className="cursor-pointer pl-3 hover:!bg-gray-1400 hover:!text-green-400"
                              >
                                {item}
                              </SelectItem>
                            );
                          })}
                        </SelectContent>
                      </Select>
                    )}
                  />

                  <FormField
                    control={control}
                    name="address"
                    render={({ field }) => (
                      <Input
                        placeholder="住所"
                        value={field.value}
                        onChange={field.onChange}
                        onBlur={field.onBlur}
                        className="focus-visible:ring-none mt-2 w-full focus:border focus:border-gray-1300 focus:outline-none focus-visible:ring-0"
                      />
                    )}
                  />

                  <FormField
                    control={control}
                    name="note"
                    render={({ field }) => (
                      <FormItem>
                        <FormLabel>備考</FormLabel>
                        <Textarea placeholder="記入する" {...field} />
                        <FormMessage></FormMessage>
                      </FormItem>
                    )}
                  />
                </form>
              </Form>
            </div>
          </div>
        </div>
      </div>
      <div className="flex justify-center">
        <Button
          className="w-[184px] rounded-md border border-gray-500 bg-white px-4 py-2 text-black outline-none"
          onClick={handleBackProduct}
        >
          戻る
        </Button>
        <Button
          disabled={!isValid}
          className="ml-8 w-[400px] rounded-md border border-gray-500 bg-green-400 px-4 py-2 text-black outline-none"
          onClick={handleSubmit(onSubmit)}
        >
          次へ
        </Button>
      </div>
    </div>
  );
};

export default StepOne;