Skip to content

Commit 447cb6a

Browse files
committed
fix: safe area 테스트
1 parent 144b8ea commit 447cb6a

File tree

5 files changed

+59
-51
lines changed

5 files changed

+59
-51
lines changed

apps/tuk-web/src/app/invite/gathering/[gatheringId]/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import InviteGathering from '@/app/invite/gathering/[gatheringId]/src/components/InviteGathering';
2-
import SplashGate from '@/app/invite/gathering/[gatheringId]/src/components/SplashGate';
2+
import SplashGate from '@/shared/components/SplashGate';
33

44
export default async function InviteGatheringPage() {
55
return (

apps/tuk-web/src/app/invite/gathering/[gatheringId]/src/components/InviteGathering.tsx

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,36 @@ import InviteGatheringSkeleton from '@/app/invite/gathering/[gatheringId]/src/co
1010
import SkeletonGuard from '@/app/invite/meet/[meetId]/src/components/SkeletonGuard';
1111
import { BackgroundTemplate, Button } from '@/shared/components';
1212
import { useParam } from '@/shared/hooks/useParam';
13+
import { cn } from '@/shared/lib';
1314

1415
const InviteGathering = () => {
1516
const gatheringId = Number(useParam('gatheringId'));
1617

1718
return (
1819
<BackgroundTemplate>
19-
<BackgroundTemplate.Main className="overflow-y-auto px-5">
20-
<BackgroundTemplate.Gradient />
20+
<BackgroundTemplate.Main className="px-5">
21+
<BackgroundTemplate.Gradient className="pointer-events-none" />
2122

22-
<QueryErrorResetBoundary>
23-
{({ reset }) => (
24-
<ErrorBoundary onReset={reset} FallbackComponent={InviteGatheringErrorFallback}>
25-
<SkeletonGuard minMs={250} skeleton={<InviteGatheringSkeleton />}>
26-
<Suspense fallback={null}>
27-
<InviteGatheringContent />
28-
</Suspense>
29-
</SkeletonGuard>
30-
</ErrorBoundary>
23+
<div
24+
className={cn(
25+
'relative z-10 mx-auto w-full max-w-[600px]',
26+
'min-h-[100svh]',
27+
'overflow-y-auto [-webkit-overflow-scrolling:touch]',
28+
'pb-[calc(120px+env(safe-area-inset-bottom,0px))]'
3129
)}
32-
</QueryErrorResetBoundary>
33-
30+
>
31+
<QueryErrorResetBoundary>
32+
{({ reset }) => (
33+
<ErrorBoundary onReset={reset} FallbackComponent={InviteGatheringErrorFallback}>
34+
<SkeletonGuard minMs={250} skeleton={<InviteGatheringSkeleton />}>
35+
<Suspense fallback={null}>
36+
<InviteGatheringContent />
37+
</Suspense>
38+
</SkeletonGuard>
39+
</ErrorBoundary>
40+
)}
41+
</QueryErrorResetBoundary>
42+
</div>
3443
<BackgroundTemplate.CTA>
3544
<Button
3645
className="w-full"

apps/tuk-web/src/app/invite/gathering/[gatheringId]/src/components/InviteGatheringContent.tsx

Lines changed: 26 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
'use client';
2+
13
import { useSuspenseQuery } from '@tanstack/react-query';
2-
import { useEffect, useState } from 'react';
4+
import { useState } from 'react';
5+
6+
import { gatheringAPIService } from '../service';
37

4-
import { gatheringAPIService } from '@/app/invite/gathering/[gatheringId]/src/service';
58
import { CardFrame } from '@/app/proposal/[proposalId]/detail/components/GatheringProposalContent';
69
import AppInstallBanner from '@/shared/components/AppInstallBanner';
710
import { useParam } from '@/shared/hooks/useParam';
811
import { cn } from '@/shared/lib';
912

10-
const BANNER_KEY = 'gathering-banner-dismissed-at';
11-
const BANNER_RESHOW_MINUTES = 30;
13+
// const BANNER_KEY = 'gathering-banner-dismissed-at';
14+
// const BANNER_RESHOW_MINUTES = 30;
1215

1316
const InviteGatheringContent = () => {
1417
const gatheringId = Number(useParam('gatheringId'));
@@ -18,27 +21,26 @@ const InviteGatheringContent = () => {
1821
queryFn: () => gatheringAPIService.getGatheringName(gatheringId),
1922
});
2023

21-
const [showBanner, setShowBanner] = useState(false);
24+
const [showBanner, setShowBanner] = useState(true);
2225

2326
const handleCloseBanner = () => {
24-
localStorage.setItem(BANNER_KEY, Date.now().toString());
27+
// localStorage.setItem(BANNER_KEY, Date.now().toString());
2528
setShowBanner(false);
2629
};
2730

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-
}, []);
31+
// useEffect(() => {
32+
// const dismissedAt = localStorage.getItem(BANNER_KEY);
33+
// const now = Date.now();
34+
// if (!dismissedAt) {
35+
// setShowBanner(true);
36+
// } else {
37+
// const dismissedTime = parseInt(dismissedAt, 10);
38+
// const thirtyMinutes = BANNER_RESHOW_MINUTES * 60 * 1000;
39+
// if (now - dismissedTime > thirtyMinutes) {
40+
// setShowBanner(true);
41+
// }
42+
// }
43+
// }, []);
4244

4345
return (
4446
<>
@@ -47,21 +49,18 @@ const InviteGatheringContent = () => {
4749
<h2
4850
className={cn(
4951
'serif-title-22-M font-bold text-gray-900',
50-
showBanner ? 'mt-[6.875rem]' : 'mt-[1.875rem]'
52+
showBanner ? 'mt-[calc(70px+env(safe-area-inset-top,0px))]' : 'mt-[1.875rem]'
5153
)}
5254
>
5355
모임에
5456
<br />
5557
참여하시겠어요?
5658
</h2>
5759

58-
<div className="relative mt-[70px] flex flex-col items-center justify-center">
60+
<div className="relative mt-[56px] flex flex-col items-center justify-center">
5961
<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-
>
62+
63+
<div className="pointer-events-none absolute bottom-[-80px] left-1/2 h-[421px] w-[408px] -translate-x-1/2">
6564
<div className="relative size-full">
6665
<div className="absolute inset-0 z-0">
6766
<CardFrame />

apps/tuk-web/src/shared/components/AppInstallBanner.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
'use client';
2+
13
import { CloseIcon24 } from '@/shared/components/icon';
24

35
const AppInstallBanner = ({ onClose }: { onClose: () => void }) => {
46
return (
5-
<div className="fixed left-1/2 top-0 z-20 flex h-14 w-full max-w-[600px] -translate-x-1/2 items-center justify-between bg-gray-50 px-5 text-black-default">
7+
<div className="fixed left-1/2 top-0 z-20 flex h-[calc(56px+env(safe-area-inset-top))] w-full max-w-[600px] -translate-x-1/2 items-center justify-between bg-gray-50 px-5 pt-[max(0px,env(safe-area-inset-top))] text-black-default shadow-[0_1px_0_0_rgba(0,0,0,0.04)] backdrop-blur-[2px]">
68
<div className="flex items-center gap-2">
7-
<button onClick={onClose}>
9+
<button onClick={onClose} aria-label="배너 닫기">
810
<CloseIcon24 />
911
</button>
1012
<div className="flex items-center gap-2">

apps/tuk-web/src/app/invite/gathering/[gatheringId]/src/components/SplashGate.tsx renamed to apps/tuk-web/src/shared/components/SplashGate.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@
33
import Image from 'next/image';
44
import { useEffect, useState } from 'react';
55

6+
import { cn } from '@/shared/lib';
7+
68
type SplashGateProps = {
7-
/** 최소 표시 시간 (ms) */
89
minMs?: number;
9-
/** 로고 경로 (public/ 기준) */
1010
logoSrc?: string;
11-
/** 로고 크기(px) */
1211
logoSize?: number;
13-
/** 페이드아웃 시간(ms) */
1412
fadeMs?: number;
1513
children: React.ReactNode;
1614
};
@@ -26,9 +24,7 @@ export default function SplashGate({
2624
const [fadeOut, setFadeOut] = useState(false);
2725

2826
useEffect(() => {
29-
// 최소 표시 시간 보장
3027
const t = setTimeout(() => {
31-
// 모션 감소 환경이면 바로 제거
3228
const media = window.matchMedia('(prefers-reduced-motion: reduce)');
3329
if (media.matches || fadeMs === 0) {
3430
setShow(false);
@@ -50,8 +46,10 @@ export default function SplashGate({
5046
<div
5147
aria-busy="true"
5248
aria-live="polite"
53-
className={`fixed inset-0 z-[9999] flex items-center justify-center bg-white-default ${fadeOut ? 'opacity-0 transition-opacity' : 'opacity-100'} `}
54-
// Tailwind transition-duration 커스텀
49+
className={cn(
50+
'fixed inset-0 z-[9999] flex items-center justify-center bg-white-default',
51+
fadeOut ? 'opacity-0 transition-opacity' : 'opacity-100'
52+
)}
5553
style={{ transitionDuration: `${fadeMs}ms` }}
5654
>
5755
<Image src={logoSrc} alt="App Logo" width={logoSize} height={logoSize} priority />

0 commit comments

Comments
 (0)