ISSUE 3: add image uploader and include add FAQ logic
This commit is contained in:
@@ -13,7 +13,12 @@ import MkdSDK from "@/utils/MkdSDK";
|
|||||||
import useDelayUnmount from "@/hooks/useDelayUnmount";
|
import useDelayUnmount from "@/hooks/useDelayUnmount";
|
||||||
import { useContext } from "react";
|
import { useContext } from "react";
|
||||||
import { GlobalContext, showToast } from "@/globalContext";
|
import { GlobalContext, showToast } from "@/globalContext";
|
||||||
import { DRAFT_STATUS, IMAGE_STATUS, SPACE_STATUS, SPACE_VISIBILITY } from "@/utils/constants";
|
import {
|
||||||
|
DRAFT_STATUS,
|
||||||
|
IMAGE_STATUS,
|
||||||
|
SPACE_STATUS,
|
||||||
|
SPACE_VISIBILITY,
|
||||||
|
} from "@/utils/constants";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import CustomSelectV2 from "@/components/CustomSelectV2";
|
import CustomSelectV2 from "@/components/CustomSelectV2";
|
||||||
import useCancellation from "@/hooks/api/useCancellation";
|
import useCancellation from "@/hooks/api/useCancellation";
|
||||||
@@ -110,14 +115,30 @@ const SpaceDetailsTwo = () => {
|
|||||||
|
|
||||||
for (let i = 0; i < pictures.length; i++) {
|
for (let i = 0; i < pictures.length; i++) {
|
||||||
const file = pictures[i];
|
const file = pictures[i];
|
||||||
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml'];
|
const allowedTypes = [
|
||||||
|
"image/jpeg",
|
||||||
|
"image/png",
|
||||||
|
"image/webp",
|
||||||
|
"image/svg+xml",
|
||||||
|
];
|
||||||
if (file?.type && !allowedTypes.includes(file?.type)) {
|
if (file?.type && !allowedTypes.includes(file?.type)) {
|
||||||
showToast(globalDispatch, 'Invalid file type. Only JPEG, PNG, WEBP, and SVG are allowed.', 4000, "ERROR");
|
showToast(
|
||||||
|
globalDispatch,
|
||||||
|
"Invalid file type. Only JPEG, PNG, WEBP, and SVG are allowed.",
|
||||||
|
4000,
|
||||||
|
"ERROR"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file?.size && file?.size > 5 * 1024 * 1024) { // 5 MB limit
|
if (file?.size && file?.size > 5 * 1024 * 1024) {
|
||||||
showToast(globalDispatch, 'One of the image is too large. Max size is 5 MB.', 4000, "ERROR");
|
// 5 MB limit
|
||||||
|
showToast(
|
||||||
|
globalDispatch,
|
||||||
|
"One or more of the image is too large. Max size is 5 MB.",
|
||||||
|
4000,
|
||||||
|
"ERROR"
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,7 +149,16 @@ const SpaceDetailsTwo = () => {
|
|||||||
dispatch({ type: "SET_THUMBNAIL", payload: upload.id });
|
dispatch({ type: "SET_THUMBNAIL", payload: upload.id });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch({ type: "SET_DETAILS_TWO", payload: { faqs: data.faqs, amenities: data.amenities, addons: data.addons, pictures: uploadedImages, pictureIds: uploadedIds } });
|
dispatch({
|
||||||
|
type: "SET_DETAILS_TWO",
|
||||||
|
payload: {
|
||||||
|
faqs: data.faqs,
|
||||||
|
amenities: data.amenities,
|
||||||
|
addons: data.addons,
|
||||||
|
pictures: uploadedImages,
|
||||||
|
pictureIds: uploadedIds,
|
||||||
|
},
|
||||||
|
});
|
||||||
globalDispatch({ type: "STOP_LOADING" });
|
globalDispatch({ type: "STOP_LOADING" });
|
||||||
|
|
||||||
navigate("/spaces/add/3");
|
navigate("/spaces/add/3");
|
||||||
@@ -156,7 +186,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
name: spaceData.name,
|
name: spaceData.name,
|
||||||
rule: spaceData.rule,
|
rule: spaceData.rule,
|
||||||
},
|
},
|
||||||
"POST",
|
"POST"
|
||||||
);
|
);
|
||||||
dispatch({ type: "SET_PROPERTY_ID", payload: propertyResult.message });
|
dispatch({ type: "SET_PROPERTY_ID", payload: propertyResult.message });
|
||||||
}
|
}
|
||||||
@@ -177,7 +207,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
additional_guest_rate: spaceData.additional_guest_rate || undefined,
|
additional_guest_rate: spaceData.additional_guest_rate || undefined,
|
||||||
size: spaceData.size || undefined,
|
size: spaceData.size || undefined,
|
||||||
},
|
},
|
||||||
"POST",
|
"POST"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +220,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
property_id: propertyResult?.message ?? spaceData.property_id,
|
property_id: propertyResult?.message ?? spaceData.property_id,
|
||||||
add_on_id: addon_id,
|
add_on_id: addon_id,
|
||||||
},
|
},
|
||||||
"POST",
|
"POST"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +238,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
photo_id: upload.id,
|
photo_id: upload.id,
|
||||||
is_approved: IMAGE_STATUS.IN_REVIEW,
|
is_approved: IMAGE_STATUS.IN_REVIEW,
|
||||||
},
|
},
|
||||||
"POST",
|
"POST"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (file?.name == formValues.thumbnail) {
|
if (file?.name == formValues.thumbnail) {
|
||||||
@@ -219,7 +249,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
default_image_id: upload.id,
|
default_image_id: upload.id,
|
||||||
// is_approved: IMAGE_STATUS.APPROVED,
|
// is_approved: IMAGE_STATUS.APPROVED,
|
||||||
},
|
},
|
||||||
"PUT",
|
"PUT"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -234,7 +264,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
question: faq.question,
|
question: faq.question,
|
||||||
answer: faq.answer,
|
answer: faq.answer,
|
||||||
},
|
},
|
||||||
"POST",
|
"POST"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,7 +277,7 @@ const SpaceDetailsTwo = () => {
|
|||||||
property_spaces_id: propertySpaceResult.message,
|
property_spaces_id: propertySpaceResult.message,
|
||||||
amenity_id,
|
amenity_id,
|
||||||
},
|
},
|
||||||
"POST",
|
"POST"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
navigate("/account/my-spaces");
|
navigate("/account/my-spaces");
|
||||||
@@ -278,138 +308,228 @@ const SpaceDetailsTwo = () => {
|
|||||||
setPictures((prev) => {
|
setPictures((prev) => {
|
||||||
var copy = [...prev];
|
var copy = [...prev];
|
||||||
copy[i] = picFile;
|
copy[i] = picFile;
|
||||||
return copy;
|
return copy.filter(Boolean);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
function isCatOthers(){
|
function isCatOthers() {
|
||||||
const cat = spaceCategories.find((cat) => Number(cat.id) == Number(spaceData.category))
|
const cat = spaceCategories.find(
|
||||||
|
(cat) => Number(cat.id) == Number(spaceData.category)
|
||||||
|
);
|
||||||
if (cat?.category === "Others") {
|
if (cat?.category === "Others") {
|
||||||
return true
|
return true;
|
||||||
} else return false
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen pb-40 md:max-w-[656px]">
|
<div className='min-h-screen pb-40 md:max-w-[656px]'>
|
||||||
<form
|
<form onSubmit={handleSubmit(onSubmit)} autoComplete='off'>
|
||||||
onSubmit={handleSubmit(onSubmit)}
|
<h1 className='mb-8 text-3xl font-bold md:text-4xl'>Space Details</h1>
|
||||||
autoComplete="off"
|
<div className='text-sm md:px-[20px] md:py-[32px]'>
|
||||||
>
|
<h3 className='text-xl font-semibold md:text-2xl'>
|
||||||
<h1 className="mb-8 text-3xl font-bold md:text-4xl">Space Details</h1>
|
* Photographs of the space
|
||||||
<div className="text-sm md:px-[20px] md:py-[32px]">
|
</h3>
|
||||||
<h3 className="text-xl font-semibold md:text-2xl">* Photographs of the space</h3>
|
<p className='mb-8'>
|
||||||
<p className="mb-8">file type (jpeg/png/svg), max size (5MB), suggest resolution (640*480)</p>
|
file type (jpeg/png/svg), max size (5MB), suggest resolution
|
||||||
<div className="eighteen-step-image mb-8 flex flex-wrap justify-center gap-x-2 gap-y-4 md:gap-5">
|
(640*480)
|
||||||
|
</p>
|
||||||
|
<div className='mb-8 flex flex-col justify-center gap-x-2 gap-y-4 md:gap-5'>
|
||||||
|
{/* FileUploader for images */}
|
||||||
|
<FileUploader
|
||||||
|
multiple
|
||||||
|
handleChange={(files) => {
|
||||||
|
const fileArray =
|
||||||
|
files instanceof FileList ? Array.from(files) : [files];
|
||||||
|
|
||||||
|
// Enforce max 6 images
|
||||||
|
if (pictures.length + fileArray.length > 6) {
|
||||||
|
showToast(
|
||||||
|
globalDispatch,
|
||||||
|
"You can only upload up to 6 images.",
|
||||||
|
4000,
|
||||||
|
"ERROR"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforce 1MB per image
|
||||||
|
for (let file of fileArray) {
|
||||||
|
if (file.size > 1024 * 1024) {
|
||||||
|
showToast(
|
||||||
|
globalDispatch,
|
||||||
|
"Each image must not exceed 1MB.",
|
||||||
|
4000,
|
||||||
|
"ERROR"
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setPictures((prev) => [...prev, ...fileArray]);
|
||||||
|
}}
|
||||||
|
name='images'
|
||||||
|
types={["JPG", "PNG", "JPEG", "SVG", "WEBP"]}
|
||||||
|
maxSize={1}
|
||||||
|
/>
|
||||||
|
{/* Show previews */}
|
||||||
|
<div className='eighteen-step-image flex flex-wrap gap-2'>
|
||||||
{pictures.map((file, idx) => {
|
{pictures.map((file, idx) => {
|
||||||
// add FileUploader logic here
|
const imageUrl =
|
||||||
|
file instanceof File ? URL.createObjectURL(file) : file;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={idx}
|
||||||
|
className='relative flex flex-col items-center'
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={imageUrl}
|
||||||
|
alt={`preview-${idx + 1}`}
|
||||||
|
className='mb-2 h-24 w-24 rounded border object-cover'
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='text-xs text-red-500 underline'
|
||||||
|
onClick={() =>
|
||||||
|
setPictures((prev) => prev.filter((_, i) => i !== idx))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Remove
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<h3 className="mb-4 text-xl font-bold">* Select thumbnail image</h3>
|
</div>
|
||||||
|
<h3 className='mb-4 text-xl font-bold'>* Select thumbnail image</h3>
|
||||||
<CustomSelectV2
|
<CustomSelectV2
|
||||||
items={pictures.filter((pic) => pic?.name)}
|
items={pictures.filter((pic) => pic?.name)}
|
||||||
labelField="name"
|
labelField='name'
|
||||||
valueField="name"
|
valueField='name'
|
||||||
containerClassName="mb-12"
|
containerClassName='mb-12'
|
||||||
className="w-full border py-2 px-3 focus:outline-primary"
|
className='w-full border px-3 py-2 focus:outline-primary'
|
||||||
openClassName="ring-primary ring-2"
|
openClassName='ring-primary ring-2'
|
||||||
placeholder={"Select thumbnail"}
|
placeholder={"Select thumbnail"}
|
||||||
control={control}
|
control={control}
|
||||||
name="thumbnail"
|
name='thumbnail'
|
||||||
/>
|
/>
|
||||||
<h3 className="mb-4 text-xl font-bold">
|
<h3 className='mb-4 text-xl font-bold'>
|
||||||
What do you offer with the space <span className="text-sm font-normal italic text-gray-500">(optional)</span>
|
What do you offer with the space{" "}
|
||||||
|
<span className='text-sm font-normal italic text-gray-500'>
|
||||||
|
(optional)
|
||||||
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex gap-3 items-center">
|
<div className='flex items-center gap-3'>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type='button'
|
||||||
className="mb-2 font-bold text-[#1570EF]"
|
className='mb-2 font-bold text-[#1570EF]'
|
||||||
onClick={() => setAddAmenitiesPopup(true)}
|
onClick={() => setAddAmenitiesPopup(true)}
|
||||||
>
|
>
|
||||||
+ Select items
|
+ Select items
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div className="addons-grid mb-12">
|
<div className='addons-grid mb-12'>
|
||||||
{amenities
|
{amenities
|
||||||
?.filter((am) => {
|
?.filter((am) => {
|
||||||
if (Array.isArray(selectedAmenities)) {
|
if (Array.isArray(selectedAmenities)) {
|
||||||
return selectedAmenities?.includes(String(am.id));
|
return selectedAmenities?.includes(String(am.id));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).sort((a, b) => (a.space_id === null ? -1 : 1) - (b.space_id === null ? -1 : 1))
|
})
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
(a.space_id === null ? -1 : 1) -
|
||||||
|
(b.space_id === null ? -1 : 1)
|
||||||
|
)
|
||||||
.map((am) => (
|
.map((am) => (
|
||||||
<li
|
<li
|
||||||
className="flex w-fit items-center gap-2 mb-4 sm:mb-0"
|
className='mb-4 flex w-fit items-center gap-2 sm:mb-0'
|
||||||
key={am.id}>
|
key={am.id}
|
||||||
|
>
|
||||||
<CircleCheckIcon />
|
<CircleCheckIcon />
|
||||||
{am.name}
|
{am.name}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<h3 className="mb-4 text-xl font-bold">
|
<h3 className='mb-4 text-xl font-bold'>
|
||||||
Add-ons <span className="text-sm font-normal italic text-gray-500">(optional)</span>
|
Add-ons{" "}
|
||||||
|
<span className='text-sm font-normal italic text-gray-500'>
|
||||||
|
(optional)
|
||||||
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex gap-3 items-center">
|
<div className='flex items-center gap-3'>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type='button'
|
||||||
className="mb-2 font-bold text-[#1570EF]"
|
className='mb-2 font-bold text-[#1570EF]'
|
||||||
onClick={() => setAddAddonsPopup(true)}
|
onClick={() => setAddAddonsPopup(true)}
|
||||||
>
|
>
|
||||||
+ Select items
|
+ Select items
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="addons-grid mb-12">
|
<div className='addons-grid mb-12'>
|
||||||
{addons
|
{addons
|
||||||
?.filter((addon) => {
|
?.filter((addon) => {
|
||||||
if (Array.isArray(selectedAddons)) {
|
if (Array.isArray(selectedAddons)) {
|
||||||
return selectedAddons?.includes(String(addon.id));
|
return selectedAddons?.includes(String(addon.id));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}).sort((a, b) => (a.space_id === null ? -1 : 1) - (b.space_id === null ? -1 : 1))
|
})
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
(a.space_id === null ? -1 : 1) -
|
||||||
|
(b.space_id === null ? -1 : 1)
|
||||||
|
)
|
||||||
.map((addon) => (
|
.map((addon) => (
|
||||||
<li
|
<li
|
||||||
className="flex w-fit items-center gap-2 mb-4 sm:mb-0"
|
className='mb-4 flex w-fit items-center gap-2 sm:mb-0'
|
||||||
key={addon.id}>
|
key={addon.id}
|
||||||
|
>
|
||||||
<CircleCheckIcon />
|
<CircleCheckIcon />
|
||||||
{addon.name}</li>
|
{addon.name}
|
||||||
|
</li>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<h3 className="mb-2 text-xl font-bold">
|
<h3 className='mb-2 text-xl font-bold'>
|
||||||
Frequently asked question <span className="text-sm font-normal italic text-gray-500">(optional)</span>
|
Frequently asked question{" "}
|
||||||
|
<span className='text-sm font-normal italic text-gray-500'>
|
||||||
|
(optional)
|
||||||
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
<p>These FAQs will show as part of your space listing.</p>
|
<p>These FAQs will show as part of your space listing.</p>
|
||||||
<div>
|
<div>
|
||||||
{fields.map((field, index) => (
|
{fields.map((field, index) => (
|
||||||
<div
|
<div className='p-[20px]' key={field.id}>
|
||||||
className="p-[20px]"
|
<div className='flex justify-between'>
|
||||||
key={field.id}
|
<label className='mb-1 font-semibold'>
|
||||||
>
|
* Question #{index + 1}
|
||||||
<div className="flex justify-between">
|
</label>
|
||||||
<label className="mb-1 font-semibold">* Question #{index + 1}</label>
|
|
||||||
<button
|
<button
|
||||||
className="text-sm font-semibold text-[#667085]"
|
className='text-sm font-semibold text-[#667085]'
|
||||||
onClick={() => remove(index)}
|
onClick={() => remove(index)}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<input
|
||||||
placeholder=""
|
placeholder=''
|
||||||
autoComplete="off"
|
autoComplete='off'
|
||||||
{...register(`faqs.${index}.question`)}
|
{...register(`faqs.${index}.question`)}
|
||||||
className={`mb-4 w-full rounded border py-2 px-3 leading-tight text-gray-700 focus:outline-primary`}
|
className={`mb-4 w-full rounded border px-3 py-2 leading-tight text-gray-700 focus:outline-primary`}
|
||||||
/>
|
/>
|
||||||
<br />
|
<br />
|
||||||
<label className="mb-2 font-semibold">* Answer #{index + 1}</label>
|
<label className='mb-2 font-semibold'>
|
||||||
|
* Answer #{index + 1}
|
||||||
|
</label>
|
||||||
<SunEditor
|
<SunEditor
|
||||||
width="100%"
|
width='100%'
|
||||||
height="107px"
|
height='107px'
|
||||||
onChange={(content) => setValue(`faqs.${index}.answer`, content)}
|
onChange={(content) =>
|
||||||
placeholder=""
|
setValue(`faqs.${index}.answer`, content)
|
||||||
|
}
|
||||||
|
placeholder=''
|
||||||
hideToolbar={true}
|
hideToolbar={true}
|
||||||
setOptions={{ resizingBar: false }}
|
setOptions={{ resizingBar: false }}
|
||||||
defaultValue={getValues().faqs[index].answer}
|
defaultValue={getValues().faqs[index].answer}
|
||||||
@@ -418,62 +538,76 @@ const SpaceDetailsTwo = () => {
|
|||||||
))}
|
))}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="mb-12 font-bold text-[#1570EF]"
|
className='mb-12 font-bold text-[#1570EF]'
|
||||||
type="button"
|
type='button'
|
||||||
id="append_faq_btn"
|
id='append_faq_btn'
|
||||||
// add logic to handle appending new FAQs field
|
onClick={() => append({ question: "", answer: "" })}
|
||||||
>
|
>
|
||||||
+ Add question
|
+ Add question
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr className="my-[20px]" />
|
<hr className='my-[20px]' />
|
||||||
<p className="px-4 text-sm md:px-0" dangerouslySetInnerHTML={{ __html: sanitizeAndTruncate(cancellationPolicy, 400) }}>
|
<p
|
||||||
</p>
|
className='px-4 text-sm md:px-0'
|
||||||
<div className="flex justify-end">
|
dangerouslySetInnerHTML={{
|
||||||
<Link to={"/help/cancellation-policy"}
|
__html: sanitizeAndTruncate(cancellationPolicy, 400),
|
||||||
className="mt-4 text-end text-sm font-semibold underline"
|
}}
|
||||||
|
></p>
|
||||||
|
<div className='flex justify-end'>
|
||||||
|
<Link
|
||||||
|
to={"/help/cancellation-policy"}
|
||||||
|
className='mt-4 text-end text-sm font-semibold underline'
|
||||||
target={"_blank"}
|
target={"_blank"}
|
||||||
>
|
>
|
||||||
View More
|
View More
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<hr className="my-[30px]" />
|
<hr className='my-[30px]' />
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type='submit'
|
||||||
className="login-btn-gradient rounded py-2 px-4 tracking-wide text-white outline-none focus:outline-none"
|
className='login-btn-gradient rounded px-4 py-2 tracking-wide text-white outline-none focus:outline-none'
|
||||||
>
|
>
|
||||||
Continue
|
Continue
|
||||||
</button>
|
</button>
|
||||||
<br />
|
<br />
|
||||||
<div
|
<div
|
||||||
className={`${showAddAmenitiesPopup ? "flex" : "hidden"} popup-container items-center justify-center normal-case`}
|
className={`${
|
||||||
|
showAddAmenitiesPopup ? "flex" : "hidden"
|
||||||
|
} popup-container items-center justify-center normal-case`}
|
||||||
onClick={() => setAddAmenitiesPopup(false)}
|
onClick={() => setAddAmenitiesPopup(false)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`${addAmenitiesPopup ? "pop-in" : "pop-out"} w-[510px] max-w-[80%] rounded-lg bg-white p-5 px-3 md:px-5`}
|
className={`${
|
||||||
|
addAmenitiesPopup ? "pop-in" : "pop-out"
|
||||||
|
} w-[510px] max-w-[80%] rounded-lg bg-white p-5 px-3 md:px-5`}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div className="mb-[18px] flex items-center justify-between">
|
<div className='mb-[18px] flex items-center justify-between'>
|
||||||
<h3 className="mb-[8px] text-2xl font-semibold">Select Amenities</h3>
|
<h3 className='mb-[8px] text-2xl font-semibold'>
|
||||||
|
Select Amenities
|
||||||
|
</h3>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type='button'
|
||||||
onClick={() => setAddAmenitiesPopup(false)}
|
onClick={() => setAddAmenitiesPopup(false)}
|
||||||
className="rounded-full border p-1 px-3 text-2xl font-normal duration-100 hover:bg-gray-200 active:bg-gray-300"
|
className='rounded-full border p-1 px-3 text-2xl font-normal duration-100 hover:bg-gray-200 active:bg-gray-300'
|
||||||
>
|
>
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="review-scroll max-h-[400px] overflow-y-auto">
|
<div className='review-scroll max-h-[400px] overflow-y-auto'>
|
||||||
{isCatOthers() ?
|
{isCatOthers()
|
||||||
amenities.sort((a, b) => (a.creator_id !== 1 ? -1 : 1) - (b.creator_id !== 1 ? -1 : 1)).map((am) => (
|
? amenities
|
||||||
<div
|
.sort(
|
||||||
key={am.id}
|
(a, b) =>
|
||||||
className="checkbox-container mb-4"
|
(a.creator_id !== 1 ? -1 : 1) -
|
||||||
>
|
(b.creator_id !== 1 ? -1 : 1)
|
||||||
|
)
|
||||||
|
.map((am) => (
|
||||||
|
<div key={am.id} className='checkbox-container mb-4'>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type='checkbox'
|
||||||
className=""
|
className=''
|
||||||
{...register("amenities")}
|
{...register("amenities")}
|
||||||
id={"amenity" + am.id}
|
id={"amenity" + am.id}
|
||||||
value={am.id}
|
value={am.id}
|
||||||
@@ -481,94 +615,113 @@ const SpaceDetailsTwo = () => {
|
|||||||
<label htmlFor={"amenity" + am.id}>{am.name}</label>
|
<label htmlFor={"amenity" + am.id}>{am.name}</label>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
:
|
: amenities
|
||||||
amenities.filter((am) => (am.space_id === Number(spaceData.category)) || am.creator_id === Number(localStorage.getItem("user"))).sort((a, b) => (a.creator_id !== 1 ? -1 : 1) - (b.creator_id !== 1 ? -1 : 1)).map((am) => (
|
.filter(
|
||||||
<div
|
(am) =>
|
||||||
key={am.id}
|
am.space_id === Number(spaceData.category) ||
|
||||||
className="checkbox-container mb-4"
|
am.creator_id === Number(localStorage.getItem("user"))
|
||||||
>
|
)
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
(a.creator_id !== 1 ? -1 : 1) -
|
||||||
|
(b.creator_id !== 1 ? -1 : 1)
|
||||||
|
)
|
||||||
|
.map((am) => (
|
||||||
|
<div key={am.id} className='checkbox-container mb-4'>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type='checkbox'
|
||||||
className=""
|
className=''
|
||||||
{...register("amenities")}
|
{...register("amenities")}
|
||||||
id={"amenity" + am.id}
|
id={"amenity" + am.id}
|
||||||
value={am.id}
|
value={am.id}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={"amenity" + am.id}>{am.name}</label>
|
<label htmlFor={"amenity" + am.id}>{am.name}</label>
|
||||||
</div>
|
</div>
|
||||||
))
|
))}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`${showAddAddonsPopup ? "flex" : "hidden"} popup-container items-center justify-center normal-case`}
|
className={`${
|
||||||
|
showAddAddonsPopup ? "flex" : "hidden"
|
||||||
|
} popup-container items-center justify-center normal-case`}
|
||||||
onClick={() => setAddAddonsPopup(false)}
|
onClick={() => setAddAddonsPopup(false)}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`${addAddonsPopup ? "pop-in" : "pop-out"} w-[510px] max-w-[80%] rounded-lg bg-white p-5 px-3 md:px-5`}
|
className={`${
|
||||||
|
addAddonsPopup ? "pop-in" : "pop-out"
|
||||||
|
} w-[510px] max-w-[80%] rounded-lg bg-white p-5 px-3 md:px-5`}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<div className="mb-[18px] flex items-center justify-between">
|
<div className='mb-[18px] flex items-center justify-between'>
|
||||||
<h3 className="mb-[8px] text-2xl font-semibold">Select Addons</h3>
|
<h3 className='mb-[8px] text-2xl font-semibold'>Select Addons</h3>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type='button'
|
||||||
onClick={() => setAddAddonsPopup(false)}
|
onClick={() => setAddAddonsPopup(false)}
|
||||||
className="rounded-full border p-1 px-3 text-2xl font-normal duration-100 hover:bg-gray-200 active:bg-gray-300"
|
className='rounded-full border p-1 px-3 text-2xl font-normal duration-100 hover:bg-gray-200 active:bg-gray-300'
|
||||||
>
|
>
|
||||||
✕
|
✕
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="review-scroll max-h-[400px] overflow-y-auto">
|
<div className='review-scroll max-h-[400px] overflow-y-auto'>
|
||||||
{isCatOthers() ?
|
{isCatOthers()
|
||||||
addons.sort((a, b) => (a.creator_id !== 1 ? -1 : 1) - (b.creator_id !== 1 ? -1 : 1)).map((addon) => (
|
? addons
|
||||||
<div
|
.sort(
|
||||||
key={addon.id}
|
(a, b) =>
|
||||||
className="checkbox-container mb-4"
|
(a.creator_id !== 1 ? -1 : 1) -
|
||||||
>
|
(b.creator_id !== 1 ? -1 : 1)
|
||||||
<input
|
)
|
||||||
type="checkbox"
|
|
||||||
{...register("addons")}
|
|
||||||
id={"addon" + addon.id}
|
|
||||||
value={addon.id}
|
|
||||||
/>
|
|
||||||
<label htmlFor={"addon" + addon.id}>{addon.name}{" "}${addon.cost}</label>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
:
|
|
||||||
addons.sort((a, b) => (a.creator_id !== 1 ? -1 : 1) - (b.creator_id !== 1 ? -1 : 1)).filter((ad) => ad.space_id === Number(spaceData.category) || ad.creator_id === Number(localStorage.getItem("user")))
|
|
||||||
.map((addon) => (
|
.map((addon) => (
|
||||||
<div
|
<div key={addon.id} className='checkbox-container mb-4'>
|
||||||
key={addon.id}
|
|
||||||
className="checkbox-container mb-4"
|
|
||||||
>
|
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type='checkbox'
|
||||||
{...register("addons")}
|
{...register("addons")}
|
||||||
id={"addon" + addon.id}
|
id={"addon" + addon.id}
|
||||||
value={addon.id}
|
value={addon.id}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={"addon" + addon.id}>{addon.name}{" "}${addon.cost}</label>
|
<label htmlFor={"addon" + addon.id}>
|
||||||
|
{addon.name} ${addon.cost}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
: addons
|
||||||
}
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
(a.creator_id !== 1 ? -1 : 1) -
|
||||||
|
(b.creator_id !== 1 ? -1 : 1)
|
||||||
|
)
|
||||||
|
.filter(
|
||||||
|
(ad) =>
|
||||||
|
ad.space_id === Number(spaceData.category) ||
|
||||||
|
ad.creator_id === Number(localStorage.getItem("user"))
|
||||||
|
)
|
||||||
|
.map((addon) => (
|
||||||
|
<div key={addon.id} className='checkbox-container mb-4'>
|
||||||
|
<input
|
||||||
|
type='checkbox'
|
||||||
|
{...register("addons")}
|
||||||
|
id={"addon" + addon.id}
|
||||||
|
value={addon.id}
|
||||||
|
/>
|
||||||
|
<label htmlFor={"addon" + addon.id}>
|
||||||
|
{addon.name} ${addon.cost}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type='button'
|
||||||
id="save-as-draft"
|
id='save-as-draft'
|
||||||
className="mt-[24px] rounded border-2 border-[#98A2B3] py-2 px-4 tracking-wide outline-none focus:outline-none"
|
className='mt-[24px] rounded border-2 border-[#98A2B3] px-4 py-2 tracking-wide outline-none focus:outline-none'
|
||||||
onClick={() => onSaveDraft()}
|
onClick={() => onSaveDraft()}
|
||||||
>
|
>
|
||||||
Save draft and exit
|
Save draft and exit
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{addOnModal &&
|
{addOnModal && <HostAddAddonsModal setAddOnModal={setAddOnModal} />}
|
||||||
<HostAddAddonsModal setAddOnModal={setAddOnModal}/>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user