generated from nim-od/softeer-mono-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #47 from softeerbootcamp4th/TASK-168
[Feature][Task-168] 캐스퍼 레이싱 대시보드 구현 & 레이싱 컨트롤 버튼 기능 보완
- Loading branch information
Showing
42 changed files
with
335 additions
and
146 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 9 additions & 2 deletions
11
packages/user/src/components/common/GradientBorderWrapper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
packages/user/src/components/event/racing/controls/TeamButton.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Category } from '@softeer/common/types'; | ||
import { ButtonHTMLAttributes } from 'react'; | ||
import GradientBorderWrapper from 'src/components/common/GradientBorderWrapper.tsx'; | ||
import { TEAM_DESCRIPTIONS } from 'src/constants/teamDescriptions.ts'; | ||
import type { Rank } from 'src/types/rank.d.ts'; | ||
|
||
const imageUrls: Record<Category, string> = { | ||
travel: '/images/racing/side/travel.png', | ||
leisure: '/images/racing/side/leisure.png', | ||
place: '/images/racing/side/place.png', | ||
pet: '/images/racing/side/pet.png', | ||
}; | ||
|
||
interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'> { | ||
type: Category; | ||
rank: Rank; | ||
percent: number; | ||
} | ||
|
||
export default function TeamButton({ | ||
type, | ||
rank, | ||
percent, | ||
disabled = false, | ||
...props | ||
}: ButtonProps) { | ||
const { shortTitle, title } = TEAM_DESCRIPTIONS[type]; | ||
const imageUrl = imageUrls[type]; | ||
|
||
const displayTitle = shortTitle ?? title; | ||
const formattedPercent = percent.toFixed(2); | ||
|
||
const styles = getStyles({ type, isActive: !disabled }); | ||
|
||
return ( | ||
<button type="button" disabled={disabled} className={styles.button} {...props}> | ||
<GradientBorderWrapper className={styles.borderWrapper}> | ||
<div className={styles.innerborderWrapper}> | ||
<h2 className="pt-2">{rank}</h2> | ||
<div className="flex flex-col items-center"> | ||
<p className={styles.percent}>{formattedPercent}%</p> | ||
<h6>{displayTitle}</h6> | ||
</div> | ||
</div> | ||
</GradientBorderWrapper> | ||
<img src={imageUrl} alt={`${title} 팀 캐스퍼 실물`} className={styles.image} /> | ||
</button> | ||
); | ||
} | ||
|
||
function getStyles({ type, isActive }: { type: Category; isActive: boolean }) { | ||
const { bgStyles, fontStyles } = styles[type]; | ||
const imageBaseStyles = 'absolute -bottom-[25px] -right-[18px] z-10 w-[100px] object-contain'; | ||
|
||
return { | ||
percent: `text-body-3 font-medium ${fontStyles}`, | ||
image: `${imageBaseStyles} ${isActive ? 'transition-transform duration-300 ease-out group-active:scale-125' : ''}`, | ||
button: 'relative overflow-visible group disabled:opacity-50', | ||
borderWrapper: isActive ? 'group-active:animate-rotate' : '', | ||
innerborderWrapper: `flex h-[84px] w-[240px] gap-7 rounded-[inherit] px-[10px] py-[10px] ${bgStyles}`, | ||
}; | ||
} | ||
|
||
const styles: Record<Category, { bgStyles: string; fontStyles: string }> = { | ||
travel: { bgStyles: 'bg-gradient-cards1', fontStyles: 'text-orange-500' }, | ||
leisure: { bgStyles: 'bg-gradient-cards2', fontStyles: 'text-yellow-500' }, | ||
place: { bgStyles: 'bg-gradient-cards3', fontStyles: 'text-neutral-200' }, | ||
pet: { bgStyles: 'bg-gradient-cards4', fontStyles: 'text-yellow-500' }, | ||
}; |
25 changes: 25 additions & 0 deletions
25
packages/user/src/components/event/racing/controls/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { CATEGORIES } from '@softeer/common/constants'; | ||
import { Category } from '@softeer/common/types'; | ||
import { CategoryRankMap } from 'src/types/rank.js'; | ||
import ControlButton from './ControlButton.tsx'; | ||
|
||
interface RacingControlsProps { | ||
ranks: CategoryRankMap; | ||
setScaledType: (type: Category) => void; | ||
} | ||
|
||
export default function RacingControls({ ranks, setScaledType }: RacingControlsProps) { | ||
return ( | ||
<div className="relative mt-[50px] h-[300px] w-full"> | ||
{CATEGORIES.map((type) => ( | ||
<ControlButton | ||
key={type} | ||
type={type} | ||
rank={ranks[type]} | ||
percentage={25} | ||
onScale={() => setScaledType(type)} | ||
/> | ||
))} | ||
</div> | ||
); | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/user/src/components/event/racing/dashboard/Background.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
export default function Background() { | ||
return ( | ||
<img | ||
className="absolute -z-10 h-full w-full object-contain" | ||
alt="레이싱 배경" | ||
src="/images/racing/background.png" | ||
/> | ||
); | ||
} |
41 changes: 41 additions & 0 deletions
41
packages/user/src/components/event/racing/dashboard/Casper.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { Category } from '@softeer/common/types'; | ||
import MarkerIcon from 'src/assets/icons/car-marker.svg?react'; | ||
import useAuth from 'src/hooks/useAuth.tsx'; | ||
import type { Rank } from 'src/types/rank.d.ts'; | ||
|
||
interface CasperProps { | ||
type:Category | ||
rank: Rank; | ||
className: string; | ||
} | ||
export default function Casper({ type, rank, className }: CasperProps) { | ||
const { user } = useAuth(); | ||
const isMyCasper = user?.type === type; | ||
|
||
return ( | ||
<div className={`flex flex-col items-center gap-8 absolute ${className} ${rankStyles[rank]} ${transitionStyles}`}> | ||
<div className="h-[10px]">{isMyCasper && <MarkerIcon /> }</div> | ||
<img | ||
src={imageUrls[type]} | ||
alt={`${rank}등 차`} | ||
className="object-contain" | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
const transitionStyles = 'transform transition-all duration-700 ease-in-out'; | ||
|
||
const rankStyles: Record<Rank, string> = { | ||
1: 'w-[335px] left-[378px] top-[295px] z-40 rotate-0', | ||
2: 'w-[260px] left-[170px] top-[345px] z-30 -rotate-[4deg]', | ||
3: 'w-[230px] left-[850px] top-[360px] z-20 rotate-6', | ||
4: 'w-[120px] left-[690px] top-[410px] z-10 rotate-[5deg]', | ||
}; | ||
|
||
const imageUrls: Record<Category, string> = { | ||
travel: '/images/racing/front/travel.png', | ||
leisure: '/images/racing/front/leisure.png', | ||
place: '/images/racing/front/place.png', | ||
pet: '/images/racing/front/pet.png', | ||
}; |
15 changes: 15 additions & 0 deletions
15
packages/user/src/components/event/racing/dashboard/RacingTitle.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
export default function RacingTitle() { | ||
return ( | ||
<> | ||
<h3> | ||
버튼을 연타해 승리를 <strong>CHARGE</strong>하세요! | ||
</h3> | ||
<div className="mb-5 flex items-center gap-3"> | ||
<p className="text-body-2 text-foreground/60"> | ||
1등에 가까워질 수 있도록 배터리를 가득 충전 | ||
<strong className="inline-block align-bottom leading-6">🔋</strong>해주세요! | ||
</p> | ||
</div> | ||
</> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
2 changes: 1 addition & 1 deletion
2
...rc/components/event/racing/card/index.tsx → ...nts/event/racing/dashboard/card/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
59 changes: 59 additions & 0 deletions
59
packages/user/src/components/event/racing/dashboard/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { CATEGORIES } from '@softeer/common/constants'; | ||
import { Category } from '@softeer/common/types'; | ||
import { Suspense } from 'react'; | ||
import type { CategoryRankMap } from 'src/types/rank.d.ts'; | ||
import Background from './Background.tsx'; | ||
import RacingCard from './card/index.tsx'; | ||
import Casper from './Casper.tsx'; | ||
import RacingTitle from './RacingTitle.tsx'; | ||
import EventTimer from './timer/index.tsx'; | ||
|
||
interface RacingDashboardProps { | ||
ranks: CategoryRankMap; | ||
scaledType: Category | null; | ||
} | ||
|
||
export default function RacingDashboard({ ranks, scaledType }: RacingDashboardProps) { | ||
return ( | ||
<div className="relative h-[685px] w-full"> | ||
<HeaderSection /> | ||
<RacingCardSection /> | ||
<CaspersSection ranks={ranks} scaledType={scaledType} /> | ||
<Background /> | ||
</div> | ||
); | ||
} | ||
|
||
function HeaderSection() { | ||
return ( | ||
<div className="absolute -top-[5px] flex w-full flex-col items-center"> | ||
<RacingTitle /> | ||
<Suspense> | ||
<EventTimer /> | ||
</Suspense> | ||
</div> | ||
); | ||
} | ||
|
||
function RacingCardSection() { | ||
return ( | ||
<div className="absolute left-[27px] top-[95px]"> | ||
<RacingCard /> | ||
</div> | ||
); | ||
} | ||
|
||
function CaspersSection({ ranks, scaledType }: RacingDashboardProps) { | ||
return ( | ||
<> | ||
{CATEGORIES.map((type) => ( | ||
<Casper | ||
key={type} | ||
type={type} | ||
rank={ranks[type]} | ||
className={scaledType === type ? 'scale-110' : ''} | ||
/> | ||
))} | ||
</> | ||
); | ||
} |
File renamed without changes.
File renamed without changes.
Oops, something went wrong.