Skip to content

Commit

Permalink
Merge pull request #54 from DDD-Community/feat/#32
Browse files Browse the repository at this point in the history
Feat/#32
  • Loading branch information
G-hoon authored Sep 9, 2024
2 parents f21b80c + a6a35b6 commit 90800b7
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 18 deletions.
3 changes: 3 additions & 0 deletions src/assets/icons/crew-1st-crown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/crew-my-crew-header-flag.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/assets/icons/crew-send-invitation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 19 additions & 13 deletions src/components/Crew/CrewList.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { useState, useRef, useEffect, ReactElement } from "react"
import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react"
import SortCrewIcon from "@assets/icons/crew-sort-icon.svg?react"
import EmptyCrewImage from "@/assets/images/crew-empty.png"
import { useGetGroups } from "@/hooks/useGroupMutation"
import { group, groupsReq } from "@/api"
import EmptyCrewImage from "@/assets/images/crew-empty.png"
import CrewItem from "@/components/Crew/CrewItem"
import JoinCrewModal from "@/components/Modal/JoinCrewModal"
import CreateCrewModal from "@/components/Modal/CreateCrewModal"
import JoinCrewModal from "@/components/Modal/JoinCrewModal"
import { useGetGroups } from "@/hooks/useGroupMutation"
import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react"
import SortCrewIcon from "@assets/icons/crew-sort-icon.svg?react"
import { ReactElement, useEffect, useRef, useState } from "react"

import MyCrewRankingContainer from "./MyCrewRankingContainer"

