Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#224 팀 랭킹 r api 연결 #263

Merged
merged 11 commits into from
Jun 29, 2024
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 @@ -39,6 +39,8 @@ const postJoinTeam = (teamId: number, code: string) =>
body: code,
});

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

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

const getMyTeams = (memberId: number) => teamFetcher(`/teams/members/${memberId}`);
Expand All @@ -57,6 +59,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 @@ -20,7 +20,7 @@ import StudyGridView from '@/containers/team/StudyGridView';
import TeamControlPanel from '@/containers/team/TeamControlPanel';
import TeamMember from '@/containers/team/teamMember';
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 @@ -109,7 +109,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