Skip to content

Commit

Permalink
Feature/#224 팀 랭킹 r api 연결 (#263)
Browse files Browse the repository at this point in the history
* api: 팀 랭킹을 불러오는 api 선언

#224

* chore: dayjs 패키지 설치

#224

* feat: api 호출되는 타입에 맞게 타입 수정 및 관련된 코드 수정

#224

* feat: 팀 랭킹 조회 api 연결

#224

* fix: api type 충돌 해결

#224

* fix: import 구문 순서 변경

#224

* refact: 코드리뷰 반영

#224

* fix: 변수 오타 수정

#224

* refact: 참조하는 변수 수정

#224
  • Loading branch information
llddang authored Jun 29, 2024
1 parent a85ea0d commit 894e191
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 516 deletions.
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.3",
"@emotion/styled": "^11.11.0",
"dayjs": "^1.11.11",
"framer-motion": "^10.18.0",
"jotai": "^2.6.1",
"next": "14.0.4",
Expand All @@ -29,8 +30,8 @@
"@swc-jotai/react-refresh": "^0.1.0",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-datepicker": "^6.2.0",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-datepicker": "^6.2.0",
"@types/react-dom": "^18",
"eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4",
Expand Down
3 changes: 3 additions & 0 deletions src/app/api/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ const postJoinTeam = (token: string, teamId: number, code: string) =>
},
});

const getTeams = () => teamFetcher(`/teams`);

const getTeamMembers = (teamId: number) => teamFetcher(`/teams/${teamId}/members`);