const SORT_LIST = [
{ sort: "userCount,desc", label: "크루원 많은 순" },
Expand All @@ -15,6 +17,7 @@ const SORT_LIST = [

const CrewList = (): ReactElement => {
const [sort, setSort] = useState<number>(0)
const [mode] = useState<"my" | "list">("my")
const [isDropdownOpen, setIsDropdownOpen] = useState<boolean>(false)
const [isJoinModalOpen, setIsJoinModalOpen] = useState<boolean>(false)
const [isCreateModalOpen, setIsCreateModalOpen] = useState<boolean>(false)
Expand Down Expand Up @@ -90,16 +93,19 @@ const CrewList = (): ReactElement => {

return (
<div className="flex h-full w-full flex-col">
{mode === "my" && <MyCrewRankingContainer openCreateModal={openCreateModal} />}
{/* header */}
<div className="mb-[24px] flex w-full items-center">
<div className="flex-grow text-[22px] font-bold text-zinc-900">전체크루(0)</div>
<div
className="flex w-[138px] cursor-pointer items-center justify-center gap-[10px] rounded-[33px] bg-zinc-800 p-[10px] text-sm font-semibold text-white"
onClick={openCreateModal}
>
<CreateCrewIcon />
<div>크루 만들기</div>
</div>
{mode === "list" && (
<div
className="flex w-[138px] cursor-pointer items-center justify-center gap-[10px] rounded-[33px] bg-zinc-800 p-[10px] text-sm font-semibold text-white"
onClick={openCreateModal}
>
<CreateCrewIcon />
<div>크루 만들기</div>
</div>
)}
</div>

{/* sort */}
Expand Down
82 changes: 82 additions & 0 deletions src/components/Crew/CrewRanking.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import Crew1stCrownIcon from "@assets/icons/crew-1st-crown.svg?react"

const RankPillar = ({ rank, name, score, height }: any) => {
const rankStyleMap: { gap: string; bgColor: string; fontSize: string }[] = [
{
gap: "6",
bgColor: "#8BBAFE",
fontSize: "32px",
},
{
gap: "6",
bgColor: "#DCEBFD",
fontSize: "22px",
},
{
gap: "4",
bgColor: "#DCEBFD",
fontSize: "22px",
},
]

return (
<div className="flex flex-col items-center text-zinc-800" style={{ height }}>
<div
className={`flex w-[180px] flex-grow flex-col items-center justify-end py-6 gap-${
rankStyleMap[rank - 1].gap
} rounded-[12px] bg-[${rankStyleMap[rank - 1].bgColor}]`}
style={{ minHeight: "100px" }} // 최소 높이 설정
>
<div className="flex flex-col items-center">
{rank === 1 && <Crew1stCrownIcon className="mb-2 h-6 w-6" />}
<div className={`font-medium text-[${rankStyleMap[rank - 1].fontSize}]`}>{rank}</div>
</div>
<div className="text-xl font-semibold">{name}</div>
<div className="text-[15px] font-normal ">틀어짐 {score}</div>
</div>
</div>
)
}

const RankCard = ({ rank, name, score, isMe }: any) => (
<div
className={`flex items-center justify-between py-1 pl-3 pr-4 ${isMe ? "rounded-full bg-[#DCEBFD]" : ""} h-[40px]`}
>
<div className="flex items-center gap-4">
<div className="flex h-8 w-8 items-center justify-center font-normal text-zinc-900">{rank}</div>
<span className={isMe ? "font-medium text-[#1A75FF]" : ""}>{isMe ? "나" : name}</span>
</div>
<span className="text-[13px] font-normal text-zinc-400">자세경고 {score}</span>
</div>
)

const CrewRanking = ({ rankings, myRank }: { rankings: any[]; myRank: any }) => {
const topThree = rankings.slice(0, 3)

return (
<div className="flex h-full gap-12">
{/* 1, 2, 3등 랭킹 */}
<div className="flex h-full flex-1 items-end gap-3">
<RankPillar rank={1} name={topThree[0].name} score={topThree[0].score} height="100%" />
<RankPillar rank={2} name={topThree[1].name} score={topThree[1].score} height="82%" />
<RankPillar rank={3} name={topThree[2].name} score={topThree[2].score} height="72%" />
</div>

{/* 전체 랭킹 목록 */}
<div className="flex flex-1 flex-col overflow-hidden">
<div className="flex h-full flex-col overflow-hidden bg-white">
<div className="flex-shrink-0">
<RankCard rank={myRank.rank} name={myRank.name} score={myRank.score} isMe={true} />
</div>
<div className="scrollbar-hide flex-grow overflow-y-auto">
{rankings.map((rank, index) => (
<RankCard key={index} rank={rank.rank} name={rank.name} score={rank.score} isMe={false} />
))}
</div>
</div>
</div>
</div>
)
}

export default CrewRanking
81 changes: 81 additions & 0 deletions src/components/Crew/MyCrewRankingContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react"
import SendInvitationIcon from "@assets/icons/crew-send-invitation.svg?react"
import CrewUserIcon from "@assets/icons/crew-user-icon.svg?react"
import { Link } from "react-router-dom"
import CrewRanking from "./CrewRanking"

import RoutePath from "@/constants/routes.json"

interface MyCrewRankingContainerProps {
openCreateModal: () => void
}

export default function MyCrewRankingContainer(props: MyCrewRankingContainerProps) {
const { openCreateModal } = props
return (
<div className="mb-12">
<div className="mb-[24px] flex w-full items-center">
<div className="flex-grow text-[22px] font-bold text-zinc-900">나의 크루</div>
<div
className="flex w-[138px] cursor-pointer items-center justify-center gap-[10px] rounded-[33px] bg-zinc-800 p-[10px] text-sm font-semibold text-white"
onClick={openCreateModal}
>
<CreateCrewIcon />
<div>크루 만들기</div>
</div>
</div>
<div className="h-[382px] w-full rounded-[12px] bg-white px-8 pt-9">
<div className="flex justify-between">
<div className="flex items-center gap-4">
<div className="text-sm font-bold">주인공 다 모여랏</div>
<div className="flex items-center gap-1">
<CrewUserIcon />
<span className="text-sm font-medium text-zinc-500">7/30명</span>
</div>
<button className="rounded-full border-[1px] border-solid border-gray-200 bg-white">
<div className="flex items-center gap-1 px-2 py-1">
<SendInvitationIcon />
<span className="text-sm font-medium text-zinc-400">초대하기</span>
</div>
</button>
</div>
<Link to={RoutePath.MYCREW}>
<div className="text-sm font-medium text-[#1A75FF]">상세보기 {">"}</div>
</Link>
</div>
{/* 랭킹 헤더 */}
<div className="mt-7">
<div className="flex items-center justify-between">
<span className="text-xl font-semibold text-[#1A75FF]">바른자세 랭킹</span>
<div className="flex gap-2 text-[13px] font-normal text-zinc-400">
<span>최근 1시간</span>
<span>|</span>
<span>2024.08.20 21:00 기준</span>
</div>
</div>
</div>

{/* 랭킹 표시 */}
<div className="mt-4 h-[220px]">
<CrewRanking
rankings={[
{ rank: 1, name: "뚝딱이", score: 1 },
{ rank: 2, name: "뚝딱이2", score: 5 },
{ rank: 3, name: "뚝딱이3", score: 10 },
{ rank: 4, name: "뚝딱이4", score: 11 },
{ rank: 5, name: "뚝딱이4", score: 11 },
{ rank: 6, name: "뚝딱이4", score: 16 },
{ rank: 7, name: "뚝딱이4", score: 17 },
{ rank: 8, name: "뚝딱이4", score: 22 },
{ rank: 9, name: "뚝딱이4", score: 26 },
{ rank: 10, name: "뚝딱이4", score: 32 },
{ rank: 11, name: "뚝딱이4", score: 40 },
// ... more rankings
]}
myRank={{ rank: 12, name: "나", score: 50 }}
/>
</div>
</div>
</div>
)
}
1 change: 1 addition & 0 deletions src/constants/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"LOGIN": "/login",
"AUTH": "/auth",
"CREW": "/crew",
"MYCREW": "/crew/my",
"HOME": "/home",
"SOCKET": "/socket"
}
107 changes: 107 additions & 0 deletions src/pages/MyCrew.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import CrewRanking from "@/components/Crew/CrewRanking"
import CreateCrewIcon from "@assets/icons/crew-create-button-icon.svg?react"
import FlagIcon from "@assets/icons/crew-my-crew-header-flag.svg?react"
import SendInvitationIcon from "@assets/icons/crew-send-invitation.svg?react"
import CrewUserIcon from "@assets/icons/crew-user-icon.svg?react"

export default function MyCrew() {
return (
<div className="mb-12">
<div className="mb-[24px] flex w-full items-center">
<div className="flex-grow text-[22px] font-bold text-zinc-900">나의 크루</div>
<div
className="flex w-[138px] cursor-pointer items-center justify-center gap-[10px] rounded-[33px] bg-zinc-800 p-[10px] text-sm font-semibold text-white"
// onClick={openCreateModal}
>
<CreateCrewIcon />
<div>크루 만들기</div>
</div>
</div>

<div className="flex w-full justify-between">
<div className="flex items-center gap-4">
<div className="flex items-center gap-3">
<FlagIcon />
<div className="text-xl font-bold text-zinc-800">주인공 다 모여랏</div>
</div>
<span>|</span>
<div className="flex items-center gap-1">
<CrewUserIcon />
<span className="text-sm font-semibold text-zinc-500">7/30명</span>
</div>
<button className="rounded-full border-[1px] border-solid border-gray-200 bg-white">
<div className="flex items-center gap-1 px-2 py-1">
<SendInvitationIcon />
<span className="text-sm font-medium text-zinc-400">초대하기</span>
</div>
</button>
</div>
<button className="rounded-full border-[1px] border-solid border-gray-200 bg-zinc-100">
<div className="px-3 py-1">
<span className="text-[15px] font-medium text-zinc-400">탈퇴하기</span>
</div>
</button>
</div>

{/* 크루 소개 */}
<div className="mt-4 flex min-h-[220px] gap-4">
<div className="flex w-[180px] flex-col items-center rounded-[10px] bg-zinc-800 pt-6">
<span className="text-bold text-[13px] text-[#5A9CFF]">크루장</span>
<span className="pt-6 text-lg font-bold text-zinc-50">꼬북이</span>
</div>
<div className="flex flex-1 flex-col items-center gap-6 rounded-[10px] border-[1px] border-solid border-gray-200 bg-white px-[70px] py-6">
<span className="font-[13px] font-bold text-[#1A75FF]">크루 소개</span>
<p className="overflow-wrap-break-word w-full">
안녕하세요. 자세공작소의 크루 주인공 다 모여랏 입니다. 저희 크루는 PM, 디자이너, 개발자로 이루어져 있습니다.
최대 300자 입니다.안녕하세요. 자세공작소의 크루 주인공 다 모여랏 입니다. 저희 크루는 PM, 디자이너, 개발자로
이루어져 있습니다. 최대 300자 입니다.안녕하세요. 자세공작소의 크루 주인공 다 모여랏 입니다. 저희 크루는 PM,
디자이너, 개발자로 이루어져 있습니다. 최대 300자 입니다.안녕하세요. 자세공작소의 크루 주인공 다 모여랏
입니다. 저희 크루는 PM, 디자이너, 개발자로 이루어져 있습니다.
</p>
</div>
</div>

{/* 랭킹 헤더 */}
<div className="mt-10">
<div className="flex items-center justify-between">
<span className="text-xl font-semibold text-zinc-700">바른자세 랭킹</span>
<div className="flex gap-2 text-[13px] font-normal text-zinc-400">
<span>최근 1시간</span>
<span>|</span>
<span>2024.08.20 21:00 기준</span>
</div>
</div>
</div>

{/* 헤더 */}
<div className="mt-6 h-[280px] w-full rounded-[12px] border-[1px] border-solid border-gray-200 bg-white px-8 py-[30px]">
{/* 랭킹 표시 */}
<div className="h-[220px]">
<CrewRanking
rankings={[
{ rank: 1, name: "뚝딱이", score: 1 },
{ rank: 2, name: "뚝딱이2", score: 5 },
{ rank: 3, name: "뚝딱이3", score: 10 },
{ rank: 4, name: "뚝딱이4", score: 11 },
{ rank: 5, name: "뚝딱이4", score: 11 },
{ rank: 6, name: "뚝딱이4", score: 16 },
{ rank: 7, name: "뚝딱이4", score: 17 },
{ rank: 8, name: "뚝딱이4", score: 22 },
{ rank: 9, name: "뚝딱이4", score: 26 },
{ rank: 10, name: "뚝딱이4", score: 32 },
{ rank: 11, name: "뚝딱이4", score: 40 },
// ... more rankings
]}
myRank={{ rank: 12, name: "나", score: 50 }}
/>
</div>
</div>

{/* footer */}
<div className="height-[68px] mt-3 flex justify-center rounded-[12px] border-[1px] border-solid border-gray-200 bg-white py-6 font-medium">
나는 우리 크루 평균보다 틀어짐이&nbsp; <span className="font-bold text-[#1A75FF]">6회 더</span>
&nbsp;감지되었어요.
</div>
</div>
)
}
15 changes: 10 additions & 5 deletions src/routes/Router.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from "react"
import { BrowserRouter, Route, Routes, Navigate } from "react-router-dom"
import { AuthPage, MonitoringPage, HomePage, AnalysisDashboard, Crew } from "@/pages"
import RoutePath from "@/constants/routes.json"
import AnalysisLayout from "@/layouts/AnalysisLayout"
import BaseLayout from "@/layouts/BaseLayout"
import MonitoringLayout from "@/layouts/MonitoringLayout"
import AnalysisLayout from "@/layouts/AnalysisLayout"
import RoutePath from "@/constants/routes.json"
import { AnalysisDashboard, AuthPage, Crew, HomePage, MonitoringPage } from "@/pages"
import MyCrew from "@/pages/MyCrew"
import AuthRoute from "@/routes/AuthRoute"
import { useAuthStore } from "@/store/AuthStore"
import React from "react"
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom"

const Router: React.FC = () => {
const isAuthenticated = useAuthStore((state) => state.isAuthenticated)
Expand All @@ -32,6 +33,10 @@ const Router: React.FC = () => {
<Route element={<AnalysisLayout />}>
<Route path={RoutePath.CREW} element={<Crew />} />
</Route>

<Route element={<AnalysisLayout />}>
<Route path={RoutePath.MYCREW} element={<MyCrew />} />
</Route>
</Route>
</Route>

Expand Down
8 changes: 8 additions & 0 deletions src/style/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,11 @@
.nav-item svg path {
fill: #5f6368; /* 비활성화 상태의 흰색 */
}

.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}

0 comments on commit 90800b7

Please sign in to comment.