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