diff --git a/src/pages/Host/Spaces/Add/SpaceDetailsTwo.jsx b/src/pages/Host/Spaces/Add/SpaceDetailsTwo.jsx index 4ed54a1..5a622b1 100644 --- a/src/pages/Host/Spaces/Add/SpaceDetailsTwo.jsx +++ b/src/pages/Host/Spaces/Add/SpaceDetailsTwo.jsx @@ -13,7 +13,12 @@ import MkdSDK from "@/utils/MkdSDK"; import useDelayUnmount from "@/hooks/useDelayUnmount"; import { useContext } from "react"; 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 CustomSelectV2 from "@/components/CustomSelectV2"; import useCancellation from "@/hooks/api/useCancellation"; @@ -110,17 +115,33 @@ const SpaceDetailsTwo = () => { for (let i = 0; i < pictures.length; i++) { const file = pictures[i]; - const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'image/svg+xml']; - if (file?.type && !allowedTypes.includes(file?.type)) { - showToast(globalDispatch, 'Invalid file type. Only JPEG, PNG, WEBP, and SVG are allowed.', 4000, "ERROR"); + const allowedTypes = [ + "image/jpeg", + "image/png", + "image/webp", + "image/svg+xml", + ]; + if (file?.type && !allowedTypes.includes(file?.type)) { + showToast( + globalDispatch, + "Invalid file type. Only JPEG, PNG, WEBP, and SVG are allowed.", + 4000, + "ERROR" + ); return; - } + } + + if (file?.size && file?.size > 5 * 1024 * 1024) { + // 5 MB limit + showToast( + globalDispatch, + "One or more of the image is too large. Max size is 5 MB.", + 4000, + "ERROR" + ); + return; + } - if (file?.size && file?.size > 5 * 1024 * 1024) { // 5 MB limit - showToast(globalDispatch, 'One of the image is too large. Max size is 5 MB.', 4000, "ERROR"); - return; - } - const upload = await handleImageUpload(file); uploadedImages[i] = upload.url; uploadedIds[i] = upload.id; @@ -128,7 +149,16 @@ const SpaceDetailsTwo = () => { 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" }); navigate("/spaces/add/3"); @@ -156,7 +186,7 @@ const SpaceDetailsTwo = () => { name: spaceData.name, rule: spaceData.rule, }, - "POST", + "POST" ); dispatch({ type: "SET_PROPERTY_ID", payload: propertyResult.message }); } @@ -177,7 +207,7 @@ const SpaceDetailsTwo = () => { additional_guest_rate: spaceData.additional_guest_rate || undefined, size: spaceData.size || undefined, }, - "POST", + "POST" ); } @@ -190,7 +220,7 @@ const SpaceDetailsTwo = () => { property_id: propertyResult?.message ?? spaceData.property_id, add_on_id: addon_id, }, - "POST", + "POST" ); } @@ -208,7 +238,7 @@ const SpaceDetailsTwo = () => { photo_id: upload.id, is_approved: IMAGE_STATUS.IN_REVIEW, }, - "POST", + "POST" ); } if (file?.name == formValues.thumbnail) { @@ -219,7 +249,7 @@ const SpaceDetailsTwo = () => { default_image_id: upload.id, // is_approved: IMAGE_STATUS.APPROVED, }, - "PUT", + "PUT" ); } } @@ -234,7 +264,7 @@ const SpaceDetailsTwo = () => { question: faq.question, answer: faq.answer, }, - "POST", + "POST" ); } @@ -247,7 +277,7 @@ const SpaceDetailsTwo = () => { property_spaces_id: propertySpaceResult.message, amenity_id, }, - "POST", + "POST" ); } navigate("/account/my-spaces"); @@ -278,138 +308,228 @@ const SpaceDetailsTwo = () => { setPictures((prev) => { var copy = [...prev]; copy[i] = picFile; - return copy; + return copy.filter(Boolean); }); }); } }, []); - function isCatOthers(){ - const cat = spaceCategories.find((cat) => Number(cat.id) == Number(spaceData.category)) + function isCatOthers() { + const cat = spaceCategories.find( + (cat) => Number(cat.id) == Number(spaceData.category) + ); if (cat?.category === "Others") { - return true - } else return false + return true; + } else return false; } return ( -
-
-

Space Details

-
-

* Photographs of the space

-

file type (jpeg/png/svg), max size (5MB), suggest resolution (640*480)

-
- {pictures.map((file, idx) => { - // add FileUploader logic here - })} +
+ +

Space Details

+
+

+ * Photographs of the space +

+

+ file type (jpeg/png/svg), max size (5MB), suggest resolution + (640*480) +

+
+ {/* FileUploader for images */} + { + 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 */} +
+ {pictures.map((file, idx) => { + const imageUrl = + file instanceof File ? URL.createObjectURL(file) : file; + + return ( +
+ {`preview-${idx + +
+ ); + })} +
-

* Select thumbnail image

+

* Select thumbnail image

pic?.name)} - labelField="name" - valueField="name" - containerClassName="mb-12" - className="w-full border py-2 px-3 focus:outline-primary" - openClassName="ring-primary ring-2" + labelField='name' + valueField='name' + containerClassName='mb-12' + className='w-full border px-3 py-2 focus:outline-primary' + openClassName='ring-primary ring-2' placeholder={"Select thumbnail"} control={control} - name="thumbnail" + name='thumbnail' /> -

- What do you offer with the space (optional) +

+ What do you offer with the space{" "} + + (optional) +

-
- - +
+
-
+
{amenities ?.filter((am) => { if (Array.isArray(selectedAmenities)) { return selectedAmenities?.includes(String(am.id)); } 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) => (
  • + className='mb-4 flex w-fit items-center gap-2 sm:mb-0' + key={am.id} + > {am.name}
  • ))}
    -

    - Add-ons (optional) +

    + Add-ons{" "} + + (optional) +

    -
    - - +
    +
    - -
    + +
    {addons ?.filter((addon) => { if (Array.isArray(selectedAddons)) { return selectedAddons?.includes(String(addon.id)); } 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) => (
  • + className='mb-4 flex w-fit items-center gap-2 sm:mb-0' + key={addon.id} + > - {addon.name}
  • + {addon.name} + ))}
    -

    - Frequently asked question (optional) +

    + Frequently asked question{" "} + + (optional) +

    These FAQs will show as part of your space listing.

    {fields.map((field, index) => ( -
    -
    - +
    +
    +

    - + setValue(`faqs.${index}.answer`, content)} - placeholder="" + width='100%' + height='107px' + onChange={(content) => + setValue(`faqs.${index}.answer`, content) + } + placeholder='' hideToolbar={true} setOptions={{ resizingBar: false }} defaultValue={getValues().faqs[index].answer} @@ -418,157 +538,190 @@ const SpaceDetailsTwo = () => { ))}
    -
    -

    -

    -
    - +

    +
    + View More
    -
    +

    setAddAmenitiesPopup(false)} >
    e.stopPropagation()} > -
    -

    Select Amenities

    +
    +

    + Select Amenities +

    -
    - {isCatOthers() ? - amenities.sort((a, b) => (a.creator_id !== 1 ? -1 : 1) - (b.creator_id !== 1 ? -1 : 1)).map((am) => ( -
    - - -
    - )) - : - 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) => ( -
    - - -
    - )) - } +
    + {isCatOthers() + ? amenities + .sort( + (a, b) => + (a.creator_id !== 1 ? -1 : 1) - + (b.creator_id !== 1 ? -1 : 1) + ) + .map((am) => ( +
    + + +
    + )) + : 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) => ( +
    + + +
    + ))}
    setAddAddonsPopup(false)} >
    e.stopPropagation()} > -
    -

    Select Addons

    +
    +

    Select Addons

    -
    - {isCatOthers() ? - addons.sort((a, b) => (a.creator_id !== 1 ? -1 : 1) - (b.creator_id !== 1 ? -1 : 1)).map((addon) => ( -
    - - -
    - )) - : - 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) => ( -
    - - -
    - )) - - } +
    + {isCatOthers() + ? addons + .sort( + (a, b) => + (a.creator_id !== 1 ? -1 : 1) - + (b.creator_id !== 1 ? -1 : 1) + ) + .map((addon) => ( +
    + + +
    + )) + : 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) => ( +
    + + +
    + ))}
    - {addOnModal && - - } + {addOnModal && }
    ); };