From e5ee571f9e7322a1f21e114b3a65ea2deaf54b0f Mon Sep 17 00:00:00 2001 From: Jiyeon Baek <58380158+100Gyeon@users.noreply.github.com> Date: Sun, 22 Oct 2023 00:36:30 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=95=B0=ED=94=8C=EB=A6=AC=ED=8A=9C?= =?UTF-8?q?=EB=93=9C=20=EB=A1=9C=EA=B9=85=20=EC=9E=91=EC=97=85=20(#562)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 앰플리튜드 로깅 추가 * feat: 필터 모달 내 대상 기수의 활동 기수만 옵션 선택 유무 * feat: 필터 모달 내 카테고리, 모집 상태, 대상 파트 선택 * feat: 모임 개설이 완료된 케이스 * feat: 내가 만든/신청한 모임 클릭 * feat: 신청자 관리 클릭 * feat: 모임 개설하기 버튼 클릭 * feat: 공지사항 토글 비활성화 버튼 클릭 * feat: management 필터 * feat: 리스트 내 프로필 클릭 * feat: 리스트 내 신청내역 클릭 및 조회 * fix: 잘못된 타입 수정 * feat: 전체 모임 리스트 내 모임 카드 클릭 * feat: 모임 상세 뷰 캐로셀 내 애로우 클릭 * feat: 모집 현황 클릭 * feat: 모임 상세 내 개설자 프로필 클릭 * feat: 모임 상세 내 /management로 접근하는 버튼 클릭 * feat: 모임 신청하기 모달 내 [신청하기] 버튼 클릭 * feat: [신청하기] 버튼 클릭 * feat: /group에서의 페이지네이션 영역 클릭 * fix: word-break 적용 위치 수정 --- pages/index.tsx | 14 +- pages/make/index.tsx | 3 + pages/mine/index.tsx | 19 +- pages/mine/management/index.tsx | 18 +- src/ampli/index.ts | 827 +++++++++++++++++- src/components/disclosure/Disclosure.tsx | 3 +- .../feed/FeedPostViewer/FeedPostViewer.tsx | 4 +- .../page/meetingDetail/Carousel/NextArrow.tsx | 11 +- .../page/meetingDetail/Carousel/index.tsx | 6 +- .../Modal/Content/ApplicationModalContent.tsx | 10 +- .../RecruitmentStatusModalContent/index.tsx | 3 +- .../meetingDetail/MeetingController/index.tsx | 9 +- .../meetingList/Card/ManagementButton.tsx | 4 +- .../page/meetingList/Card/index.tsx | 17 +- .../Filter/Modal/Chip/ChipItem.tsx | 17 +- .../meetingList/Filter/Modal/Chip/index.tsx | 3 + .../meetingList/Filter/Modal/OpenButton.tsx | 9 +- .../meetingList/Filter/Modal/Toggle/index.tsx | 12 +- .../page/meetingList/Pagination.tsx | 14 + .../meetingManagement/ManagementListItem.tsx | 19 +- 20 files changed, 945 insertions(+), 77 deletions(-) diff --git a/pages/index.tsx b/pages/index.tsx index 333fd5cb..46d67f82 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -18,6 +18,7 @@ import WriteIcon from '@assets/svg/write.svg'; import { useQueryMyProfile } from '@api/user/hooks'; import NoticeSlider from '@components/page/meetingList/Slider/NoticeSlider/NoticeSlider'; import useNotices from '@api/notice/hooks'; +import { ampli } from '@/ampli'; const Home: NextPage = () => { const router = useRouter(); @@ -30,6 +31,7 @@ const Home: NextPage = () => { handleModalOpen(); return; } + ampli.clickMakeGroup(); router.push('/make'); }; @@ -39,12 +41,20 @@ const Home: NextPage = () => { - + { + ampli.clickNavbarGroup({ menu: '전체 모임' }); + }} + > 전체 모임 - + { + ampli.clickNavbarGroup({ menu: '내 모임' }); + }} + > 내 모임 diff --git a/pages/make/index.tsx b/pages/make/index.tsx index 15c5c70c..cd4fb8e9 100644 --- a/pages/make/index.tsx +++ b/pages/make/index.tsx @@ -9,6 +9,8 @@ import { useRouter } from 'next/router'; import PlusIcon from '@assets/svg/plus.svg'; import { useMutation } from '@tanstack/react-query'; import dynamic from 'next/dynamic'; +import { ampli } from '@/ampli'; + const DevTool = dynamic(() => import('@hookform/devtools').then(module => module.DevTool), { ssr: false, }); @@ -41,6 +43,7 @@ const MakePage = () => { const { data: { meetingId }, } = await mutateCreateMeeting(formData); + ampli.completedMakeGroup(); alert('모임을 개설했습니다.'); router.push(`/detail?id=${meetingId}`); }; diff --git a/pages/mine/index.tsx b/pages/mine/index.tsx index 9910180a..402e1569 100644 --- a/pages/mine/index.tsx +++ b/pages/mine/index.tsx @@ -12,6 +12,7 @@ import { SSRSafeSuspense } from '@components/util/SSRSafeSuspense'; import { MeetingListOfApplied, MeetingListOfMine } from '@components/page/meetingList/Grid/List'; import GridLayout from '@components/page/meetingList/Grid/Layout'; import CardSkeleton from '@components/page/meetingList/Card/Skeleton'; +import { ampli } from '@/ampli'; const enum MeetingType { MADE, @@ -26,12 +27,12 @@ const MinePage: NextPage = () => { - + ampli.clickNavbarGroup({ menu: '전체 모임' })}> 전체 모임 - + ampli.clickNavbarGroup({ menu: '내 모임' })}> 내 모임 @@ -40,10 +41,20 @@ const MinePage: NextPage = () => { - 내가 만든 모임 + ampli.clickMakebymeGroup()} + > + 내가 만든 모임 + - 내가 신청한 모임 + ampli.clickRegisteredGroup()} + > + 내가 신청한 모임 + diff --git a/pages/mine/management/index.tsx b/pages/mine/management/index.tsx index 9490798c..3a4fda9c 100644 --- a/pages/mine/management/index.tsx +++ b/pages/mine/management/index.tsx @@ -25,6 +25,7 @@ import { } from '@api/meeting/hooks'; import Filter from '@components/page/meetingManagement/Filter'; import DownloadIcon from '@assets/svg/download.svg'; +import { ampli } from '@/ampli'; const ManagementPage = () => { const router = useRouter(); @@ -52,7 +53,18 @@ const ManagementPage = () => { const handleChangeSelectOption = (setValue: (value: string | number) => void, optionList: Option[]) => (changeOption: Option) => { - setValue(optionList.findIndex(option => option.value === changeOption.value)); + const changeOptionValue = String(changeOption.value); + + switch (optionList) { + case numberOptionList: + ampli.filterListOptionManagement({ manage_listing_no: Number(changeOptionValue) }); + break; + case sortOptionList: + ampli.filterManagementListOrder({ manage_sort: changeOptionValue }); + break; + } + + setValue(optionList.findIndex(option => option.value === changeOptionValue)); }; const handleCSVDownload = () => { @@ -63,12 +75,12 @@ const ManagementPage = () => { - + ampli.clickNavbarGroup({ menu: '전체 모임' })}> 전체 모임 - + ampli.clickNavbarGroup({ menu: '내 모임' })}> 내 모임 diff --git a/src/ampli/index.ts b/src/ampli/index.ts index 75946b21..265425d1 100644 --- a/src/ampli/index.ts +++ b/src/ampli/index.ts @@ -303,6 +303,99 @@ export interface ClickFilterStatusProperties { group_status?: string; } +export interface ClickGroupCardProperties { + /** + * 모임의 소속 구성원 여부를 의미합니다. + */ + crew_status?: boolean; + /** + * 모임 카테고리를 의미합니다. + */ + group_category?: string; + /** + * 모임의 모집 대상이 활동기수인지 아닌지를 의미합니다. + */ + group_generation?: boolean; + /** + * 모임의 id값을 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + group_id?: number; + /** + * 모임의 개설자 id값을 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + group_owner_id?: number; + /** + * 모임의 모집 대상 파트를 의미합니다. + */ + group_part?: string; + /** + * 모임의 모집 상태를 의미합니다. + */ + group_status?: string; + /** + * 모임의 이름을 의미합니다. + */ + group_title?: string; +} + +export interface ClickMakebymeGroupProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + +export interface ClickMakeGroupProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + +export interface ClickManagementListProfileProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + +export interface ClickManagementListPromiseProperties { + /** + * 모임 신청 당시 다짐의 작성 여부를 의미합니다. + */ + submit_promise?: boolean; +} + +export interface ClickMemberManagementProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + +export interface ClickMemberStatusProperties { + /** + * 모임의 소속 구성원 여부를 의미합니다. + */ + crew_status?: boolean; +} + export interface ClickNavbarGroupProperties { /** * 모임 서비스 내의 탭 영역 메뉴명을 의미합니다. @@ -310,6 +403,15 @@ export interface ClickNavbarGroupProperties { menu: string; } +export interface ClickNoticeOffProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + export interface ClickNoticeOnProperties { /** * | Rule | Value | @@ -319,6 +421,98 @@ export interface ClickNoticeOnProperties { url?: string; } +export interface ClickOwnerProfileProperties { + /** + * 모임의 개설자 id값을 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + group_owner_id?: number; +} + +export interface ClickPaginationArrowProperties { + /** + * 모임 리스트 내 페이지를 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + page?: number; +} + +export interface ClickPaginationNumberProperties { + /** + * 모임 리스트 내 페이지를 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + page?: number; +} + +export interface ClickRegisteredGroupProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + +export interface ClickRegisteredGroupCardProperties { + /** + * 모임 카테고리를 의미합니다. + */ + group_category?: string; + /** + * 모임의 모집 대상이 활동기수인지 아닌지를 의미합니다. + */ + group_generation?: boolean; + /** + * 모임의 id값을 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + group_id?: number; + /** + * 모임의 개설자 id값을 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + group_owner_id?: number; + /** + * 모임의 모집 대상 파트를 의미합니다. + */ + group_part?: string; + /** + * 모임의 모집 상태를 의미합니다. + */ + group_status?: string; + /** + * 모임의 이름을 의미합니다. + */ + group_title?: string; +} + +export interface ClickRegisterGroupProperties { + /** + * 플레이그라운드 DB 기반 유저의 고유한 ID를 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + user_id?: number; +} + export interface CompletedCommentPostingProperties { /** * 모임의 소속 구성원 여부를 의미합니다. @@ -372,6 +566,48 @@ export interface CompletedFeedPostingCanceledProperties { user_id?: number; } +export interface CompletedMakeGroupProperties { + /** + * | Rule | Value | + * |---|---| + * | Regex | | + */ + url?: string; +} + +export interface CompletedRegisterGroupProperties { + /** + * 모임 신청 당시 다짐의 작성 여부를 의미합니다. + */ + submit_promise?: boolean; + /** + * 플레이그라운드 DB 기반 유저의 고유한 ID를 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | integer | + */ + user_id?: number; +} + +export interface FilterListOptionManagementProperties { + /** + * 모임 관리자의 모임 신청자 리스트 조회 옵션을 의미합니다. + * + * | Rule | Value | + * |---|---| + * | Type | number | + */ + manage_listing_no?: number; +} + +export interface FilterManagementListOrderProperties { + /** + * 모임 관리자의 모임 신청자 리스트 정렬 옵션을 의미합니다. + */ + manage_sort?: string; +} + export class Identify implements BaseEvent { event_type = amplitude.Types.SpecialEventType.IDENTIFY; @@ -436,147 +672,331 @@ export class ClickFeeddetailLike implements BaseEvent { event_type = 'Click-feeddetailLike'; constructor( - public event_properties?: ClickFeeddetailLikeProperties, + public event_properties?: ClickFeeddetailLikeProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFeeddetatilProfile implements BaseEvent { + event_type = 'Click-feeddetatilProfile'; + + constructor( + public event_properties?: ClickFeeddetatilProfileProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFeedlistLike implements BaseEvent { + event_type = 'Click-feedlistLike'; + + constructor( + public event_properties?: ClickFeedlistLikeProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFeedPosting implements BaseEvent { + event_type = 'Click-feedPosting'; + + constructor( + public event_properties?: ClickFeedPostingProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFeedProfile implements BaseEvent { + event_type = 'Click-feedProfile'; + + constructor( + public event_properties?: ClickFeedProfileProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFilterCategory implements BaseEvent { + event_type = 'Click-filterCategory'; + + constructor( + public event_properties?: ClickFilterCategoryProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFilterGeneration implements BaseEvent { + event_type = 'Click-filterGeneration'; + + constructor( + public event_properties?: ClickFilterGenerationProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFilterOn implements BaseEvent { + event_type = 'Click-filterOn'; + + constructor( + public event_properties?: ClickFilterOnProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFilterPart implements BaseEvent { + event_type = 'Click-filterPart'; + + constructor( + public event_properties?: ClickFilterPartProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickFilterStatus implements BaseEvent { + event_type = 'Click-filterStatus'; + + constructor( + public event_properties?: ClickFilterStatusProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickGroupCard implements BaseEvent { + event_type = 'Click-groupCard'; + + constructor( + public event_properties?: ClickGroupCardProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickMakebymeGroup implements BaseEvent { + event_type = 'Click-makebymeGroup'; + + constructor( + public event_properties?: ClickMakebymeGroupProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickMakeGroup implements BaseEvent { + event_type = 'Click-makeGroup'; + + constructor( + public event_properties?: ClickMakeGroupProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickManageGroup implements BaseEvent { + event_type = 'Click-manageGroup'; +} + +export class ClickManagementListProfile implements BaseEvent { + event_type = 'Click-managementListProfile'; + + constructor( + public event_properties?: ClickManagementListProfileProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickManagementListPromise implements BaseEvent { + event_type = 'Click-managementListPromise'; + + constructor( + public event_properties?: ClickManagementListPromiseProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickMemberManagement implements BaseEvent { + event_type = 'Click-memberManagement'; + + constructor( + public event_properties?: ClickMemberManagementProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickMemberStatus implements BaseEvent { + event_type = 'Click-memberStatus'; + + constructor( + public event_properties?: ClickMemberStatusProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickNavbarGroup implements BaseEvent { + event_type = 'Click-navbarGroup'; + + constructor( + public event_properties: ClickNavbarGroupProperties, + ) { + this.event_properties = event_properties; + } +} + +export class ClickNoticeOff implements BaseEvent { + event_type = 'Click-noticeOff'; + + constructor( + public event_properties?: ClickNoticeOffProperties, ) { this.event_properties = event_properties; } } -export class ClickFeeddetatilProfile implements BaseEvent { - event_type = 'Click-feeddetatilProfile'; +export class ClickNoticeOn implements BaseEvent { + event_type = 'Click-noticeOn'; constructor( - public event_properties?: ClickFeeddetatilProfileProperties, + public event_properties?: ClickNoticeOnProperties, ) { this.event_properties = event_properties; } } -export class ClickFeedlistLike implements BaseEvent { - event_type = 'Click-feedlistLike'; +export class ClickOwnerProfile implements BaseEvent { + event_type = 'Click-ownerProfile'; constructor( - public event_properties?: ClickFeedlistLikeProperties, + public event_properties?: ClickOwnerProfileProperties, ) { this.event_properties = event_properties; } } -export class ClickFeedPosting implements BaseEvent { - event_type = 'Click-feedPosting'; +export class ClickPaginationArrow implements BaseEvent { + event_type = 'Click-paginationArrow'; constructor( - public event_properties?: ClickFeedPostingProperties, + public event_properties?: ClickPaginationArrowProperties, ) { this.event_properties = event_properties; } } -export class ClickFeedProfile implements BaseEvent { - event_type = 'Click-feedProfile'; +export class ClickPaginationNumber implements BaseEvent { + event_type = 'Click-paginationNumber'; constructor( - public event_properties?: ClickFeedProfileProperties, + public event_properties?: ClickPaginationNumberProperties, ) { this.event_properties = event_properties; } } -export class ClickFilterCategory implements BaseEvent { - event_type = 'Click-filterCategory'; +export class ClickRegisteredGroup implements BaseEvent { + event_type = 'Click-registeredGroup'; constructor( - public event_properties?: ClickFilterCategoryProperties, + public event_properties?: ClickRegisteredGroupProperties, ) { this.event_properties = event_properties; } } -export class ClickFilterGeneration implements BaseEvent { - event_type = 'Click-filterGeneration'; +export class ClickRegisteredGroupCard implements BaseEvent { + event_type = 'Click-registeredGroupCard'; constructor( - public event_properties?: ClickFilterGenerationProperties, + public event_properties?: ClickRegisteredGroupCardProperties, ) { this.event_properties = event_properties; } } -export class ClickFilterOn implements BaseEvent { - event_type = 'Click-filterOn'; +export class ClickRegisterGroup implements BaseEvent { + event_type = 'Click-registerGroup'; constructor( - public event_properties?: ClickFilterOnProperties, + public event_properties?: ClickRegisterGroupProperties, ) { this.event_properties = event_properties; } } -export class ClickFilterPart implements BaseEvent { - event_type = 'Click-filterPart'; +export class CompletedCommentPosting implements BaseEvent { + event_type = 'Completed-commentPosting'; constructor( - public event_properties?: ClickFilterPartProperties, + public event_properties?: CompletedCommentPostingProperties, ) { this.event_properties = event_properties; } } -export class ClickFilterStatus implements BaseEvent { - event_type = 'Click-filterStatus'; +export class CompletedFeedPosting implements BaseEvent { + event_type = 'Completed-feedPosting'; constructor( - public event_properties?: ClickFilterStatusProperties, + public event_properties?: CompletedFeedPostingProperties, ) { this.event_properties = event_properties; } } -export class ClickNavbarGroup implements BaseEvent { - event_type = 'Click-navbarGroup'; +export class CompletedFeedPostingCanceled implements BaseEvent { + event_type = 'Completed-feedPostingCanceled'; constructor( - public event_properties: ClickNavbarGroupProperties, + public event_properties?: CompletedFeedPostingCanceledProperties, ) { this.event_properties = event_properties; } } -export class ClickNoticeOn implements BaseEvent { - event_type = 'Click-noticeOn'; +export class CompletedMakeGroup implements BaseEvent { + event_type = 'Completed-makeGroup'; constructor( - public event_properties?: ClickNoticeOnProperties, + public event_properties?: CompletedMakeGroupProperties, ) { this.event_properties = event_properties; } } -export class CompletedCommentPosting implements BaseEvent { - event_type = 'Completed-commentPosting'; +export class CompletedRegisterGroup implements BaseEvent { + event_type = 'Completed-registerGroup'; constructor( - public event_properties?: CompletedCommentPostingProperties, + public event_properties?: CompletedRegisterGroupProperties, ) { this.event_properties = event_properties; } } -export class CompletedFeedPosting implements BaseEvent { - event_type = 'Completed-feedPosting'; +export class FilterListOptionManagement implements BaseEvent { + event_type = 'Filter-listOptionManagement'; constructor( - public event_properties?: CompletedFeedPostingProperties, + public event_properties?: FilterListOptionManagementProperties, ) { this.event_properties = event_properties; } } -export class CompletedFeedPostingCanceled implements BaseEvent { - event_type = 'Completed-feedPostingCanceled'; +export class FilterManagementListOrder implements BaseEvent { + event_type = 'Filter-managementListOrder'; constructor( - public event_properties?: CompletedFeedPostingCanceledProperties, + public event_properties?: FilterManagementListOrderProperties, ) { this.event_properties = event_properties; } @@ -954,6 +1374,140 @@ export class Ampli { return this.track(new ClickFilterStatus(properties), options); } + /** + * Click-groupCard + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-groupCard) + * + * 전체 모임 리스트 내 모임 카드 클릭 유저의 모임 멤버 유무에 따른 방문 데이터 수집 + * + * @param properties The event's properties (e.g. crew_status) + * @param options Amplitude event options. + */ + clickGroupCard( + properties?: ClickGroupCardProperties, + options?: EventOptions, + ) { + return this.track(new ClickGroupCard(properties), options); + } + + /** + * Click-makebymeGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-makebymeGroup) + * + * \[내가 만든 모임\] 클릭 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + clickMakebymeGroup( + properties?: ClickMakebymeGroupProperties, + options?: EventOptions, + ) { + return this.track(new ClickMakebymeGroup(properties), options); + } + + /** + * Click-makeGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-makeGroup) + * + * \[+모임 개설하기\] 버튼 클릭 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + clickMakeGroup( + properties?: ClickMakeGroupProperties, + options?: EventOptions, + ) { + return this.track(new ClickMakeGroup(properties), options); + } + + /** + * Click-manageGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-manageGroup) + * + * \[신청자 관리\] 클릭 + * + * @param options Amplitude event options. + */ + clickManageGroup( + options?: EventOptions, + ) { + return this.track(new ClickManageGroup(), options); + } + + /** + * Click-managementListProfile + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-managementListProfile) + * + * 리스트 내 프로필 클릭 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + clickManagementListProfile( + properties?: ClickManagementListProfileProperties, + options?: EventOptions, + ) { + return this.track(new ClickManagementListProfile(properties), options); + } + + /** + * Click-managementListPromise + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-managementListPromise) + * + * 리스트 내 신청내역 클릭 및 조회 + * + * @param properties The event's properties (e.g. submit_promise) + * @param options Amplitude event options. + */ + clickManagementListPromise( + properties?: ClickManagementListPromiseProperties, + options?: EventOptions, + ) { + return this.track(new ClickManagementListPromise(properties), options); + } + + /** + * Click-memberManagement + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-memberManagement) + * + * 모임 상세 내 /management로 접근하는 버튼 클릭 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + clickMemberManagement( + properties?: ClickMemberManagementProperties, + options?: EventOptions, + ) { + return this.track(new ClickMemberManagement(properties), options); + } + + /** + * Click-memberStatus + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-memberStatus) + * + * 모집 현황 클릭 + * + * @param properties The event's properties (e.g. crew_status) + * @param options Amplitude event options. + */ + clickMemberStatus( + properties?: ClickMemberStatusProperties, + options?: EventOptions, + ) { + return this.track(new ClickMemberStatus(properties), options); + } + /** * Click-navbarGroup * @@ -971,6 +1525,23 @@ export class Ampli { return this.track(new ClickNavbarGroup(properties), options); } + /** + * Click-noticeOff + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-noticeOff) + * + * 공지사항 토글 비활성화 버튼 클릭 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + clickNoticeOff( + properties?: ClickNoticeOffProperties, + options?: EventOptions, + ) { + return this.track(new ClickNoticeOff(properties), options); + } + /** * Click-noticeOn * @@ -988,6 +1559,108 @@ export class Ampli { return this.track(new ClickNoticeOn(properties), options); } + /** + * Click-ownerProfile + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-ownerProfile) + * + * 모임 상세 내 개설자 프로필 클릭 + * + * @param properties The event's properties (e.g. group_owner_id) + * @param options Amplitude event options. + */ + clickOwnerProfile( + properties?: ClickOwnerProfileProperties, + options?: EventOptions, + ) { + return this.track(new ClickOwnerProfile(properties), options); + } + + /** + * Click-paginationArrow + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-paginationArrow) + * + * 하단 페이지네이션 영역 중 애로우 클릭 + * + * @param properties The event's properties (e.g. page) + * @param options Amplitude event options. + */ + clickPaginationArrow( + properties?: ClickPaginationArrowProperties, + options?: EventOptions, + ) { + return this.track(new ClickPaginationArrow(properties), options); + } + + /** + * Click-paginationNumber + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-paginationNumber) + * + * 하단 페이지네이션 영역 중 페이지 클릭 + * + * @param properties The event's properties (e.g. page) + * @param options Amplitude event options. + */ + clickPaginationNumber( + properties?: ClickPaginationNumberProperties, + options?: EventOptions, + ) { + return this.track(new ClickPaginationNumber(properties), options); + } + + /** + * Click-registeredGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-registeredGroup) + * + * \[내가 신청한 모임\] 클릭 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + clickRegisteredGroup( + properties?: ClickRegisteredGroupProperties, + options?: EventOptions, + ) { + return this.track(new ClickRegisteredGroup(properties), options); + } + + /** + * Click-registeredGroupCard + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-registeredGroupCard) + * + * 내가 신청한 모임의 모임 카드 클릭 + * + * @param properties The event's properties (e.g. group_category) + * @param options Amplitude event options. + */ + clickRegisteredGroupCard( + properties?: ClickRegisteredGroupCardProperties, + options?: EventOptions, + ) { + return this.track(new ClickRegisteredGroupCard(properties), options); + } + + /** + * Click-registerGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Click-registerGroup) + * + * \[신청하기\] 버튼 클릭 + * + * @param properties The event's properties (e.g. user_id) + * @param options Amplitude event options. + */ + clickRegisterGroup( + properties?: ClickRegisterGroupProperties, + options?: EventOptions, + ) { + return this.track(new ClickRegisterGroup(properties), options); + } + /** * Completed-commentPosting * @@ -1038,6 +1711,74 @@ export class Ampli { ) { return this.track(new CompletedFeedPostingCanceled(properties), options); } + + /** + * Completed-makeGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Completed-makeGroup) + * + * 모임 개설이 완료된 케이스 + * + * @param properties The event's properties (e.g. url) + * @param options Amplitude event options. + */ + completedMakeGroup( + properties?: CompletedMakeGroupProperties, + options?: EventOptions, + ) { + return this.track(new CompletedMakeGroup(properties), options); + } + + /** + * Completed-registerGroup + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Completed-registerGroup) + * + * 모임 신청하기 모달 내 \[신청하기\] 버튼 클릭 + * + * @param properties The event's properties (e.g. submit_promise) + * @param options Amplitude event options. + */ + completedRegisterGroup( + properties?: CompletedRegisterGroupProperties, + options?: EventOptions, + ) { + return this.track(new CompletedRegisterGroup(properties), options); + } + + /** + * Filter-listOptionManagement + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Filter-listOptionManagement) + * + * 리스트 뷰에서 몇명까지 볼 것인지 선택한 옵션 + * + * @param properties The event's properties (e.g. manage_listing_no) + * @param options Amplitude event options. + */ + filterListOptionManagement( + properties?: FilterListOptionManagementProperties, + options?: EventOptions, + ) { + return this.track(new FilterListOptionManagement(properties), options); + } + + /** + * Filter-managementListOrder + * + * [View in Tracking Plan](https://data.amplitude.com/sopt-makers/sopt-makers-crew/events/main/latest/Filter-managementListOrder) + * + * 최신순 ↔ 오래된순 + * + * @param properties The event's properties (e.g. manage_sort) + * @param options Amplitude event options. + */ + filterManagementListOrder( + properties?: FilterManagementListOrderProperties, + options?: EventOptions, + ) { + return this.track(new FilterManagementListOrder(properties), options); + } } export const ampli = new Ampli(); diff --git a/src/components/disclosure/Disclosure.tsx b/src/components/disclosure/Disclosure.tsx index 6d58d566..d0359a60 100644 --- a/src/components/disclosure/Disclosure.tsx +++ b/src/components/disclosure/Disclosure.tsx @@ -3,6 +3,7 @@ import { Disclosure as HeadlessDisclosure } from '@headlessui/react'; import { styled } from 'stitches.config'; import ArrowIcon from 'public/assets/svg/arrow_down.svg'; import { parseTextToLink } from '@components/util/parseTextToLink'; +import { ampli } from '@/ampli'; interface DisclosureProps { title: string; @@ -21,7 +22,7 @@ export default function Disclosure({ title, subTitle, contents, createdDate }: D {title} {subTitle} - + (!open ? ampli.clickNoticeOn() : ampli.clickNoticeOff())}> diff --git a/src/components/feed/FeedPostViewer/FeedPostViewer.tsx b/src/components/feed/FeedPostViewer/FeedPostViewer.tsx index 27857157..032e9d6a 100644 --- a/src/components/feed/FeedPostViewer/FeedPostViewer.tsx +++ b/src/components/feed/FeedPostViewer/FeedPostViewer.tsx @@ -165,9 +165,7 @@ const Contents = styled('p', { color: '$gray30', fontStyle: 'B2', whiteSpace: 'pre-wrap', - a: { - wordBreak: 'break-all', - }, + wordBreak: 'break-word', '@tablet': { fontStyle: 'B3', }, diff --git a/src/components/page/meetingDetail/Carousel/NextArrow.tsx b/src/components/page/meetingDetail/Carousel/NextArrow.tsx index 69de2e3b..dbad9659 100644 --- a/src/components/page/meetingDetail/Carousel/NextArrow.tsx +++ b/src/components/page/meetingDetail/Carousel/NextArrow.tsx @@ -1,15 +1,22 @@ import React from 'react'; import { styled } from 'stitches.config'; import ArrowBigLeftIcon from '@assets/svg/arrow_big_left.svg'; +import { ampli } from '@/ampli'; interface NextArrowProps { className: string; onClick?: React.MouseEventHandler; + total: number; } -const NextArrow = ({ className, onClick }: NextArrowProps) => { +const NextArrow = ({ className, onClick, total }: NextArrowProps) => { + const handleClick = (e: React.MouseEvent) => { + ampli.clickCarouselArrow({ image_total: total }); + onClick?.(e); + }; + return ( - + handleClick(e)}> ); diff --git a/src/components/page/meetingDetail/Carousel/index.tsx b/src/components/page/meetingDetail/Carousel/index.tsx index 7763dfe4..ec6616b3 100644 --- a/src/components/page/meetingDetail/Carousel/index.tsx +++ b/src/components/page/meetingDetail/Carousel/index.tsx @@ -9,9 +9,11 @@ interface CarouselProps { } const Carousel = ({ imageList }: CarouselProps) => { + const imageListLength = imageList.length; + const settings = { - prevArrow: , - nextArrow: , + prevArrow: , + nextArrow: , responsive: [ { breakpoint: 768, diff --git a/src/components/page/meetingDetail/MeetingController/Modal/Content/ApplicationModalContent.tsx b/src/components/page/meetingDetail/MeetingController/Modal/Content/ApplicationModalContent.tsx index ed913f21..4f78e535 100644 --- a/src/components/page/meetingDetail/MeetingController/Modal/Content/ApplicationModalContent.tsx +++ b/src/components/page/meetingDetail/MeetingController/Modal/Content/ApplicationModalContent.tsx @@ -1,3 +1,5 @@ +import { ampli } from '@/ampli'; +import { useQueryMyProfile } from '@api/user/hooks'; import Textarea from '@components/form/Textarea'; import { useState } from 'react'; import { styled } from 'stitches.config'; @@ -9,6 +11,12 @@ interface ApplicationModalContentProps { const ApplicationModalContent = ({ handleApplicationButton, disabled }: ApplicationModalContentProps) => { const [textareaValue, setTextareaValue] = useState(''); + const { data: me } = useQueryMyProfile(); + + const handleClick = () => { + ampli.completedRegisterGroup({ user_id: Number(me?.orgId), submit_promise: textareaValue ? true : false }); + handleApplicationButton(textareaValue); + }; return ( @@ -19,7 +27,7 @@ const ApplicationModalContent = ({ handleApplicationButton, disabled }: Applicat maxLength={150} error={textareaValue.length >= 150 ? '150자 까지 입력할 수 있습니다.' : ''} /> - diff --git a/src/components/page/meetingDetail/MeetingController/Modal/Content/RecruitmentStatusModalContent/index.tsx b/src/components/page/meetingDetail/MeetingController/Modal/Content/RecruitmentStatusModalContent/index.tsx index c759d543..41f5ffe0 100644 --- a/src/components/page/meetingDetail/MeetingController/Modal/Content/RecruitmentStatusModalContent/index.tsx +++ b/src/components/page/meetingDetail/MeetingController/Modal/Content/RecruitmentStatusModalContent/index.tsx @@ -3,6 +3,7 @@ import { styled } from 'stitches.config'; import { ApplyResponse } from '@api/user'; import RecruitmentStatusList from './RecruitmentStatusList'; import ArrowSmallRightIcon from '@assets/svg/arrow_small_right.svg'; +import { ampli } from '@/ampli'; interface RecruitmentStatusModalContentProps { meetingId: number; @@ -34,7 +35,7 @@ const RecruitmentStatusModalContent = ({ {total > 0 && 총 {total}명 신청} {(isHost || isApplied) && ( - + ampli.clickMemberManagement()}> {isHost ? '신청자 관리' : isApplied && '참여자 리스트'} diff --git a/src/components/page/meetingDetail/MeetingController/index.tsx b/src/components/page/meetingDetail/MeetingController/index.tsx index a00e1abe..6d7b8ac9 100644 --- a/src/components/page/meetingDetail/MeetingController/index.tsx +++ b/src/components/page/meetingDetail/MeetingController/index.tsx @@ -22,6 +22,7 @@ import MentorTooltip from './MentorTooltip'; import { getResizedImage } from '@utils/image'; import alertErrorMessage from '@utils/alertErrorMessage'; import { useQueryMyProfile } from '@api/user/hooks'; +import { ampli } from '@/ampli'; interface DetailHeaderProps { detailData: MeetingResponse; @@ -50,6 +51,7 @@ const MeetingController = ({ detailData, mutateMeetingDeletion, mutateApplicatio title, user: { orgId: hostId, name: hostName, profileImage: hostProfileImage }, appliedInfo, + approved, approvedApplyCount, capacity, host: isHost, @@ -85,6 +87,7 @@ const MeetingController = ({ detailData, mutateMeetingDeletion, mutateApplicatio const [isSubmitting, setIsSubmitting] = useState(false); const handleRecruitmentStatusModal = () => { + ampli.clickMemberStatus({ crew_status: approved || isHost }); handleDefaultModalOpen(); setModalTitle(`모집 현황 (${approvedApplyCount}/${capacity}명)`); }; @@ -95,6 +98,7 @@ const MeetingController = ({ detailData, mutateMeetingDeletion, mutateApplicatio return; } if (!isApplied) { + ampli.clickRegisterGroup({ user_id: Number(me.orgId) }); handleDefaultModalOpen(); setModalTitle('모임 신청하기'); return; @@ -166,7 +170,10 @@ const MeetingController = ({ detailData, mutateMeetingDeletion, mutateApplicatio {title} - + ampli.clickOwnerProfile({ group_owner_id: Number(hostId) })} + > {hostProfileImage ? : } {hostName} diff --git a/src/components/page/meetingList/Card/ManagementButton.tsx b/src/components/page/meetingList/Card/ManagementButton.tsx index c84cb1bb..1b296caf 100644 --- a/src/components/page/meetingList/Card/ManagementButton.tsx +++ b/src/components/page/meetingList/Card/ManagementButton.tsx @@ -3,6 +3,7 @@ import { styled } from 'stitches.config'; import ArrowSmallRight from '@assets/svg/arrow_small_right.svg'; import Link from 'next/link'; import ArrowMobileRight from '@assets/svg/arrow_mobile_right.svg'; +import { ampli } from '@/ampli'; interface ManagementButtonProps { id: number; @@ -11,7 +12,7 @@ interface ManagementButtonProps { function ManagementButton({ id }: ManagementButtonProps) { return ( - + ampli.clickManageGroup()}>

신청자 관리

@@ -41,4 +42,5 @@ const SButton = styled(Flex, { const SAnchor = styled('a', { display: 'block', mt: '$16', + width: 'fit-content', }); diff --git a/src/components/page/meetingList/Card/index.tsx b/src/components/page/meetingList/Card/index.tsx index 9ca97ed1..365b6068 100644 --- a/src/components/page/meetingList/Card/index.tsx +++ b/src/components/page/meetingList/Card/index.tsx @@ -5,6 +5,8 @@ import { MeetingResponse } from '@api/meeting'; import DesktopSizeCard from './DesktopSizeCard'; import MobileSizeCard from './MobileSize'; import { styled } from 'stitches.config'; +import { PART_OPTIONS, PART_VALUES, RECRUITMENT_STATUS } from '@constants/option'; +import { ampli } from '@/ampli'; interface CardProps { bottom?: ReactNode; @@ -16,7 +18,20 @@ function Card({ bottom, meetingData, mobileType }: CardProps) { const isAllParts = meetingData.joinableParts?.length === 6 || meetingData.joinableParts === null; return ( - + { + ampli.clickGroupCard({ + group_id: meetingData.id, + group_status: RECRUITMENT_STATUS[meetingData.status], + group_category: meetingData.category, + group_title: meetingData.title, + group_owner_id: Number(meetingData.user.orgId), + group_part: meetingData.joinableParts.map(part => PART_OPTIONS[PART_VALUES.indexOf(part)]).join(', '), + group_generation: meetingData.canJoinOnlyActiveGeneration, + }); + }} + > diff --git a/src/components/page/meetingList/Filter/Modal/Chip/ChipItem.tsx b/src/components/page/meetingList/Filter/Modal/Chip/ChipItem.tsx index e2a941f5..aaf78c06 100644 --- a/src/components/page/meetingList/Filter/Modal/Chip/ChipItem.tsx +++ b/src/components/page/meetingList/Filter/Modal/Chip/ChipItem.tsx @@ -1,14 +1,29 @@ +import { ampli } from '@/ampli'; +import { CATEGORY_FILTER, PART_FILTER, STATUS_FILTER } from '@constants/option'; import { styled } from 'stitches.config'; interface ChipItemProps { + label: string; value: string; isSelected: boolean; addValue: (val: string) => void; deleteValue: (val: string) => void; } -function ChipItem({ value, isSelected, addValue, deleteValue }: ChipItemProps) { +function ChipItem({ label, value, isSelected, addValue, deleteValue }: ChipItemProps) { const toggle = () => { + switch (label) { + case CATEGORY_FILTER.label: + ampli.clickFilterCategory({ group_category: value }); + break; + case STATUS_FILTER.label: + ampli.clickFilterStatus({ group_status: value }); + break; + case PART_FILTER.label: + ampli.clickFilterPart({ group_part: value }); + break; + } + if (isSelected) return deleteValue(value); return addValue(value); }; diff --git a/src/components/page/meetingList/Filter/Modal/Chip/index.tsx b/src/components/page/meetingList/Filter/Modal/Chip/index.tsx index 5d5b5c73..9ebc5f54 100644 --- a/src/components/page/meetingList/Filter/Modal/Chip/index.tsx +++ b/src/components/page/meetingList/Filter/Modal/Chip/index.tsx @@ -7,6 +7,7 @@ interface ChipProps { css?: CSSType; filter: FilterType; } + function Chip({ css, filter }: ChipProps) { const { label, subject, options } = filter; const { value: selectedValues, addValue, deleteValue } = useMultiQueryString(subject, true); @@ -17,6 +18,7 @@ function Chip({ css, filter }: ChipProps) { { + ampli.clickFilterOn(); + setIsModalOpened(true); + }; + return ( <> setIsModalOpened(true)} + onClick={handleButtonClick} isFilterActive={isFilterActive} className="filter-button" > diff --git a/src/components/page/meetingList/Filter/Modal/Toggle/index.tsx b/src/components/page/meetingList/Filter/Modal/Toggle/index.tsx index ce5ead4f..7ea619e4 100644 --- a/src/components/page/meetingList/Filter/Modal/Toggle/index.tsx +++ b/src/components/page/meetingList/Filter/Modal/Toggle/index.tsx @@ -4,6 +4,7 @@ import { useIsOnlyActiveGenerationParams } from '@hooks/queryString/custom'; import { parseBool } from '@utils/parseBool'; import { CSSType, styled } from 'stitches.config'; import { Switch as HeadlessSwitch } from '@headlessui/react'; +import { ampli } from '@/ampli'; interface ToggleProps { css?: CSSType; label: string; @@ -11,6 +12,12 @@ interface ToggleProps { function Toggle({ css, label }: ToggleProps) { const { value: isOnlyActiveGeneration, setValue } = useIsOnlyActiveGenerationParams(); + const handleChange = () => { + const value = !parseBool(isOnlyActiveGeneration); + ampli.clickFilterGeneration({ group_generation: value }); + setValue(String(value)); + }; + return ( @@ -19,10 +26,7 @@ function Toggle({ css, label }: ToggleProps) { 활동 기수만 - setValue(String(!parseBool(isOnlyActiveGeneration)))} - /> + diff --git a/src/components/page/meetingList/Pagination.tsx b/src/components/page/meetingList/Pagination.tsx index ba229562..281d238b 100644 --- a/src/components/page/meetingList/Pagination.tsx +++ b/src/components/page/meetingList/Pagination.tsx @@ -3,6 +3,7 @@ import { bindThePages } from '@utils/bindThePages'; import { useEffect, useState } from 'react'; import { styled } from 'stitches.config'; import { ArrowButton } from '@components/button/Arrow'; +import { ampli } from '@/ampli'; interface PaginationProps { totalPagesLength?: number; currentPageIndex?: number; @@ -10,21 +11,34 @@ interface PaginationProps { } function Pagination({ totalPagesLength = 1, currentPageIndex = 1, changeCurrentPage }: PaginationProps) { + const path = window.location.pathname; + const isMainPage = path === '/group' || path === '/group/'; const BUNDLE_SIZE = 5; const [pagesIndex, setPagesIndex] = useState(0); const pagesBundle = bindThePages(totalPagesLength, BUNDLE_SIZE); + const prevBundle = () => { const prevBundleLastPage = Math.floor((currentPageIndex - 1) / BUNDLE_SIZE) * BUNDLE_SIZE; + if (isMainPage) { + ampli.clickPaginationArrow({ page: prevBundleLastPage }); + } changeCurrentPage(prevBundleLastPage); }; + const nextBundle = () => { const nextBundleFirstPage = Math.ceil(currentPageIndex / BUNDLE_SIZE) * BUNDLE_SIZE + 1; + if (isMainPage) { + ampli.clickPaginationArrow({ page: nextBundleFirstPage }); + } changeCurrentPage(nextBundleFirstPage); }; const handlePageLinkClick = (item: number) => { + if (isMainPage) { + ampli.clickPaginationNumber({ page: item }); + } changeCurrentPage(item); window.scrollTo({ top: 0, behavior: 'smooth' }); }; diff --git a/src/components/page/meetingManagement/ManagementListItem.tsx b/src/components/page/meetingManagement/ManagementListItem.tsx index f23e2499..80dfa1a9 100644 --- a/src/components/page/meetingManagement/ManagementListItem.tsx +++ b/src/components/page/meetingManagement/ManagementListItem.tsx @@ -12,6 +12,7 @@ import ProfileDefaultIcon from '@assets/svg/profile_default.svg?rect'; import dayjs from 'dayjs'; import { AxiosError } from 'axios'; import alertErrorMessage from '@utils/alertErrorMessage'; +import { ampli } from '@/ampli'; interface ManagementListItemProps { meetingId: number; @@ -28,7 +29,8 @@ const ManagementListItem = ({ meetingId, application, isHost }: ManagementListIt const queryClient = useQueryClient(); const [isMutateLoading, setIsMutateLoading] = useState(false); - const moveToMemberDetailPage = (id: string) => { + const handleProfileClick = (id: string) => { + ampli.clickManagementListProfile(); window.location.href = `${playgroundLink.memberDetail(id)}`; }; @@ -55,6 +57,11 @@ const ManagementListItem = ({ meetingId, application, isHost }: ManagementListIt const addHyphenToPhoneNumber = (phoneNumber: string) => phoneNumber.replace(/[^0-9]/g, '').replace(/^(\d{2,3})(\d{3,4})(\d{4})$/, `$1-$2-$3`); + const handleDetailButtonClick = () => { + ampli.clickManagementListPromise({ submit_promise: content ? true : false }); + handleModalOpen(); + }; + return ( <> {isHost && ( @@ -65,12 +72,12 @@ const ManagementListItem = ({ meetingId, application, isHost }: ManagementListIt {user.profileImage ? : } - moveToMemberDetailPage(user.orgId)}>{user.name} + handleProfileClick(user.orgId)}>{user.name} {APPROVAL_STATUS[status]} {user.activities[0].generation}기 {user.phone ? addHyphenToPhoneNumber(user.phone) : '-'} - {APPLICATION_TYPE[type]} 내역 + {APPLICATION_TYPE[type]} 내역 {date} {time} @@ -119,7 +126,7 @@ const ManagementListItem = ({ meetingId, application, isHost }: ManagementListIt
- moveToMemberDetailPage(user.orgId)}>{user.name} + handleProfileClick(user.orgId)}>{user.name} {APPROVAL_STATUS[status]}
@@ -128,7 +135,7 @@ const ManagementListItem = ({ meetingId, application, isHost }: ManagementListIt
- + {APPLICATION_TYPE[type]} 내역 @@ -186,7 +193,7 @@ const ManagementListItem = ({ meetingId, application, isHost }: ManagementListIt {user.profileImage ? : } - moveToMemberDetailPage(user.orgId)}>{user.name} + handleProfileClick(user.orgId)}>{user.name} {date}