diff --git a/packages/web-domains/package.json b/packages/web-domains/package.json
index b24f0b4d..4e6d142a 100644
--- a/packages/web-domains/package.json
+++ b/packages/web-domains/package.json
@@ -24,6 +24,7 @@
"@tanstack/react-query": "^5.50.1",
"@toss/use-overlay": "^1.4.0",
"axios": "^1.7.2",
+ "react-canvas-confetti": "^2.0.7",
"react-copy-to-clipboard": "^5.1.0",
"react-countdown": "^2.3.5",
"react-hook-form": "^7.52.1"
diff --git a/packages/web-domains/src/common/animates/Confetti.tsx b/packages/web-domains/src/common/animates/Confetti.tsx
new file mode 100644
index 00000000..af396407
--- /dev/null
+++ b/packages/web-domains/src/common/animates/Confetti.tsx
@@ -0,0 +1,52 @@
+import { colors } from '@sds/theme';
+import { CSSProperties } from 'react';
+import Fireworks from 'react-canvas-confetti/dist/presets/fireworks';
+
+interface ConfettiProps {
+ position: {
+ top: number;
+ left: number;
+ };
+ width?: number;
+ height?: number;
+}
+
+export const Confetti = (props: ConfettiProps) => {
+ const {
+ position: { top, left },
+ width,
+ height,
+ } = props;
+
+ const canvasStyles: CSSProperties = {
+ width: width ?? '100%',
+ height: height ?? '100%',
+ zIndex: '3',
+ position: 'absolute',
+ top,
+ left,
+ };
+
+ const decorateOptions = (originalOptions: any) => {
+ return {
+ ...originalOptions,
+ particleCount: 100, // 조각 개수 설정
+ spread: 100, // 퍼짐 정도 설정
+ startVelocity: 50, // 초기 속도 설정
+ ticks: 200, // 애니메이션 지속 시간 설정
+ origin: { x: 0.5, y: 0.7 }, // 발사 위치 설정
+ shapes: ['square', 'circle', 'square'], // 이미지 배열을 shapes로 설정
+ gravity: 0.8, // 중력 설정
+ scalar: 1.5, // 색종이 크기
+ colors: [colors.primary500, colors.quaternary500, colors.secondary500, colors.tertiary500],
+ };
+ };
+
+ return (
+
+ );
+};
diff --git a/packages/web-domains/src/common/animates/index.ts b/packages/web-domains/src/common/animates/index.ts
new file mode 100644
index 00000000..56463932
--- /dev/null
+++ b/packages/web-domains/src/common/animates/index.ts
@@ -0,0 +1 @@
+export { Confetti } from './Confetti';
diff --git a/packages/web-domains/src/common/index.ts b/packages/web-domains/src/common/index.ts
index 88e81a3d..22ed6e9f 100644
--- a/packages/web-domains/src/common/index.ts
+++ b/packages/web-domains/src/common/index.ts
@@ -5,3 +5,4 @@ export { RootLayout } from './layout/RootLayout';
export { GlobalStyle } from './styles/GlobalStyles';
export { getWebDomain } from './utils/getWebDomain';
export * from './components/Error';
+export * from './animates';
diff --git a/packages/web-domains/src/new-meeting/features/new-meeting-closing/components/ClosingMessage.tsx b/packages/web-domains/src/new-meeting/features/new-meeting-closing/components/ClosingMessage.tsx
index 04f7fb3d..8240b672 100644
--- a/packages/web-domains/src/new-meeting/features/new-meeting-closing/components/ClosingMessage.tsx
+++ b/packages/web-domains/src/new-meeting/features/new-meeting-closing/components/ClosingMessage.tsx
@@ -1,63 +1,60 @@
-import { Txt } from '@sambad/sds/components';
+import { If } from '@sambad/react-utils';
+import { Skeleton, Txt } from '@sambad/sds/components';
import { colors, size } from '@sambad/sds/theme';
-import Image from 'next/image';
-import ClosingBackground from '../../../common/assets/images/closing-background.png';
+import { Confetti } from '@/common';
+
+import { useGetMeetingNameService } from '../services/useGetMeetingNameService';
interface ClosingMessageProps {
- name?: string;
+ inviteCode: string;
}
-const ClosingMessage = (props: ClosingMessageProps) => {
- const { name } = props;
+export const ClosingMessage = (props: ClosingMessageProps) => {
+ const { inviteCode } = props;
- if (!name) {
- null;
- }
+ const { data, isLoading, isSuccess } = useGetMeetingNameService({ inviteCode });
return (
-
-
- {name && (
-
- {name}
-
- )}
-
- 모임을 만들었어요!
-
-
- 이제 모임원을 초대해보세요!
-
-
-
+ <>
+
+
+
-
+
+
+
+
+
+ {data?.name && (
+
+ {data.name}
+
+ )}
+
+
+ 모임을 만들었어요!
+
+
+ 이제 모임원을 초대해보세요!
+
+
-
+ >
);
};
-
-export default ClosingMessage;
diff --git a/packages/web-domains/src/new-meeting/features/new-meeting-closing/containers/NewMeetingClosingContainer.tsx b/packages/web-domains/src/new-meeting/features/new-meeting-closing/containers/NewMeetingClosingContainer.tsx
index 49c1bc17..203e6572 100644
--- a/packages/web-domains/src/new-meeting/features/new-meeting-closing/containers/NewMeetingClosingContainer.tsx
+++ b/packages/web-domains/src/new-meeting/features/new-meeting-closing/containers/NewMeetingClosingContainer.tsx
@@ -6,8 +6,7 @@ import Image from 'next/image';
import Character from '../../../common/assets/images/meeting-character.png';
import { InviteCodeShareButton } from '../components/Button/InviteCodeShareButton';
-import ClosingMessage from '../components/ClosingMessage';
-import { useGetMeetingNameService } from '../services/useGetMeetingNameService';
+import { ClosingMessage } from '../components/ClosingMessage';
interface NewMeetingClosingContainerProps {
inviteCode: string;
@@ -16,8 +15,6 @@ interface NewMeetingClosingContainerProps {
const NewMeetingClosingContainer = (props: NewMeetingClosingContainerProps) => {
const { inviteCode } = props;
- const { data } = useGetMeetingNameService({ inviteCode });
-
return (
{
justifyContent: 'center',
}}
>
-
+
{
const { inviteCode } = props;
- const { data } = useGetMeetingName({ inviteCode });
+ const { data, isLoading, isSuccess } = useGetMeetingName({ inviteCode });
return (
-
-
+
+
+
+
- {data?.name && (
-
- {data?.name}
+
+
+
+
+
+ {data?.name && (
+
+ {data?.name}
+
+ )}
+
+
+ 가입이 완료되었어요!
- )}
-
- 가입이 완료되었어요!
-
+
-
-
-
+
+ >
);
};
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 646dea32..cb946801 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -335,6 +335,9 @@ importers:
axios:
specifier: ^1.7.2
version: 1.7.2
+ react-canvas-confetti:
+ specifier: ^2.0.7
+ version: 2.0.7(react@18.2.0)
react-copy-to-clipboard:
specifier: ^5.1.0
version: 5.1.0(react@18.2.0)
@@ -4331,6 +4334,10 @@ packages:
'@types/node': 20.14.10
dev: true
+ /@types/canvas-confetti@1.6.4:
+ resolution: {integrity: sha512-fNyZ/Fdw/Y92X0vv7B+BD6ysHL4xVU5dJcgzgxLdGbn8O3PezZNIJpml44lKM0nsGur+o/6+NZbZeNTt00U1uA==}
+ dev: false
+
/@types/connect@3.4.38:
resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==}
dependencies:
@@ -5885,6 +5892,10 @@ packages:
/caniuse-lite@1.0.30001642:
resolution: {integrity: sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==}
+ /canvas-confetti@1.9.3:
+ resolution: {integrity: sha512-rFfTURMvmVEX1gyXFgn5QMn81bYk70qa0HLzcIOSVEyl57n6o9ItHeBtUSWdvKAPY0xlvBHno4/v3QPrT83q9g==}
+ dev: false
+
/case-sensitive-paths-webpack-plugin@2.4.0:
resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==}
engines: {node: '>=4'}
@@ -10585,6 +10596,16 @@ packages:
strip-json-comments: 2.0.1
dev: true
+ /react-canvas-confetti@2.0.7(react@18.2.0):
+ resolution: {integrity: sha512-DIj44O35TPAwJkUSIZqWdVsgAMHtVf8h7YNmnr3jF3bn5mG+d7Rh9gEcRmdJfYgRzh6K+MAGujwUoIqQyLnMJw==}
+ peerDependencies:
+ react: '*'
+ dependencies:
+ '@types/canvas-confetti': 1.6.4
+ canvas-confetti: 1.9.3
+ react: 18.2.0
+ dev: false
+
/react-colorful@5.6.1(react-dom@18.2.0)(react@18.2.0):
resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==}
peerDependencies: