//HANDLE CHARACTERS LABEL UNDER OFFER -> LOAD useEffect(() => { const setLinkEditorMethods = () => { //SPECIAL DISCOUNT FORM INPUT const form = document.querySelector(".offer-form-item") as HTMLElement; if(form) { const inputBox = form.getElementsByClassName('ant-form-item-has-success')[0] as HTMLElement; const hasError = form.querySelector(".ant-form-item-explain-error") as HTMLElement; //Initial Check if (inputBox) { inputBox.style.marginBottom = hasError ? "24px" : "0px"; } } //FRONT SECOND INPUT const form2 = document.querySelector(".link-editor-form") as HTMLElement; if(form2) { const inputBox2 = form2.getElementsByClassName('ant-form-item-has-success')[1] as HTMLElement; //Initial Check if(inputBox2) { inputBox2.style.marginBottom = "24px"; } } //console.log(form.getElementsByClassName('ant-form-item-has-success')); }; if (isModalOpen && linkType === LINK_TYPES.SPECIAL_OFFER) { // Wait briefly to allow DOM to mount const interval = setInterval(setLinkEditorMethods, 100); const timeout = setTimeout(() => clearInterval(interval), 2000); return () => { clearInterval(interval); clearTimeout(timeout); }; } if (isModalOpen && linkType === LINK_TYPES.NORMAL) { // Wait briefly to allow DOM to mount const interval = setInterval(setLinkEditorMethods, 100); const timeout = setTimeout(() => clearInterval(interval), 2000); return () => { clearInterval(interval); clearTimeout(timeout); }; } }, [isModalOpen, linkType]); // ๐ include `linkType` ================================================================================================================= #V3 INCLUDING MUTATION OBSERVERS [WORKING] useEffect(() => { const adjustDiscountLabelMargin = () => { const form = document.querySelector(".offer-form-item") as HTMLElement; const inputBox = form.getElementsByClassName('ant-form-item-has-success')[0] as HTMLElement; const hasError = form.querySelector(".ant-form-item-explain-error") as HTMLElement; //Create a Mutation Observer to Observe This Element const observer = new MutationObserver(() => { const hasError = document.querySelector(".offer-form-item .ant-form-item-explain-error"); //discountLabel.style.marginBottom = hasError ? "24px" : "0px"; inputBox.style.marginBottom = hasError ? "24px" : "0px"; }); observer.observe(form, { childList: true, subtree: true, }); //Initial Check if (inputBox) { console.log('FIRED') inputBox.style.marginBottom = hasError ? "24px" : "0px"; } return () => observer.disconnect(); }; if (isModalOpen && linkType === LINK_TYPES.SPECIAL_OFFER) { // Wait briefly to allow DOM to mount const interval = setInterval(adjustDiscountLabelMargin, 100); const timeout = setTimeout(() => clearInterval(interval), 2000); return () => { clearInterval(interval); clearTimeout(timeout); }; } }, [isModalOpen, linkType]); // ๐ include `linkType` ===================================================================================================== //HANDLE CHARACTERS LABEL UNDER OFFER -> LOAD useEffect(() => { const adjustDiscountLabelMargin = () => { const form = document.querySelector(".offer-form-item .ant-form-item-has-success") as HTMLElement; const hasError = document.querySelector(".ant-form-item-explain-error") as HTMLElement; if (form) { //console.log(form); form.style.marginBottom = hasError ? "24px" : "0px"; } }; if (isModalOpen && linkType === LINK_TYPES.SPECIAL_OFFER) { // Wait briefly to allow DOM to mount const interval = setInterval(adjustDiscountLabelMargin, 100); const timeout = setTimeout(() => clearInterval(interval), 2000); return () => { clearInterval(interval); clearTimeout(timeout); }; } }, [isModalOpen, linkType]); // ๐ include `linkType` //USE MUTATION OBSERVER TO CHECK WHEN ERROR LABEL IS ACTIVATED -> OBSERVER useEffect(() => { console.log('FIRED'); if (!(isModalOpen && linkType === LINK_TYPES.SPECIAL_OFFER)) return; const formItem = document.querySelector(".offer-form-item") as HTMLElement; const discountLabel = document.querySelector(".offer-form-item .ant-form-item-has-success") as HTMLElement; if (!formItem || !discountLabel) return; const observer = new MutationObserver(() => { const hasError = document.querySelector(".offer-form-item .ant-form-item-explain-error"); discountLabel.style.marginBottom = hasError ? "24px" : "0px"; }); observer.observe(formItem, { childList: true, subtree: true, }); // Initial check const hasError = document.querySelector(".offer-form-item .ant-form-item-has-success"); discountLabel.style.marginBottom = hasError ? "24px" : "0px"; return () => observer.disconnect(); }, [isModalOpen, linkType]); ======================================================================================= "use client"; import React, { useRef, useState, useEffect } from "react"; import { Upload } from "antd"; import { Col, Row } from "antd/lib/grid"; import "../css/base/App.scss" import "../css/base/spacing.scss" import "../css/base/modal.scss" import "../css/base/tabs.scss" import "../css/base/text.scss" import "../css/base/display.scss" import "../css/base/form.scss" import "../css/onboardingFlow.scss" import "../css/LinkEditorModal.scss"; import "../css/ProductEditorModal.scss"; import "../css/ModuleOndemandVideo.scss"; import "../css/ModuleShopify.scss" import Modal from "@/components/Modal/Modal"; // Adjust this path as needed import Tabs from "antd/lib/tabs"; import Button from "antd/lib/button"; import Alert from "antd/lib/alert"; import * as yup from "yup"; import { Text } from "@/components/Typography/Text"; import classNames from "classnames"; import ImageUpload from "@/components/ImageUpload/ImageUpload"; import { Field, Form, Formik, FormikProps } from "formik"; import { LinkItem } from "@/models/talent/talent-profile-module.model"; import { AntInput, FieldType } from "@/components/Form/FormItem"; //import icon import InfoIcon from "@/icons/Infoicon"; import CloseOutlineIcon from "@/icons/Closeoutlineicon"; const initialProductValues: LinkItem = { title: "", url: "", order: 0, visible: true, }; const initialSpecialOfferValues: LinkItem = { title: "", url: "", order: 0, specialOffer: { thumbnail: "", title: "", storeUrl: "", couponCode: "", }, visible: true, }; const LINK_TYPES = { NORMAL: "NORMAL", SPECIAL_OFFER: "SPECIAL_OFFER", }; const Icon = ({ className, name, width, height }: { className?: string; name: string; width?: number; height?: number }) => { return ( [icon: {name}] ); }; const dummyPhoto = { url: "https://via.placeholder.com/369", // static test image fileName: "placeholder.jpg", loading: false, }; const onUploadSuccess = (file: any) => { console.log("Upload success:", file); }; const onRemove = (file: any) => { console.log("Removed:", file); }; const validateLinkSchema = yup.object().shape({ title: yup.string().required("Please enter the link title"), url: yup .string() .required("Please enter the URL") .url("Please enter a valid URL"), }); const validateSpecialOfferSchema = yup.object().shape({ specialOffer: yup.object().shape({ title: yup .string() .required("Please add the offer information") .test("len", "Offer not more than 50 characters", (val) => { if (val == undefined) { return true; } return val.length == 0 || (val.length >= 1 && val.length <= 50); }), storeUrl: yup .string() .required("Please enter the URL") .url("Please enter a valid URL"), }), }); export type LinkEditorModalFormValues = Pick< LinkItem, "thumbnail" | "url" | "title" | "specialOffer" | "order" | "visible" >; export default function Page() { const [isModalOpen, setIsModalOpen] = useState(false); // Dummy state vars to eliminate TS errors const [linkType, setLinkType] = useState(LINK_TYPES.NORMAL); const [isEdit, setIsEdit] = useState(false); const [showAlert, setShowAlert] = useState(true); const [initialValues, setInitialValues] = useState(); function handleSubmit(values: LinkEditorModalFormValues, formikHelpers: FormikHelpers): void | Promise { throw new Error("Function not implemented."); } const dummyOptions = [ { label: "Option A", value: "A" }, { label: "Option B", value: "B" }, ]; const [modalTop, setModalTop] = useState(); // default safe gap const modalRef = useRef(null); let newTop: number; //CUSTOM LOGIC: HANDLE THE TOP OF THE MODAL OF DIFFERENT PLATFORMS useEffect(() => { const updateModalTop = () => { const modalEl = document.querySelector('.link-editor-modal') as HTMLElement; if (!modalEl) return; const modalHeight = modalEl.getBoundingClientRect().height; const windowHeight = window.innerHeight; const isMobile = window.innerWidth <= 768; //PLATFORM LOGIC if(!isMobile) { if (modalHeight + 60 > windowHeight) { newTop = 20; setModalTop(newTop); //console.log('DESKTOP OVERFLOW'); } else { //newTop = Math.max((windowHeight - modalHeight) / 4, 30); newTop = 20; setModalTop(newTop); //console.log('DESKTOP CENTERED'); } } else { if (modalHeight + 60 > windowHeight) { newTop = 20; setModalTop(newTop); //console.log('MOBILE OVERFLOW'); } else { //newTop = Math.max((windowHeight - ( modalHeight + 120) / 2), 30);; //setModalTop(newTop); modalEl.style.removeProperty('top'); console.log('MOBILE CENTERED'); } } modalEl.style.top = `${newTop}px`; // ๐ฅ Direct DOM update }; if (isModalOpen) { setTimeout(updateModalTop, 100); // Wait for DOM to fully render window.addEventListener("resize", updateModalTop); } return () => { window.removeEventListener("resize", updateModalTop); }; }, [isModalOpen, linkType]); //HANDLE CHARACTERS LABEL UNDER OFFER -> LOAD useEffect(() => { const adjustDiscountLabelMargin = () => { const form = document.querySelector(".offer-form-item .ant-form-item-has-success") as HTMLElement; const hasError = document.querySelector(".ant-form-item-explain-error") as HTMLElement; if (form) { //console.log(form); form.style.marginBottom = hasError ? "24px" : "0px"; } }; if (isModalOpen && linkType === LINK_TYPES.SPECIAL_OFFER) { // Wait briefly to allow DOM to mount const interval = setInterval(adjustDiscountLabelMargin, 100); const timeout = setTimeout(() => clearInterval(interval), 2000); return () => { clearInterval(interval); clearTimeout(timeout); }; } if (isModalOpen && linkType === LINK_TYPES.NORMAL) { // Wait briefly to allow DOM to mount console.log('FIRED') const form = document.querySelector(".link-editor-form") as HTMLElement; const inputBox = form.getElementsByClassName('ant-input-status-success')[1] as HTMLElement; if (form) { //console.log(form); inputBox.style.removeProperty("marginBottom"); } } }, [isModalOpen, linkType]); // ๐ include `linkType` return ( <> {/** INLINE ROOT STYLING */} 1: Home setIsModalOpen(true)}>Open Modal setIsModalOpen(false)} maskClosable={false} ref={modalRef} > setLinkType(activeKey)} activeKey={linkType} className={isEdit ? "is-edit" : ""} > {!isEdit && ( Link} key={LINK_TYPES.NORMAL} /> )} {!isEdit && ( Special offers} key={LINK_TYPES.SPECIAL_OFFER} > {showAlert && ( } showIcon closeText={ } onClose={() => { setShowAlert(false); localStorage.setItem( "CLOSE_ALERT_ADD_SPECIAL_OFFER", "true" ); }} /> )} )} {/* IMAGE UPLOAD BUTTON */} Thumbnail Photo {/* //TODO */} Use a size thatโs at least 369 x 369 pixels and 6MB or less <> {linkType === LINK_TYPES.NORMAL ? ( <> > ) : ( <> {`0/50 characters`} > )} Cancel Done > This is the modal content. > ); }
1: Home
This is the modal content.