Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ const LetterDetailModal = ({
overlayClassName={styles.modalOverlay}
contentClassName={styles.modalContent}
fullScreenOnMobile={false}
closeOnOverlayClick={true}
>
<section className={styles.container}>
{imageUrl && (
Expand Down
12 changes: 8 additions & 4 deletions app/(sub)/capsule-detail/_components/modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface ModalProps {
contentClassName?: string;
fullScreenOnMobile?: boolean;
closeOnOverlayClick?: boolean;
closeOnEsc?: boolean;
}

export default function Modal({
Expand All @@ -22,25 +23,28 @@ export default function Modal({
overlayClassName,
contentClassName,
fullScreenOnMobile = true,
closeOnOverlayClick = false,
closeOnOverlayClick = true,
closeOnEsc = true,
}: ModalProps) {
Comment thread
seung365 marked this conversation as resolved.
useEffect(() => {
const handleEscapeKey = (event: KeyboardEvent) => {
if (event.key === "Escape" && isOpen) {
if (event.key === "Escape" && isOpen && closeOnEsc) {
onClose();
}
};

if (isOpen) {
document.addEventListener("keydown", handleEscapeKey);
if (closeOnEsc) {
document.addEventListener("keydown", handleEscapeKey);
}
document.body.style.overflow = "hidden";
}

return () => {
document.removeEventListener("keydown", handleEscapeKey);
document.body.style.overflow = "unset";
};
}, [isOpen, onClose]);
}, [isOpen, onClose, closeOnEsc]);

if (!isOpen) return null;

Expand Down
72 changes: 47 additions & 25 deletions app/(sub)/capsule-detail/_components/write-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
"use client";

import { useWriteLetter } from "@/shared/api/mutations/letter";
import Close from "@/shared/assets/icon/close.svg";
import Plus from "@/shared/assets/icon/plus.svg";
import type { CapsuleDetailRes } from "@/shared/types/api/capsule";
import type { WriteLetterReq } from "@/shared/types/api/letter";
import Chip from "@/shared/ui/chip";
import RevealMotion from "@/shared/ui/motion/reveal-motion";
import ShakeYMotion from "@/shared/ui/motion/shakeY-motion";
import PopupConfirmLetter from "@/shared/ui/popup/popup-confirm-letter";
import PopupWarningLetter from "@/shared/ui/popup/popup-warning-letter";
import { PulseLoader } from "react-spinners";
import { useWriteLetter } from "@/shared/api/mutations/letter";
import type { CapsuleDetailRes } from "@/shared/types/api/capsule";
import type { WriteLetterReq } from "@/shared/types/api/letter";
import { formatOpenDateString } from "@/shared/utils/date";
import Image from "next/image";
import { useState } from "react";
import { useForm, useController } from "react-hook-form";
import { useController, useForm } from "react-hook-form";
import { PulseLoader } from "react-spinners";
import Modal from "../modal";
import { useImageUpload } from "./_hooks/use-image-upload";
import * as styles from "./write-modal.css";
Expand Down Expand Up @@ -90,22 +90,26 @@ const WriteModal = ({
});
};

const handleCloseWithWarning = () => {
setIsWarningOpen(true);
reset({
capsuleId: capsuleData.result.id.toString(),
content: "",
from: "",
objectKey: "",
});
if (uploadedImageUrl) {
removeImage();
const handleCloseWithWarning = (e: React.MouseEvent) => {
e.stopPropagation();

const hasContent =
contentField.value?.trim() || fromField.value?.trim() || uploadedImageUrl;

if (hasContent) {
setIsWarningOpen(true);
} else {
onClose();
}
};

return (
<>
<Modal isOpen={isOpen} onClose={onClose}>
<Modal
isOpen={isOpen}
onClose={onClose}
closeOnEsc={false}
closeOnOverlayClick={false}
>
<form className={styles.container} onSubmit={handleSubmit(onSubmit)}>
<div className={styles.header}>
<button
Expand All @@ -115,12 +119,16 @@ const WriteModal = ({
>
닫기
</button>
<button
type="submit"
className={styles.title}
disabled={(isPending || isUploading)}
<button
type="submit"
className={styles.title}
disabled={isPending || isUploading}
>
{(isPending || isUploading) ? <PulseLoader color="#FFFFFF" size={5}/> : '편지담기'}
{isPending || isUploading ? (
<PulseLoader color="#FFFFFF" size={5} />
) : (
"편지담기"
)}
</button>
</div>

Expand Down Expand Up @@ -156,7 +164,7 @@ const WriteModal = ({
{contentField.value?.length || 0}/1000
</span>
</div>

{uploadedImageUrl ? (
<div className={styles.imagePreviewContainer}>
<button
Expand Down Expand Up @@ -227,15 +235,29 @@ const WriteModal = ({
/>
)}
</Modal>

{isWarningOpen && (
<PopupWarningLetter
isOpen={isWarningOpen}
close={() => {
setIsWarningOpen(false);
}}
confirm={() => {
setIsWarningOpen(false);
}}
onGoBack={() => {
setIsWarningOpen(false);
reset({
capsuleId: capsuleData.result.id.toString(),
content: "",
from: "",
objectKey: "",
});
if (uploadedImageUrl) {
removeImage();
}
onClose();
}}
confirm={() => setIsWarningOpen(false)}
/>
)}
</>
Expand Down
14 changes: 12 additions & 2 deletions shared/ui/popup/popup-warning-letter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ interface PopupWarningLetterProps {
isOpen: boolean;
close: () => void;
confirm: () => void;
onGoBack?: () => void;
}

const PopupWarningLetter = ({
isOpen,
close,
confirm,
onGoBack,
}: PopupWarningLetterProps) => {
return (
<Popup open={isOpen} close={close}>
Expand All @@ -25,8 +27,16 @@ const PopupWarningLetter = ({
</div>
</Popup.Title>
<Popup.Actions>
<Popup.Button onClick={close} className={styles.content}>돌아가기</Popup.Button>
<Popup.Button className={styles.continueButton} onClick={confirm}>
<Popup.Button onClick={onGoBack || close} className={styles.content}>
돌아가기
</Popup.Button>
<Popup.Button
className={styles.continueButton}
onClick={(e) => {
e.stopPropagation();
confirm();
}}
>
계속 쓰기
</Popup.Button>
</Popup.Actions>
Expand Down