Untitled
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;