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
9 changes: 9 additions & 0 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AdminClubProvider } from '@/context/AdminClubContext';
import LoginTab from '@/pages/AdminPage/auth/LoginTab/LoginTab';
import PrivateRoute from '@/pages/AdminPage/auth/PrivateRoute/PrivateRoute';
import ClubDetailPage from '@/pages/ClubDetailPage/ClubDetailPage';
import ClubDetailPage2 from '@/pages/clubDetailPage2/ClubDetailPage2';
import MainPage from '@/pages/MainPage/MainPage';
import GlobalStyles from '@/styles/Global.styles';
import { theme } from '@/styles/theme';
Expand Down Expand Up @@ -43,6 +44,14 @@ const App = () => {
</Suspense>
}
/>
<Route
path='/club2/:clubId'
element={
<Suspense fallback={null}>
<ClubDetailPage2 />
</Suspense>
}
/>
<Route path='/introduce' element={<IntroducePage />} />
<Route path='/admin/login' element={<LoginTab />} />
<Route
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/assets/images/icons/sns/instagram_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions frontend/src/assets/images/icons/sns/youtube_icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions frontend/src/constants/eventName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export const USER_EVENT = {
TAB_CLICKED: 'Tab Clicked',
PHOTO_NAVIGATION_CLICKED: 'Photo Navigation',
CLUB_CARD_CLICKED: 'ClubCard Clicked',
CLUB_INTRO_TAB_CLICKED: 'Club Intro Tab Clicked',
CLUB_FEED_TAB_CLICKED: 'Club Feed Tab Clicked',

// 동아리 지원
CLUB_APPLY_BUTTON_CLICKED: 'Club Apply Button Clicked',
Expand Down
60 changes: 60 additions & 0 deletions frontend/src/pages/clubDetailPage2/ClubDetailPage2.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import styled from 'styled-components';
import { media } from '@/styles/mediaQuery';
import { colors } from '@/styles/theme/colors';

export const Container = styled.div`
width: 100%;
min-height: 100vh;
`;

export const ContentWrapper = styled.div`
max-width: 1180px;
width: 100%;
margin: 0 auto;
display: flex;
gap: 24px;
margin-top: 100px;

${media.laptop} {
padding: 0 20px;
}

${media.tablet} {
flex-direction: column;
padding: 0;
max-width: 100%;
margin-top: 0;
}
`;

export const RightSection = styled.div`
width: 100%;
`;

export const TabList = styled.div`
display: flex;
gap: 8px;
border-bottom: 1px solid ${colors.gray[300]};
padding: 0 20px;
`;

export const TabButton = styled.button<{ $active: boolean }>`
padding: 12px 20px;
font-size: 16px;
font-weight: ${({ $active }) => ($active ? 700 : 400)};
color: ${({ $active }) => ($active ? colors.base.black : colors.gray[600])};
background: none;
border: none;
border-bottom: 2px solid
${({ $active }) => ($active ? colors.base.black : 'transparent')};
cursor: pointer;
transition: all 0.2s;

&:hover {
color: ${colors.base.black};
}
`;

export const TabContent = styled.div`
padding: 20px;
`;
83 changes: 83 additions & 0 deletions frontend/src/pages/clubDetailPage2/ClubDetailPage2.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useState } from 'react';
import { useParams } from 'react-router-dom';
import Footer from '@/components/common/Footer/Footer';
import Header from '@/components/common/Header/Header';
import { PAGE_VIEW, USER_EVENT } from '@/constants/eventName';
import { useGetClubDetail } from '@/hooks/queries/club/useGetClubDetail';
import useDevice from '@/hooks/useDevice';
import useMixpanelTrack from '@/hooks/useMixpanelTrack';
import useTrackPageView from '@/hooks/useTrackPageView';
import ClubProfileCard from '@/pages/clubDetailPage2/components/ClubProfileCard/ClubProfileCard';
import * as Styled from './ClubDetailPage2.styles';
import { mockClubApi } from './mockData';

