"use client"; import type { HTMLAttributes } from "react"; import { useCallback, useEffect, useId, useMemo, useRef, useState } from "react"; import { useHardwareBackHandler } from "@/hooks/use-hardware-back-handler"; import { useI18n } from "@/translations/provider"; import Button from "./button"; const EXIT_ANIMATION_MS = 220; export type DismissReasonSheetProps = Omit< HTMLAttributes, "title" | "onSubmit" > & { closeOnOutside?: boolean; onClose?: () => void; onSubmit?: (value: string) => void; }; export function DismissReasonSheet({ closeOnOutside = true, onClose, onSubmit, className, ...props }: DismissReasonSheetProps) { const { dictionary: t } = useI18n(); const options = useMemo( () => [ t["Not a good personal fit"], t["No mutual interest"], t["Different expectations"], t["No connection felt"], t["Location not suitable"], t["Other reasons"], ], [t], ); const groupId = useId(); const [isVisible, setIsVisible] = useState(true); const [isClosing, setIsClosing] = useState(false); const [selectedReasons, setSelectedReasons] = useState([]); const [reasonText, setReasonText] = useState(""); const textareaRef = useRef(null); const isMountedRef = useRef(true); useEffect(() => { isMountedRef.current = true; return () => { isMountedRef.current = false; }; }, []); useEffect(() => { const otherReason = options[options.length - 1]; if (selectedReasons.includes(otherReason)) { const timeoutId = setTimeout(() => { textareaRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest", }); }, 100); return () => clearTimeout(timeoutId); } }, [selectedReasons, options]); const closeSheet = useCallback(() => { if (isClosing) { return; } setIsClosing(true); window.setTimeout(() => { if (isMountedRef.current) { setIsVisible(false); } onClose?.(); }, EXIT_ANIMATION_MS); }, [isClosing, onClose]); useHardwareBackHandler(closeSheet, isVisible && !isClosing); useEffect(() => { if (!isVisible) { return; } const previousBodyOverflow = document.body.style.overflow; const previousHtmlOverflow = document.documentElement.style.overflow; document.body.style.overflow = "hidden"; document.documentElement.style.overflow = "hidden"; return () => { document.body.style.overflow = previousBodyOverflow; document.documentElement.style.overflow = previousHtmlOverflow; }; }, [isVisible]); if (!isVisible) { return null; } return ( { if (closeOnOutside && event.target === event.currentTarget) { closeSheet(); } }} onKeyDown={(event) => { if ( closeOnOutside && event.target === event.currentTarget && (event.key === "Escape" || event.key === "Enter" || event.key === " ") ) { event.preventDefault(); closeSheet(); } }} > {t["Dismiss reasons"]} { t[ "Please provide the full reason for rejecting the submitted item" ] } {t["Dismiss reasons"]} {options.map((option) => { const checked = selectedReasons.includes(option); const showTextArea = option === options[options.length - 1]; return ( { setSelectedReasons((prev) => prev.includes(option) ? prev.filter((r) => r !== option) : [...prev, option], ); }} > {checked ? ( ) : null} {option} {checked && showTextArea ? ( setReasonText(event.target.value) } /> ) : null} ); })} { const activeReasons = selectedReasons.map((r) => { if (r === options[options.length - 1]) { return reasonText ? `${r}: ${reasonText}` : r; } return r; }); onSubmit?.(activeReasons.join("\n")); closeSheet(); }} > {t["Decline"]} ); } export default DismissReasonSheet;
{ t[ "Please provide the full reason for rejecting the submitted item" ] }