const getMyTeams = (memberId: number) => teamFetcher(`/teams/members/${memberId}`);
Expand All @@ -62,6 +64,7 @@ export {
deleteTeam,
postInviteTeam,
postJoinTeam,
getTeams,
getMyTeams,
getMyTeamsWithStudy,
getTeamMembers,
Expand Down
4 changes: 2 additions & 2 deletions src/app/team/[teamId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import TeamControlPanel from '@/containers/team/TeamControlPanel';
import TeamMember from '@/containers/team/teamMember';
import { useMutateWithToken } from '@/hooks/useFetchWithToken';
import documentCardData from '@/mocks/documentCard';
import { gardenInfos1 } from '@/mocks/Garden3D';
import { gardenData } from '@/mocks/Garden3D';
import studyCardData from '@/mocks/studyCard';
import teamInfoData from '@/mocks/teamInfo';

Expand Down Expand Up @@ -133,7 +133,7 @@ const Page = ({ params }: { params: { teamId: number } }) => {
rotateY={0}
cubeGap={useBreakpointValue({ base: 3, xl: 4 }) || 3}
cubeSize={useBreakpointValue({ base: 20, md: 26, xl: 30 }) || 20}
gardenInfos={gardenInfos1}
garden={gardenData}
/>
</Box>
</Box>
Expand Down
39 changes: 27 additions & 12 deletions src/components/Garden3D/index.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,43 @@
/* eslint-disable import/no-extraneous-dependencies */

'use client';

import { Box } from '@chakra-ui/react';
import dayjs from 'dayjs';
import { useState } from 'react';

import { Garden } from '@/types';

import Bar from './Bar';
import { Garden3DProps } from './types';

const Garden3D = ({ rotate = false, cubeSize, cubeGap, rotateY, gardenInfos }: Garden3DProps) => {
const Garden3D = ({ rotate = false, cubeSize, cubeGap, rotateY, garden }: Garden3DProps) => {
const gardenInfo: Garden[] = [];

const dayCount = 7 * 12 + dayjs().day();
for (let i = dayCount; i >= 0; i -= 1) {
gardenInfo.push({ contributeDate: dayjs().subtract(i, 'days').format('YYYY-MM-DD'), contributeCount: 0 });
}

garden.forEach((grass) => {
const duration = dayjs().diff(dayjs(grass.contributeDate), 'days');
if (duration >= 0 && dayCount >= duration) gardenInfo[dayCount - duration].contributeCount = grass.contributeCount;
});

const cubeSizeHalf = cubeSize / 2;

const offsetDefaultY = 545;
const [offsetY, setOffsetY] = useState<number>(offsetDefaultY);

const gap = cubeSize + cubeGap;
const standX = (gardenInfos[gardenInfos.length - 1].week - gardenInfos[0].week + 1) / 2 + gardenInfos[0].week;
const standX = 8;
const maxCount =
gardenInfos.reduce((prev, value) => {
return prev.count >= value.count ? prev : value;
}).count / 4;
gardenInfo.reduce((prev, value) => {
return prev.contributeCount >= value.contributeCount ? prev : value;
}).contributeCount / 4;

/* setting for drag event */
const [yDegree, setYDegree] = useState<number>(rotateY);

/* cube mouse drag event */
const mouseDown = (clickEvent: React.MouseEvent<Element, MouseEvent>) => {
const mouseMoveHandler = (moveEvent: MouseEvent) => {
const deltaX = moveEvent.screenX - clickEvent.screenX;
Expand Down Expand Up @@ -51,20 +66,20 @@ const Garden3D = ({ rotate = false, cubeSize, cubeGap, rotateY, gardenInfos }: G
h="100%"
style={{ perspective: '800px', transformStyle: 'preserve-3d' }}
>
{gardenInfos.map((info) => {
const currX = (info.week - standX) * gap;
const currZ = (info.date - 3) * gap;
{gardenInfo.map((info, idx) => {
const currX = (Math.floor(idx / 7) - standX) * gap;
const currZ = (dayjs(info.contributeDate).day() - 3) * gap;

return (
<Box
key={info.id}
key={info.contributeDate}
pos="absolute"
w="100%"
h="100%"
style={{ transformStyle: 'preserve-3d', transform: `rotateY(${yDegree}deg)` }}
>
<Bar
count={info.count}
count={info.contributeCount}
maxCount={maxCount}
currX={currX}
currZ={currZ}
Expand Down
4 changes: 2 additions & 2 deletions src/components/Garden3D/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GardenInfoType } from '@/types';
import { Garden } from '@/types';

export interface CubeProps {
currX: number;
Expand All @@ -14,5 +14,5 @@ export interface Garden3DProps {
cubeSize: number;
cubeGap: number;
rotateY: number;
gardenInfos: GardenInfoType[];
garden: Garden[];
}
15 changes: 8 additions & 7 deletions src/containers/main/TeamCard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Box, Card, CardHeader, Text, Flex, CardBody, useBreakpointValue } from '@chakra-ui/react';

import Garden3D from '@/components/Garden3D';
import { TeamRank } from '@/types';

import { TeamCardProps } from './types';

const TeamCard = ({ rank, name, description, gardenInfos }: TeamCardProps) => {
const TeamCard = ({ rank, teamReferenceResponse, teamGardenResponse }: Omit<TeamRank, 'point'>) => {
return (
<Card overflow="hidden" w="100%" h="100%" bg="none" backdropFilter="blur(30px)">
<CardHeader
Expand All @@ -19,7 +18,7 @@ const TeamCard = ({ rank, name, description, gardenInfos }: TeamCardProps) => {
<Text textStyle="title_bold_xl" textAlign="right">
{rank}
</Text>
<Box pos="absolute" top={{ base: '110px', lg: '150px', '2xl': '170px' }} w="100%">
<Box pos="absolute" top={{ base: '120px', lg: '160px', '2xl': '170px' }} w="100%">
<Box w="100%" h="2px" bg="white" id="bar" />
<Box
pos="absolute"
Expand All @@ -35,15 +34,17 @@ const TeamCard = ({ rank, name, description, gardenInfos }: TeamCardProps) => {
</Box>
</Box>
<Flex direction="column" w="full" pt={{ base: '6', lg: '7', '2xl': '10' }}>
<Text textStyle="bold_4xl">{name}</Text>
<Text textStyle="bold_4xl">{teamReferenceResponse.name}</Text>
<Text
textStyle="md"
overflow="hidden"
w={{ base: '250px', lg: '300px', '2xl': '350px' }}
maxH={{ base: '44px', xl: '48px' }}
whiteSpace="wrap"
>
{description === '' ? '팀 소개글이 아직 없습니다.' : description}
{teamReferenceResponse.description === ''
? '팀 소개글이 아직 없습니다.'
: teamReferenceResponse.description}
</Text>
</Flex>
</CardHeader>
Expand All @@ -60,7 +61,7 @@ const TeamCard = ({ rank, name, description, gardenInfos }: TeamCardProps) => {
cubeSize={useBreakpointValue({ base: 18, lg: 24, '2xl': 32 }) || 18}
cubeGap={4}
rotateY={55}
gardenInfos={gardenInfos}
garden={teamGardenResponse}
/>
</CardBody>
</Card>
Expand Down
4 changes: 2 additions & 2 deletions src/containers/main/TeamCard/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { GardenInfoType } from '@/types';
import { Garden } from '@/types';

export interface TeamCardProps {
rank: number;
name: string;
description: string;
gardenInfos: GardenInfoType[];
garden: Garden[];
}
40 changes: 25 additions & 15 deletions src/containers/main/TeamRankSlider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,39 @@

import { Box, Flex } from '@chakra-ui/react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { Swiper, SwiperSlide, SwiperClass } from 'swiper/react';

import 'swiper/css';

import teamRankInfos from '@/mocks/TeamRanking';
import { getTeams } from '@/app/api/team';
import { TeamRank } from '@/types';

import TeamCard from '../TeamCard';

const TeamRankSlider = () => {
const [teamRank, setTeamRank] = useState<TeamRank[]>([]);
const [swiperIndex, setSwiperIndex] = useState<number>(0);
const [swiper, setSwiper] = useState<SwiperClass>();
const router = useRouter();

const slideOnClick = (idx: number, url: string) => {
const slideOnClick = (idx: number, teamId: number) => {
if (swiper?.activeIndex === idx) {
router.push(url);
router.push(`/team/${teamId}`);
} else {
swiper?.slideTo(idx);
}
};

useEffect(() => {
getTeams().then((res) => {
const teams = res.body.slice(0, 10).map((team: TeamRank, idx: number) => {
return { ...team, rank: idx + 1 };
});
setTeamRank(teams);
});
}, []);

return (
<Flex align="center" direction="column" w="100%">
<Box w="100%">
Expand All @@ -34,21 +45,20 @@ const TeamRankSlider = () => {
onSwiper={(e) => setSwiper(e)}
onSlideChange={(e) => setSwiperIndex(e.activeIndex)}
>
{teamRankInfos.map((data) => (
<SwiperSlide key={data.id} style={{ width: 'fit-content' }}>
{teamRank.map((team, idx) => (
<SwiperSlide key={team.teamReferenceResponse.id} style={{ width: 'fit-content' }}>
<Box
overflow="hidden"
w={{ base: '450px', lg: '600px', '2xl': '720px' }}
h={{ base: '300px', lg: '360px', '2xl': '430px' }}
bg="rgba(255, 255, 255, 0.1)"
borderRadius="30"
onClick={() => slideOnClick(data.idx, data.url)}
onClick={() => slideOnClick(idx, team.teamReferenceResponse.id)}
>
<TeamCard
rank={data.rank}
name={data.name}
description={data.description}
gardenInfos={data.gardenInfos}
rank={team.rank}
teamReferenceResponse={team.teamReferenceResponse}
teamGardenResponse={team.teamGardenResponse}
/>
</Box>
</SwiperSlide>
Expand All @@ -57,16 +67,16 @@ const TeamRankSlider = () => {
</Box>

<Flex justify="center" w="100%" h="10" mt="8">
{teamRankInfos.map((data) => (
{teamRank.map((team, idx) => (
<Box
key={data.id}
key={team.teamReferenceResponse.id}
w="3"
h="3"
mx="4"
bg={data.idx === swiperIndex ? 'white' : 'transparent'}
bg={idx === swiperIndex ? 'white' : 'transparent'}
border="2px solid white"
borderRadius="100%"
onClick={() => swiper?.slideTo(data.idx)}
onClick={() => swiper?.slideTo(idx)}
/>
))}
</Flex>
Expand Down
Loading

0 comments on commit 894e191

Please sign in to comment.