const ClubDetailPage2 = () => {
// TODO: mockClubApi 대신 실제 clubDetail 데이터 사용하도록 변경 필요
const club = mockClubApi;
const [activeTab, setActiveTab] = useState<'intro' | 'photos'>('intro');

const { clubId } = useParams<{ clubId: string }>();
const { isLaptop, isDesktop } = useDevice();
const trackEvent = useMixpanelTrack();

const { data: clubDetail, error } = useGetClubDetail(clubId || '');

useTrackPageView(PAGE_VIEW.CLUB_DETAIL_PAGE, clubDetail?.name, !clubDetail);

if (!clubDetail) {
return null;
}

if (error) {
return <div>에러가 발생했습니다.</div>;
}

return (
<>
{(isLaptop || isDesktop) && <Header />}
<Styled.Container>
<Styled.ContentWrapper>
<ClubProfileCard
name={club.name}
logo={club.logo}
cover={club.cover}
recruitmentStatus={club.recruitmentStatus}
socialLinks={club.socialLinks}
activityDescription={club.description.activityDescription}
/>

<Styled.RightSection>
<Styled.TabList>
<Styled.TabButton
$active={activeTab === 'intro'}
onClick={() => {
setActiveTab('intro');
trackEvent(USER_EVENT.CLUB_INTRO_TAB_CLICKED);
}}
>
소개 내용
</Styled.TabButton>
<Styled.TabButton
$active={activeTab === 'photos'}
onClick={() => {
setActiveTab('photos');
trackEvent(USER_EVENT.CLUB_FEED_TAB_CLICKED);
}}
>
활동사진
</Styled.TabButton>
</Styled.TabList>

<Styled.TabContent>
{activeTab === 'intro' && <p>소개 내용 컴포넌트 추가 예정</p>}
{activeTab === 'photos' && <p>활동 사진 컴포넌트 추가 예정</p>}
</Styled.TabContent>
</Styled.RightSection>
</Styled.ContentWrapper>
</Styled.Container>
<Footer />
</>
);
};

export default ClubDetailPage2;
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import styled from 'styled-components';
import { media } from '@/styles/mediaQuery';
import { colors } from '@/styles/theme/colors';

export const Container = styled.div`
position: relative;
width: 100%;
max-width: 375px;
background-color: #ffffff;
border-radius: 20px;
overflow: hidden;

${media.tablet} {
max-width: none;
}
`;

export const CoverImage = styled.img`
width: 100%;
height: 213px;
position: relative;
z-index: 1;
object-fit: cover;
`;

export const LogoWrapper = styled.div`
position: absolute;
top: 165px;
left: 16px;
width: 64px;
height: 64px;
border-radius: 16px;
background-color: #ffffff;
padding: 2px;
z-index: 3;
`;

export const Logo = styled.img`
width: 100%;
height: 100%;
border-radius: 14px;
object-fit: cover;
border: 0.5px solid var(--Gray-400, #dcdcdc);
`;

export const Content = styled.div`
padding: 42px 20px 20px;
margin-top: -20px;
position: relative;
z-index: 2;
background-color: #f5f5f5;
border-radius: 20px;

${media.tablet} {
background-color: #ffffff;
}

${media.laptop} {
padding: 40px 16px 20px;
}
`;

export const Header = styled.div`
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 4px;
`;

export const ClubName = styled.h2`
font-size: 32px;
font-weight: 700;
color: ${colors.base.black};

${media.laptop} {
font-size: 28px;
}
${media.mobile} {
font-size: 22px;
}
`;

export const RecruitmentBadge = styled.span`
display: inline-block;
padding: 4px 10px;
background-color: ${colors.accent[1][700]};
color: ${colors.accent[1][900]};
font-size: 12px;
font-weight: 600;
border-radius: 12px;

${media.laptop} {
font-size: 11px;
padding: 3px 8px;
}
`;

export const SocialLinksWrapper = styled.div`
display: flex;
flex-direction: column;
margin-bottom: 8px;
`;

export const SocialIcon = styled.img`
width: 14px;
height: 14px;
`;

export const SocialLinkItem = styled.a`
padding: 2px;
display: flex;
align-items: center;
gap: 2px;
font-size: 14px;
color: ${colors.gray[700]};
text-decoration: none;
transition: color 0.2s;

&:hover {
color: ${colors.base.black};
}

${media.mobile} {
font-size: 12px;
}
`;

export const SocialText = styled.span`
word-break: break-all;
`;

export const SocialUrl = styled.span`
color: #0066cc;
`;

export const IntroSection = styled.section`
padding: 16px;
border-radius: 14px;
background-color: #ffffff;

${media.tablet} {
background-color: #f5f5f5;
}
`;

export const IntroTitle = styled.h3`
font-size: 16px;
font-weight: 700;
color: ${colors.base.black};
margin-bottom: 6px;
`;

export const IntroDescription = styled.p`
font-size: 14px;
color: ${colors.gray[800]};

${media.mobile} {
font-size: 12px;
}
`;
Loading