Skip to content

Instantly share code, notes, and snippets.

@naiplawan
Last active September 28, 2023 02:15
Show Gist options
  • Select an option

  • Save naiplawan/866862983a1ff69914c938fc4b36b3d2 to your computer and use it in GitHub Desktop.

Select an option

Save naiplawan/866862983a1ff69914c938fc4b36b3d2 to your computer and use it in GitHub Desktop.
AllStepCheckOutForm
import { useEffect, useState } from "react";
import { useNavigate,useParams } from "react-router-dom";
import Navbar from "../components/Navbar";
import arrowBlue from "../assets/CustomerPhoto/icons/arrow-blue.svg"
import arrowWhite from "../assets/CustomerPhoto/icons/arrow-white.svg";
import sellblack from "../assets/CustomerPhoto/icons/sellblack.svg";
import axios from "axios";
import dayjs from 'dayjs';
import credit from "../assets/CustomerPhoto/icons/credit.svg";
import qr from "../assets/CustomerPhoto/icons/qr.svg";
import greyarrow from "../assets/CustomerPhoto/icons/BackGrey.svg";
import { message, Steps, Form, Input, DatePicker, TimePicker } from "antd";
function AllStepCheckOutForm() {
const [service, setService] = useState({});
const [form] = Form.useForm();
const params = useParams();
const [current, setCurrent] = useState(0);
const [selectedSubService, setSelectedSubService] = useState([]);
const { TextArea } = Input;
const [formData, setFormData] = useState({});
const navigate = useNavigate();
console.log("params.serviceId:", params.serviceId);
console.log("Service Data:", service);
const steps = [
{
title: "รายการ",
content: "First-content",
},
{
title: "กรอกข้อมูลบริการ",
content: "Second-content",
},
{
title: "ชำระเงิน",
content: "Third-content",
}
];
const items = steps.map((item) => ({ key: item.title, title: item.title }));
const next = () => {
setCurrent(current + 1);
};
const prev = () => {
setCurrent(current - 1);
};
const getService = async (serviceId) => {
try {
const response = await axios.get(
`http://localhost:4000/service/${serviceId}`
);
const serviceData = response.data.data;
if (serviceData) {
setService(serviceData);
} else {
console.error("Service data is not valid:", serviceData);
}
} catch (error) {
console.error("Error fetching service data:", error);
}
};
useEffect(() => {
getService(params.serviceId);
}, [params.serviceId]);
const handleIncrement = (subService) => {
const index = selectedSubService.findIndex(
(item) => item.sub_service_id === subService.sub_service_id
);
if (index === -1) {
setSelectedSubService([
...selectedSubService,
{ ...subService, count: 1 },
]);
} else {
const updatedSubService = [...selectedSubService];
updatedSubService[index].count += 1;
setSelectedSubService(updatedSubService);
}
};
const handleDecrement = (subServiceId) => {
const updatedSubService = [...selectedSubService];
const subServiceIndex = updatedSubService.findIndex(
(item) => item.sub_service_id === subServiceId
);
if (subServiceIndex !== -1) {
updatedSubService[subServiceIndex].count -= 1;
if (updatedSubService[subServiceIndex].count === 0) {
updatedSubService.splice(subServiceIndex, 1);
}
setSelectedSubService(updatedSubService);
}
};
const calculateTotalPrice = () => {
return selectedSubService;
};
const handleFormChange = (changedValues) => {
setFormData({ ...formData, ...changedValues });
};
const handleFormSubmit = (formValues) => {
// Handle form submission logic here
console.log("Form values:", formValues);
// Assuming you want to move to the next step after form submission
next();
};
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(null);
const handlePaymentMethodClick = (method) => {
setSelectedPaymentMethod(method);
};
console.log("current is:",current)
console.log("Form:",formData)
console.log("Subservices:",selectedSubService)
return (
<div className="First-content bg-grey300" content="First-content">
<Navbar />
<div className="">
{service.service_photo && service.service_photo ? (
<div className="h-[300px] overflow-hidden flex items-center justify-center relative bg-blue900">
<img
src={service.service_photo}
alt="Service Photo"
className="min-w-full mt-40 mix-blend-screen"
/>
<div className="rounded-lg px-10 py-[10px] w-auto h-[68px] text-center text-[#646C80] bg-opacity-12 shadow-[2px_2px_24px_rgba(23,51,106,0.12)] absolute bg-white left-[12rem]">
บริการของเรา
<img src={greyarrow} className="inline mx-3" />
<span className="text-[32px] text-[#336DF2] ">
{service.service_name}
</span>
</div>
</div>
) : (
<p>No service photo available.</p>
)}
{current !== 3 && ( // Hide Steps on the Summary page
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps current={current} labelPlacement="vertical" items={items} />
</div>
)}
</div>
<div className="flex my-8 lg:mx-[12rem] md:mx-10 justify-between min-h-screen w-[80%] bg-white ">
{current === 0 ? (
<div className="h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg bg-white mt-20 ">
<div className="text-[20px] text-[#646C80]">
เลือกรายการบริการ{service.service_name}
</div>
<div className="mt-4">
{service.sub_service && service.sub_service.length > 0 && (
<div>
<ul>
{service.sub_service.map((subService, index) => (
<div
key={subService.sub_service_id}
className={`py-5 flex justify-between items-center${
index === service.sub_service.length - 1
? ""
: " border-b border-[#CCD0D7]"
}`}
>
<div>
<li className="text-[18px] font-bold">
{subService.sub_service_name}
</li>
<img src={sellblack} className="inline mr-2" />
<li className="text-[14px] text-[#646C80] inline">
{subService.price_per_unit}.00฿ / {subService.unit}
</li>
</div>
<div className="flex flex-row items-center p-">
<div className="flex items-center justify-center mx-3 w-[43px] h-[43px] border border-[#336DF2] rounded-[8px]">
<button
className="text-[25px] text-[#336DF2]"
onClick={() =>
handleDecrement(subService.sub_service_id)
}
>
-
</button>
</div>
<div className="mx-3">
{selectedSubService.find(
(item) =>
item.sub_service_id ===
subService.sub_service_id
)?.count || 0}
</div>
<div className="flex items-center justify-center mx-3 w-[43px] h-[43px] border border-[#336DF2] rounded-[8px]">
<button
className="text-[25px] text-[#336DF2]"
onClick={() => handleIncrement(subService)}
>
+
</button>
</div>
</div>
</div>
))}
</ul>
</div>
)}
</div>
</div>
) : current === 1 ? (
<div
className="Second-content h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20"
content="Second-content"
>
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps current={current} labelPlacement="vertical" items={items} />
</div>
<div className="flex my-8 lg:mx-[12rem] md:mx-10 justify-between min-h-screen w-[80%]">
<div className="h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20 ">
<Form
labelCol={{ span: 5 }}
wrapperCol={{ span: 19 }}
form={form}
autoComplete="on"
onFinish={(formValues) => {
// Handle form submission and pass formValues to the next step
handleFormSubmit(formValues);
}}
>
<h1 className="text-gray300 text-center text-[20px] font-medium">
กรอกข้อมูลบริการ
</h1>
<Form.Item
label="วันที่สะดวกใช้บริการ"
className="font-medium text-grey900"
name="date"
>
<DatePicker
format="DD/MM/YYYY"
placeholder="กรุณาเลือกวันที่"
className="w-[22.5vw] h-[44px] px-4 py-2.5"
value={formData.date}
onChange={(date) => handleFormChange({ date })}
/>
</Form.Item>
<Form.Item
label="เวลาที่สะดวกใช้บริการ"
className="font-medium text-grey900"
name="time"
>
<TimePicker
format="HH:mm"
placeholder="กรุณาเลือกเวลา"
className="w-[22.5vw] h-[44px] px-4 py-2.5"
value={formData.time}
onChange={(time) => handleFormChange({ time })}
/>
</Form.Item>
<Form.Item
label="ที่อยู่"
className="font-medium text-grey900"
name="address"
>
<Input placeholder="กรุณากรอกที่อยู่" allowClear
value={formData.address}
onChange={(e) => handleFormChange({ address: e.target.value })}/>
</Form.Item>
<div className="w-full flex justify-between mt-4">
<Form.Item
label="แขวง / ตำบล"
className="font-medium text-grey900"
name="subdistrict"
>
<Input placeholder="กรุณากรอกแขวง / ตำบล" allowClear
value={formData.subdistrict}
onChange={(e) => handleFormChange({ subdistrict: e.target.value})}/>
</Form.Item>
<Form.Item
label="เขต / อำเภอ"
className="font-medium text-grey900"
name="district"
>
<Input placeholder="กรุณากรอกเขต / อำเภอ" allowClear
value={formData.district}
onChange={(e) => handleFormChange({ district: e.target.value })}/>
</Form.Item>
</div>
<div className="w-full flex justify-between mt-4">
<Form.Item
label="จังหวัด"
className="font-medium text-grey900"
name="province"
>
<Input placeholder="กรุณากรอกจังหวัด" allowClear
value={formData.province}
onChange={(e) => handleFormChange({ province: e.target.value })}/>
</Form.Item>
<Form.Item
label="รหัสไปรษณีย์"
className="font-medium text-grey900"
name="zipcode"
>
<Input placeholder="กรุณากรอกรหัสไปรษณีย์" allowClear
value={formData.zipcode}
onChange={(e) => handleFormChange({ zipcode: e.target.value })}/>
</Form.Item>
</div>
<Form.Item
label="ระบุข้อมูลเพิ่มเติม"
className="font-medium text-grey900"
name="additionalInfo"
>
<TextArea
placeholder="กรุณาระบุข้อมูลเพิ่มเติม"
autoSize={{ minRows: 3 }}
value={formData.additionalInfo}
onChange={(e) => handleFormChange({ additionalInfo: e.target.value })}
/>
</Form.Item>
</Form>
</div>
</div>
</div>
) : current === 2 ? (
<div
className="Last-content h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20"
content="Last-content"
>
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps current={current} labelPlacement="vertical" items={items} />
</div>
<div
className="Last-content h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20"
content="Last-content"
>
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps current={2} labelPlacement="vertical" items={items} />
</div>
<div>ชำระเงิน</div>
<div className="flex justify-evenly mt-4">
<button
className={`w-full border border-[#CCD0D7] rounded-lg p-1 flex flex-col justify-center items-center focus:outline-none focus:ring focus:ring-[#336DF2] ${
selectedPaymentMethod === "qr" ? "bg-[#E7EEFF] focus:ring focus:ring-[#336DF2]" : ""
}`}
onClick={() => handlePaymentMethodClick("qr")}
>
<img src={qr} />
<p>พร้อมเพ</p>
</button>
<button
className={`w-full border border-[#CCD0D7] rounded-lg p-1 ml-4 flex flex-col justify-center items-center focus:outline-none focus:ring focus:ring-[#336DF2] ${
selectedPaymentMethod === "credit" ? "bg-[#E7EEFF] focus:ring focus:ring-[#336DF2]" : ""
}`}
onClick={() => handlePaymentMethodClick("credit")}
>
<img src={credit} />
<p>บัตรเครดิต</p>
</button>
</div>
<div className="mt-5">
<p>หมายเลขบัตรเครดิต<span className="text-[#C82438]">*</span></p>
<input placeholder="กรุณากรอกหมายเลขบัตรเครดิต" className="w-full border border-[#CCD0D7] rounded-lg p-2" required/>
</div>
<div className="mt-5">
<p>ชื่อบนบัตร<span className="text-[#C82438]">*</span></p>
<input placeholder="กรุณากรอกชื่อบนบัตร" className="w-full border border-[#CCD0D7] rounded-lg p-2" required/>
</div>
<div className="flex mt-5">
<div>
<p>วันหมดอายุ<span className="text-[#C82438]">*</span></p>
<DatePicker defaultValue={dayjs('2015/01', monthFormat)} format={monthFormat} picker="month" placeholder="MM/YY" required/>
</div>
<div className="ml-4">
<p>รหัส CVC / CVV<span className="text-[#C82438]">*</span></p>
<input type="tel"
placeholder="xxx"
className="w-full border border-[#CCD0D7] rounded-lg p-0.5"
maxlength="3" pattern="([0-9]{3})" required/>
</div>
</div>
<div className="my-8 w-full h-[1px] border border-[#CCD0D7]"></div>
<div className="flex">
<div>
<p>Promotion Code</p>
<input placeholder="กรุณากรอกโค้ดส่วนลด (ถ้ามี)" className="w-full border border-[#CCD0D7] rounded-lg p-1"/>
</div>
<div className="pt-6 ml-5">
<button className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-20 p-1 px-1 bg-[#336DF2] rounded-lg">ใช้โค้ด</button>
</div>
</div>
</div>
</div>
) : null}
{/* summary-box */}
<div className="h-full w-[562px] py-8 px-6 flex flex-col justify-between border border-grey300 rounded-lg mr-0 top-40 mt-20 ">
<div className="summary-box flex-auto text-center pb-3 text-[40px] text-[#646C80]"> {current === 3 ? "ชำระเงินเรียบร้อยแล้ว" : "สรุปรายการ"}</div>
<ul>
{calculateTotalPrice().map((item, index) => (
<li key={index} className="flex justify-between">
<p className="text-black" >{item.sub_service_name}</p>
<p className="text-black">
{item.count > 1
? `${item.count} ${item.unit}`
: `1 ${item.unit}`}
</p>
</li>
))}
</ul>
<div className="w-[301]px h-[1px] border border-[#CCD0D7] mt-3"></div>
<div className="pt-10"><div> {current === 1 || current === 2 || current ===3 ? (
<div>
<div className="flex justify-between">
<div className="text-[#646C80]">วันที่:</div>
<div className="text-black">{formData.date ? formData.date.format('DD/MM/YYYY') : ''}</div>
</div>
<div className="flex justify-between">
<div className="text-[#646C80]">เวลา:</div>
<div className="text-black">{formData.time ? formData.time.format('HH:mm') : ''}</div>
</div>
<div className="flex justify-between">
<div className="text-[#646C80]">สถานที่:</div>
<div className="text-black">{formData.address} {formData.subdistrict} {formData.district} {formData.province} {formData.zipcode}</div>
</div>
<div className="flex justify-between">
<div className="text-[#646C80]">ข้อมูลเพิ่มเติม:</div>
<div className="text-black">{formData.additionalInfo}</div>
</div>
</div>
) : null}</div>
</div>
<div className="w-[301]px h-[1px] border border-[#CCD0D7] mt-3"></div>
<div className="flex justify-between pt-5 mb-2">
<div className="text-[16px] text-[#646C80]">รวม</div>
<div className="text-black">
{calculateTotalPrice().reduce(
(total, item) => total + item.price_per_unit * item.count,
0
)}
.00฿
</div>
</div>
{current === 3 && (
<div>
<button
className="bg-blue600 w-full h-11 rounded-lg text-white"
onClick={() => navigate(`/customer-services-history/:userId`)}
>
เช็ครายการซ่อม
</button>
</div>
)}
</div>
</div>
<div className="flex justify-between p-5 sticky bottom-0 z-[100] border-y-grey300 border-x-white border px-40 bg-white">
{current === 0 ? (
<>
<button
className="btn-secondary flex items-center justify-center text-base font-medium w-40 p-2 px-6"
onClick={() => {
// Navigate to "/services-list" when current === 0
navigate("/services-list");
}}
>
ย้อนกลับ
<img src={arrowBlue} alt="arrow" />
</button>
<button
className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-40 p-2 px-6 bg-[#336DF2] rounded-lg"
onClick={next}
>
ดำเนินการต่อ
<img src={arrowWhite} alt="goarrow" />
</button>
</>
) : (
<>
{current > 0 && (
<button
className="btn-secondary flex items-center justify-center text-base font-medium w-40 p-2 px-6"
onClick={() => prev()}
>
ย้อนกลับ
<img src={arrowBlue} alt="arrow" />
</button>
)}
{current < steps.length - 1 && (
<button
className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-40 p-2 px-6 bg-[#336DF2] rounded-lg"
onClick={current === 2 ? () => next(onFinish()) : () => next()}
>
ดำเนินการต่อ
<img src={arrowWhite} alt="goarrow" />
</button>
)}
{current === steps.length - 1 && (
<button
type="primary"
onClick={() => {
message.success('Processing complete!');
next();
}}
className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-45 p-2 px-6 bg-[#336DF2] rounded-lg"
>
ยืนยันการชำระเงิน
</button>
)}
</>
)}
</div>
</div>
);
}
export default AllStepCheckOutForm;
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import Navbar from "../components/Navbar";
import arrowBlue from "../assets/CustomerPhoto/icons/arrow-blue.svg";
import arrowWhite from "../assets/CustomerPhoto/icons/arrow-white.svg";
import sellblack from "../assets/CustomerPhoto/icons/sellblack.svg";
import axios from "axios";
import dayjs from "dayjs";
import credit from "../assets/CustomerPhoto/icons/credit.svg";
import qr from "../assets/CustomerPhoto/icons/qr.svg";
import greyarrow from "../assets/CustomerPhoto/icons/BackGrey.svg";
import { message, Steps, Form, Input, DatePicker, TimePicker } from "antd";
// npm install --save @stripe/react-stripe-js @stripe/stripe-js
import { loadStripe } from "@stripe/stripe-js";
import moment from "moment"; // npm install moment
function AllStepCheckOutForm() {
const [service, setService] = useState({});
const [form] = Form.useForm();
const params = useParams();
const [current, setCurrent] = useState(0);
const [selectedSubService, setSelectedSubService] = useState([]);
const { TextArea } = Input;
const [formData, setFormData] = useState({});
const navigate = useNavigate();
const monthFormat = "MM/YY";
const user_id = localStorage.getItem("user_id");
const [error, setError] = useState(null);
const [availableTimeSlots, setAvailableTimeSlots] = useState([]);
const [setSuccess] = useState(false);
const stripePromise = loadStripe(
"pk_test_51Nu6oIL0v3CrBX83LGIIF7Jg1hTUm7LqnHABeSt8Yz0VTyDHTL4ecgodTtLsbhksXbJbd1t4GO7V10nmhM6QbSlh00vyRy9Gv5"
);
console.log("params.serviceId:", params.serviceId);
console.log("Service Data:", service);
const steps = [
{
title: "รายการ",
content: "First-content",
},
{
title: "กรอกข้อมูลบริการ",
content: "Second-content",
},
{
title: "ชำระเงิน",
content: "Third-content",
},
];
const items = steps.map((item) => ({ key: item.title, title: item.title }));
const next = () => {
setCurrent(current + 1);
};
const prev = () => {
setCurrent(current - 1);
};
const getService = async (serviceId) => {
try {
const response = await axios.get(
`http://localhost:4000/service/${serviceId}`
);
const serviceData = response.data.data;
if (serviceData) {
setService(serviceData);
} else {
console.error("Service data is not valid:", serviceData);
}
} catch (error) {
console.error("Error fetching service data:", error);
}
};
useEffect(() => {
getService(params.serviceId);
}, [params.serviceId]);
const handleIncrement = (subService) => {
const index = selectedSubService.findIndex(
(item) => item.sub_service_id === subService.sub_service_id
);
if (index === -1) {
setSelectedSubService([
...selectedSubService,
{ ...subService, count: 1 },
]);
} else {
const updatedSubService = [...selectedSubService];
updatedSubService[index].count += 1;
setSelectedSubService(updatedSubService);
}
};
const handleDecrement = (subServiceId) => {
const updatedSubService = [...selectedSubService];
const subServiceIndex = updatedSubService.findIndex(
(item) => item.sub_service_id === subServiceId
);
if (subServiceIndex !== -1) {
updatedSubService[subServiceIndex].count -= 1;
if (updatedSubService[subServiceIndex].count === 0) {
updatedSubService.splice(subServiceIndex, 1);
}
setSelectedSubService(updatedSubService);
}
};
const calculateTotalPrice = () => {
return selectedSubService;
};
const handleFormChange = (changedValues) => {
setFormData({ ...formData, ...changedValues });
};
const [selectedPaymentMethod, setSelectedPaymentMethod] = useState(null);
const handlePaymentMethodClick = (method) => {
setSelectedPaymentMethod(method);
};
const handleSubmitOrder = async (e, stripe) => {
e.preventDefault();
if (!stripe) {
console.error("Stripe.js has not loaded yet.");
return;
}
if (!error) {
try {
const response = await axios.post("http://localhost:4000/payment", {
amount: calculateTotalPrice(), // Pass the total amount here
});
if (response.data.success) {
console.log("Successful payment");
setSuccess(true);
// Call the orderToServer function here to submit the order
await orderToServer();
}
} catch (error) {
console.log("Error", error);
message.error("Payment failed. Please try again.");
}
} else {
console.log(error.message);
message.error("Payment failed. Please check your card details.");
}
};
const orderToServer = async () => {
try {
const response = await axios.post("http://localhost:4000/checkout", {
selectedSubService,
formData,
user_id,
});
// Handle the response here, e.g., you can log it or perform further actions.
console.log("server data",response.data);
} catch (error) {
// Handle any errors that occur during the request.
console.error(error);
}
};
useEffect(() => {
const currentTime = moment();
const bookingStartTime = currentTime.clone().add(1, "hour");
const closingTime = moment("20:00", "HH:mm"); // Replace with your service's closing time
const timeSlots = [];
while (bookingStartTime.isBefore(closingTime)) {
timeSlots.push(bookingStartTime);
bookingStartTime.add(15, "minutes"); // Add 15 minutes to get the next time slot
}
setAvailableTimeSlots(timeSlots);
}, []);
console.log("current is:", current);
console.log("Form:", formData);
console.log("Subservices:", selectedSubService);
return (
<div className="First-content bg-grey300" content="First-content">
<Navbar />
<div className="">
{service.service_photo && service.service_photo ? (
<div className="h-[300px] overflow-hidden flex items-center justify-center relative bg-blue900">
<img
src={service.service_photo}
alt="Service Photo"
className="min-w-full mt-40 mix-blend-screen"
/>
<div className="rounded-lg px-10 py-[10px] w-auto h-[68px] text-center text-[#646C80] bg-opacity-12 shadow-[2px_2px_24px_rgba(23,51,106,0.12)] absolute bg-white left-[12rem]">
บริการของเรา
<img src={greyarrow} className="inline mx-3" />
<span className="text-[32px] text-[#336DF2] ">
{service.service_name}
</span>
</div>
</div>
) : (
<p>No service photo available.</p>
)}
{current !== 3 && ( // Hide Steps on the Summary page
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps current={current} labelPlacement="vertical" items={items} />
</div>
)}
</div>
<div className="flex my-8 lg:mx-[12rem] md:mx-10 justify-between min-h-screen w-[80%] bg-white ">
{current === 0 ? (
<div className="h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg bg-white mt-20 ">
<div className="text-[20px] text-[#646C80]">
เลือกรายการบริการ{service.service_name}
</div>
<div className="mt-4">
{service.sub_service && service.sub_service.length > 0 && (
<div>
<ul>
{service.sub_service.map((subService, index) => (
<div
key={subService.sub_service_id}
className={`py-5 flex justify-between items-center${
index === service.sub_service.length - 1
? ""
: " border-b border-[#CCD0D7]"
}`}
>
<div>
<li className="text-[18px] font-bold">
{subService.sub_service_name}
</li>
<img src={sellblack} className="inline mr-2" />
<li className="text-[14px] text-[#646C80] inline">
{subService.price_per_unit}.00฿ / {subService.unit}
</li>
</div>
<div className="flex flex-row items-center p-">
<div className="flex items-center justify-center mx-3 w-[43px] h-[43px] border border-[#336DF2] rounded-[8px]">
<button
className="text-[25px] text-[#336DF2]"
onClick={() =>
handleDecrement(subService.sub_service_id)
}
>
-
</button>
</div>
<div className="mx-3">
{selectedSubService.find(
(item) =>
item.sub_service_id ===
subService.sub_service_id
)?.count || 0}
</div>
<div className="flex items-center justify-center mx-3 w-[43px] h-[43px] border border-[#336DF2] rounded-[8px]">
<button
className="text-[25px] text-[#336DF2]"
onClick={() => handleIncrement(subService)}
>
+
</button>
</div>
</div>
</div>
))}
</ul>
</div>
)}
</div>
</div>
) : current === 1 ? (
<div
className="Second-content h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20"
content="Second-content"
>
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps
current={current}
labelPlacement="vertical"
items={items}
/>
</div>
<div className="flex my-8 lg:mx-[12rem] md:mx-10 justify-between min-h-screen w-[80%]">
<div className="h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20 ">
<Form
labelCol={{ span: 5 }}
wrapperCol={{ span: 19 }}
form={form}
autoComplete="on"
>
<h1 className="text-gray300 text-center text-[20px] font-medium">
กรอกข้อมูลบริการ
</h1>
<Form.Item
label="วันและเวลาที่สะดวกใช้บริการ"
className="font-medium text-grey900"
name="service_date_time"
>
<DatePicker
format="DD/MM/YYYY"
placeholder="กรุณาเลือกวัน"
className="w-[22.5vw] h-[44px] px-4 py-2.5"
value={moment(formData.service_date_time)}
onChange={(date) =>
handleFormChange({
service_date_time: moment(
`${date.format("DD/MM/YYYY")} ${formData.service_date_time.format(
"HH:mm"
)}`,
"DD/MM/YYYY HH:mm"
),
})
}
disabledDate={(current) =>
current && current < moment().startOf("day")
}
/>
<TimePicker
format="HH:mm"
placeholder="กรุณาเลือกเวลา"
className="w-[22.5vw] h-[44px] px-4 py-2.5"
value={moment(formData.service_date_time)}
onChange={(time) =>
handleFormChange({
service_date_time: moment(
`${formData.service_date_time.format("DD/MM/YYYY")} ${time.format(
"HH:mm"
)}`,
"DD/MM/YYYY HH:mm"
),
})
}
disabledTime={(current) =>
availableTimeSlots
.filter((timeSlot) => timeSlot.hours() === current.hours())
.map((timeSlot) => timeSlot.minutes())
.filter((minute) => !current.minutes().includes(minute))
}
/>
</Form.Item>
<Form.Item
label="ที่อยู่"
className="font-medium text-grey900"
name="address"
>
<Input
placeholder="กรุณากรอกที่อยู่"
allowClear
value={formData.address}
onChange={(e) =>
handleFormChange({ address: e.target.value })
}
/>
</Form.Item>
<div className="w-full flex justify-between mt-4">
<Form.Item
label="แขวง / ตำบล"
className="font-medium text-grey900"
name="subdistrict"
>
<Input
placeholder="กรุณากรอกแขวง / ตำบล"
allowClear
value={formData.subdistrict}
onChange={(e) =>
handleFormChange({ subdistrict: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="เขต / อำเภอ"
className="font-medium text-grey900"
name="district"
>
<Input
placeholder="กรุณากรอกเขต / อำเภอ"
allowClear
value={formData.district}
onChange={(e) =>
handleFormChange({ district: e.target.value })
}
/>
</Form.Item>
</div>
<div className="w-full flex justify-between mt-4">
<Form.Item
label="จังหวัด"
className="font-medium text-grey900"
name="province"
>
<Input
placeholder="กรุณากรอกจังหวัด"
allowClear
value={formData.province}
onChange={(e) =>
handleFormChange({ province: e.target.value })
}
/>
</Form.Item>
<Form.Item
label="รหัสไปรษณีย์"
className="font-medium text-grey900"
name="zipcode"
>
<Input
placeholder="กรุณากรอกรหัสไปรษณีย์"
allowClear
value={formData.zipcode}
onChange={(e) =>
handleFormChange({ zipcode: e.target.value })
}
/>
</Form.Item>
</div>
<Form.Item
label="ระบุข้อมูลเพิ่มเติม"
className="font-medium text-grey900"
name="note"
>
<TextArea
placeholder="กรุณาระบุข้อมูลเพิ่มเติม"
autoSize={{ minRows: 3 }}
value={formData.note}
onChange={(e) =>
handleFormChange({ note: e.target.value })
}
/>
</Form.Item>
</Form>
</div>
</div>
</div>
) : current === 2 ? (
<div
className="Last-content h-full w-[687px] lg:mr-[2vw] py-8 px-6 mb-[125px] flex flex-col justify-between border border-grey300 rounded-lg mt-20"
content="Last-content"
>
<div className="w-[80%] h-[129px] border border-[#D8D8D8] py-[19px] px-[160px] rounded-lg mx-auto top-80 absolute bg-white left-[12rem] ">
<Steps
current={current}
labelPlacement="vertical"
items={items}
/>
</div>
{/* <Elements stripe={stripePromise}> */}
<div>ชำระเงิน</div>
<div className="flex justify-evenly mt-4">
<button
className={`w-full border border-[#CCD0D7] rounded-lg p-1 flex flex-col justify-center items-center focus:outline-none focus:ring focus:ring-[#336DF2] ${
selectedPaymentMethod === "qr"
? "bg-[#E7EEFF] focus:ring focus:ring-[#336DF2]"
: ""
}`}
onClick={() => handlePaymentMethodClick("qr")}
>
<img src={qr} />
<p>พร้อมเพย์</p>
</button>
<button
className={`w-full border border-[#CCD0D7] rounded-lg p-1 ml-4 flex flex-col justify-center items-center focus:outline-none focus:ring focus:ring-[#336DF2] ${
selectedPaymentMethod === "credit"
? "bg-[#E7EEFF] focus:ring focus:ring-[#336DF2]"
: ""
}`}
onClick={() => handlePaymentMethodClick("credit")}
>
<img src={credit} />
<p>บัตรเครดิต</p>
</button>
</div>
<div className="mt-5">
<p>
หมายเลขบัตรเครดิต<span className="text-[#C82438]">*</span>
</p>
<input
placeholder="กรุณากรอกหมายเลขบัตรเครดิต"
className="w-full border border-[#CCD0D7] rounded-lg p-2"
required
/>
</div>
<div className="mt-5">
<p>
ชื่อบนบัตร<span className="text-[#C82438]">*</span>
</p>
<input
placeholder="กรุณากรอกชื่อบนบัตร"
className="w-full border border-[#CCD0D7] rounded-lg p-2"
required
/>
</div>
<div className="flex mt-5">
<div>
<p>
วันหมดอายุ<span className="text-[#C82438]">*</span>
</p>
<DatePicker
defaultValue={dayjs("2015/01", monthFormat)}
format={monthFormat}
picker="month"
placeholder="MM/YY"
required
/>
</div>
<div className="ml-4">
<p>
รหัส CVC / CVV<span className="text-[#C82438]">*</span>
</p>
<input
type="tel"
placeholder="xxx"
className="w-full border border-[#CCD0D7] rounded-lg p-0.5"
maxLength="3"
pattern="([0-9]{3})"
required
/>
</div>
</div>
<div className="my-8 w-full h-[1px] border border-[#CCD0D7]"></div>
<div>
<p>Promotion Code</p>
<input
placeholder="กรุณากรอกโค้ดส่วนลด (ถ้ามี)"
className="w-full border border-[#CCD0D7] rounded-lg p-1"
/>
</div>
<div className="pt-6 ml-5">
<button className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-20 p-1 px-1 bg-[#336DF2] rounded-lg">
ใช้โค้ด
</button>
</div>
{/* </Elements> */}
</div>
) : null}
{/* summary-box */}
<div className="h-full w-[562px] py-8 px-6 flex flex-col justify-between border border-grey300 rounded-lg mr-0 top-40 mt-20 ">
<div className="summary-box flex-auto text-center pb-3 text-[40px] text-[#646C80]">
{" "}
{current === 3 ? "ชำระเงินเรียบร้อยแล้ว" : "สรุปรายการ"}
</div>
<ul>
{calculateTotalPrice().map((item, index) => (
<li key={index} className="flex justify-between">
<p className="text-black">{item.sub_service_name}</p>
<p className="text-black">
{item.count > 1
? `${item.count} ${item.unit}`
: `1 ${item.unit}`}
</p>
</li>
))}
</ul>
<div className="w-[301]px h-[1px] border border-[#CCD0D7] mt-3"></div>
<div className="pt-10">
<div>
{" "}
{current === 1 || current === 2 || current === 3 ? (
<div>
<div className="flex justify-between">
<div className="text-[#646C80]">วันที่:</div>
<div className="text-black">
{formData.service_date_time ? formData.service_date_time.format("DD/MM/YYYY") : ""}
</div>
</div>
<div className="flex justify-between">
<div className="text-[#646C80]">เวลา:</div>
<div className="text-black">
{formData.service_date_time ? formData.service_date_time.format("HH:mm") : ""}
</div>
</div>
<div className="flex justify-between">
<div className="text-[#646C80]">สถานที่:</div>
<div className="text-black">
{formData.address} {formData.subdistrict}{" "}
{formData.district} {formData.province} {formData.zipcode}
</div>
</div>
<div className="flex justify-between">
<div className="text-[#646C80]">ข้อมูลเพิ่มเติม:</div>
<div className="text-black">{formData.note}</div>
</div>
</div>
) : null}
</div>
</div>
{current === 3 && (
<div className="w-[301]px h-[1px] border border-[#CCD0D7] mt-3"></div>
)}
<div className="flex justify-between pt-5 mb-2">
<div className="text-[16px] text-[#646C80]">รวม</div>
<div className="text-black">
{calculateTotalPrice().reduce(
(total, item) => total + item.price_per_unit * item.count,
0
)}
.00฿
</div>
</div>
{current === 3 && (
<div>
<button
className="bg-blue600 w-full h-11 rounded-lg text-white"
onClick={() => navigate(`/customer-services-history/:userId`)}
>
เช็ครายการซ่อม
</button>
</div>
)}
</div>
</div>
<div className="flex justify-between p-5 sticky bottom-0 z-[100] border-y-grey300 border-x-white border px-40 bg-white">
{current === 0 ? (
<>
<button
className="btn-secondary flex items-center justify-center text-base font-medium w-40 p-2 px-6"
onClick={() => {
// Navigate to "/services-list" when current === 0
navigate("/services-list");
}}
>
ย้อนกลับ
<img src={arrowBlue} alt="arrow" />
</button>
<button
className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-40 p-2 px-6 bg-[#336DF2] rounded-lg"
onClick={next}
>
ดำเนินการต่อ
<img src={arrowWhite} alt="goarrow" />
</button>
</>
) : (
<>
{current > 0 && (
<button
className="btn-secondary flex items-center justify-center text-base font-medium w-40 p-2 px-6"
onClick={() => prev()}
>
ย้อนกลับ
<img src={arrowBlue} alt="arrow" />
</button>
)}
{current < steps.length - 1 && (
<button
className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-40 p-2 px-6 bg-[#336DF2] rounded-lg"
onClick={current === 2 ? () => next(onFinish()) : () => next()}
>
ดำเนินการต่อ
<img src={arrowWhite} alt="goarrow" />
</button>
)}
{current === steps.length - 1 && (
<button
type="primary"
onClick={(e) => {
e.preventDefault(); // Prevent the default form submission
message.success("Processing complete!");
handleSubmitOrder(e, stripePromise);
orderToServer(e); // Pass the event object
next();
}}
className="btn-secondary-[#336DF2] flex items-center justify-center text-white font-medium w-45 p-2 px-6 bg-[#336DF2] rounded-lg"
>
ยืนยันการชำระเงิน
</button>
)}
</>
)}
</div>
</div>
);
}
export default AllStepCheckOutForm;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment