1+ // import { useSuspenseQuery } from '@tanstack/react-query';
2+ // import { useEffect, useState } from 'react';
3+
4+ // import { gatheringAPIService } from '@/app/invite/gathering/[gatheringId]/src/service';
5+ // import { CardFrame } from '@/app/proposal/[proposalId]/detail/components/GatheringProposalContent';
6+ // import AppInstallBanner from '@/shared/components/AppInstallBanner';
7+ // import { useParam } from '@/shared/hooks/useParam';
8+ // import { cn } from '@/shared/lib';
9+
10+ // const BANNER_KEY = 'gathering-banner-dismissed-at';
11+ // const BANNER_RESHOW_MINUTES = 30;
12+
13+ // const InviteGatheringContent = () => {
14+ // const gatheringId = Number(useParam('gatheringId'));
15+
16+ // const { data: proposalDetail } = useSuspenseQuery({
17+ // queryKey: ['getGatheringName', gatheringId],
18+ // queryFn: () => gatheringAPIService.getGatheringName(gatheringId),
19+ // });
20+
21+ // const [showBanner, setShowBanner] = useState(false);
22+
23+ // const handleCloseBanner = () => {
24+ // localStorage.setItem(BANNER_KEY, Date.now().toString());
25+ // setShowBanner(false);
26+ // };
27+
28+ // useEffect(() => {
29+ // const dismissedAt = localStorage.getItem(BANNER_KEY);
30+ // const now = Date.now();
31+
32+ // if (!dismissedAt) {
33+ // setShowBanner(true);
34+ // } else {
35+ // const dismissedTime = parseInt(dismissedAt, 10);
36+ // const thirtyMinutes = BANNER_RESHOW_MINUTES * 60 * 1000;
37+ // if (now - dismissedTime > thirtyMinutes) {
38+ // setShowBanner(true);
39+ // }
40+ // }
41+ // }, []);
42+
43+ // return (
44+ // <>
45+ // {showBanner && <AppInstallBanner onClose={handleCloseBanner} /> }
46+
47+ // <h2
48+ // className={cn(
49+ // 'serif-title-22-M font-bold text-gray-900',
50+ // showBanner ? 'mt-[6.875rem]' : 'mt-[1.875rem]'
51+ // )}
52+ // >
53+ // 모임에
54+ // <br />
55+ // 참여하시겠어요?
56+ // </h2>
57+
58+ // <div className="relative mt-[70px] flex flex-col items-center justify-center">
59+ // <div className="h-[320px] w-[278px] rounded-[10px] bg-gray-50" />
60+ // <div
61+ // className={cn(
62+ // 'absolute bottom-[-80px] left-1/2 h-[421px] w-[408px] -translate-x-1/2 translate-y-0'
63+ // )}
64+ // >
65+ // <div className="relative size-full">
66+ // <div className="absolute inset-0 z-0">
67+ // <CardFrame />
68+ // </div>
69+
70+ // {proposalDetail.data.gatheringName && (
71+ // <div className="serif-body-16-M absolute left-1/2 top-[180px] z-[1] -translate-x-1/2 text-center text-gray-900">
72+ // {proposalDetail.data.gatheringName}
73+ // </div>
74+ // )}
75+ // </div>
76+ // </div>
77+ // </div>
78+ // </>
79+ // );
80+ // };
81+
82+ // export default InviteGatheringContent;
83+
84+ 'use client' ;
85+
186import { useSuspenseQuery } from '@tanstack/react-query' ;
287import { useEffect , useState } from 'react' ;
388
4- import { gatheringAPIService } from '@/app/invite/gathering/[gatheringId]/src/service' ;
89+ import { gatheringAPIService } from '../service' ;
90+
591import { CardFrame } from '@/app/proposal/[proposalId]/detail/components/GatheringProposalContent' ;
692import AppInstallBanner from '@/shared/components/AppInstallBanner' ;
793import { useParam } from '@/shared/hooks/useParam' ;
@@ -28,7 +114,6 @@ const InviteGatheringContent = () => {
28114 useEffect ( ( ) => {
29115 const dismissedAt = localStorage . getItem ( BANNER_KEY ) ;
30116 const now = Date . now ( ) ;
31-
32117 if ( ! dismissedAt ) {
33118 setShowBanner ( true ) ;
34119 } else {
@@ -44,24 +129,27 @@ const InviteGatheringContent = () => {
44129 < >
45130 { showBanner && < AppInstallBanner onClose = { handleCloseBanner } /> }
46131
132+ { /* 배너 노출 시: safe-area 포함하여 충분한 상단 여백 확보 */ }
47133 < h2
48134 className = { cn (
49135 'serif-title-22-M font-bold text-gray-900' ,
50- showBanner ? 'mt-[6.875rem]' : 'mt-[1.875rem]'
136+ showBanner
137+ ? 'mt-[calc(110px+env(safe-area-inset-top))]' // 기존 6.875rem(110px) + 노치
138+ : 'mt-[1.875rem]' // 30px
51139 ) }
52140 >
53141 모임에
54142 < br />
55143 참여하시겠어요?
56144 </ h2 >
57145
58- < div className = "relative mt-[70px] flex flex-col items-center justify-center" >
146+ { /* 카드/프레임 영역 */ }
147+ < div className = "relative mt-[56px] flex flex-col items-center justify-center" >
148+ { /* 카드 배경 박스 (그림자/여백 안정화) */ }
59149 < div className = "h-[320px] w-[278px] rounded-[10px] bg-gray-50" />
60- < div
61- className = { cn (
62- 'absolute bottom-[-80px] left-1/2 h-[421px] w-[408px] -translate-x-1/2 translate-y-0'
63- ) }
64- >
150+
151+ { /* 프레임을 살짝 겹치게 띄워서 시각적 포커스 */ }
152+ < div className = "pointer-events-none absolute bottom-[-80px] left-1/2 h-[421px] w-[408px] -translate-x-1/2" >
65153 < div className = "relative size-full" >
66154 < div className = "absolute inset-0 z-0" >
67155 < CardFrame />
@@ -75,6 +163,9 @@ const InviteGatheringContent = () => {
75163 </ div >
76164 </ div >
77165 </ div >
166+
167+ { /* 본문 끝에서 한 번 더 하단 여백 확보 (작은 기기 대비) */ }
168+ < div className = "h-8" />
78169 </ >
79170 ) ;
80171} ;
0 commit comments