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

feat: deep dip scene redesign #179

Merged
merged 2 commits into from
May 5, 2024
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
39 changes: 39 additions & 0 deletions modules/deep-dip/leaderboard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from 'react';
import clsx from 'clsx';
import { useCurrentProgress, useGlobalLeaderboard } from '../pre-stream/utils/deep-dip';
import { ResultBlock, ResultBlockDivider, ResultBlockFallback } from './result-block';

export function DeepDip2Leaderboard({ className }: React.ComponentPropsWithoutRef<'div'>) {
const { leaderboard, isLoading: isLeaderboardLoading } = useGlobalLeaderboard();
const { progress, isLoading: isProgressLoading } = useCurrentProgress();
const truncatedLeaderboard = leaderboard?.length ? leaderboard.slice(0, 10) : [];

return (
<div className={clsx('flex flex-col items-center flex-1 space-y-3', className)}>
<div className="flex items-center justify-between flex-1 w-full max-w-7xl px-6 bg-chungking-black/90 rounded-lg">
<div className="text-chungking-white text-4xl font-bold">Current Standings</div>
</div>
<div className="flex flex-col flex-1 w-full max-w-7xl space-y-3">
<div className="flex flex-col space-y-2">
{isLeaderboardLoading
? Array(10)
.fill(undefined)
.map((_, key) => <ResultBlockFallback key={key} />)
: truncatedLeaderboard.map(item => <ResultBlock key={item.wsid} result={item} />)}
</div>

{isProgressLoading ? (
<>
<ResultBlockDivider />
<ResultBlockFallback />
</>
) : progress ? (
<>
<ResultBlockDivider />
<ResultBlock result={progress} />
</>
) : null}
</div>
</div>
);
}
34 changes: 34 additions & 0 deletions modules/deep-dip/result-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react';
import { LeaderboardResult } from '~/server/modules/deepdip/get-global-leaderboard';

export interface ResultBlockProps {
result: LeaderboardResult;
}

export function ResultBlockDivider() {
return (
<div className="flex items-center justify-center h-[16px] bg-chungking-black/90 rounded-lg" />
);
}

export function ResultBlockFallback() {
return (
<div className="flex items-center justify-between h-[56px] bg-chungking-black/90 rounded-lg" />
);
}

export function ResultBlock({ result }: ResultBlockProps) {
return (
<div className="flex items-center justify-between bg-chungking-black/90 rounded-lg gap-6 p-1">
<div className="flex items-center justify-center w-[84px] h-[48px] rounded-md bg-chungking-blue-500">
<span className="text-chungking-white text-3xl font-bold">{result.rank}</span>
</div>
<div className="flex items-center justify-start flex-1 pr-3">
<span className="text-chungking-white text-3xl">{result.name}</span>
</div>
<div className="flex items-center justify-center px-2 w-[160px] h-[48px] rounded-md bg-chungking-white">
<span className="text-chungking-black text-3xl font-bold">{result.height.toFixed(1)}m</span>
</div>
</div>
);
}
190 changes: 127 additions & 63 deletions modules/pre-stream/pre-stream-deep-dip.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,137 @@
import * as React from 'react';
import { useClock } from '~/lib/hooks/use-clock';
import { useOnMount } from '~/lib/hooks/use-on-mount';
import { DeepDip2Leaderboard } from '../deep-dip/leaderboard';
import { useOverlayData } from '../overlay-data/use-overlay-data';
import { SceneWrapper } from '../scenes/scene-wrapper';
import { useCurrentProgress, useGlobalLeaderboard } from './utils/deep-dip';
import { PreStreamSceneProps } from './pre-stream-scene';
import { PreStreamWipeUpperLayer } from './pre-stream-wipe-upper-layer';
import { PreStreamWipeLowerLayer } from './pre-stream-wipe-lower-layer';
import { PrestreamCountdown } from './pre-stream-countdown';
import { PrestreamDate } from './pre-stream-date';

export function PreStreamDeepDipScene() {
const { leaderboard, isLoading: isLeaderboardLoading } = useGlobalLeaderboard();
const { progress, isLoading: isProgressLoading } = useCurrentProgress();
const truncatedLeaderboard = leaderboard?.length ? leaderboard.slice(0, 10) : [];
export function PreStreamDeepDipScene({ headerText, variant }: PreStreamSceneProps) {
const time = useClock();
const [isClientReady, setIsClientReady] = React.useState(false);
const { overlayData } = useOverlayData();

return (
<SceneWrapper>
<div className="flex flex-col items-center flex-1 pt-[96px] pb-[24px] px-[128px] space-y-4">
<div className="flex items-center justify-between w-full max-w-7xl h-[72px] px-6 bg-black/90 rounded-lg">
<div className="text-white text-4xl font-bold">Deep Dip 2 - Current Standings</div>
<div className="text-white text-3xl">Be right back.</div>
</div>
<div className="flex flex-col flex-1 w-full max-w-7xl space-y-3">
<div className="flex flex-col space-y-2">
{isLeaderboardLoading
? Array(10)
.fill(undefined)
.map((_, key) => (
<div
className="flex items-center justify-between h-[56px] bg-black/90 rounded-lg gap-6"
key={key}
/>
))
: truncatedLeaderboard.map(item => (
<div
className="flex items-center justify-between bg-black/90 rounded-lg gap-6 p-1"
key={item.wsid}
>
<div className="flex items-center justify-center w-[64px] h-[48px] rounded-md bg-blue-600">
<span className="text-white text-2xl font-bold">{item.rank}</span>
</div>
<div className="flex items-center justify-start flex-1 pr-3">
<span className="text-white text-2xl font-bold">{item.name}</span>
</div>
<div className="flex items-center justify-center px-2 w-[128px] h-[48px] rounded-md bg-white">
<span className="text-black text-2xl font-bold">
{item.height.toFixed(1)}m
</span>
</div>
</div>
))}
const streamStart = React.useMemo(
() => (overlayData?.streamStart ? new Date(overlayData.streamStart) : undefined),
[overlayData?.streamStart],
);

const isAnimationActive = React.useMemo(() => {
if (variant !== 'pre-stream' && variant !== 'pre-stream-cerveza') {
return false;
}

if (streamStart) {
return time.toISOString() >= streamStart.toISOString();
}

return false;
}, [streamStart, time, variant]);

useOnMount(() => {
setIsClientReady(true);
});

const renderCountdown = (format?: string) => {
if (isClientReady) {
if (variant === 'pre-stream' || variant === 'pre-stream-cerveza') {
return (
<div className="flex items-center justify-center w-full p-4 rounded-md bg-chungking-blue-500">
<PrestreamCountdown
className="text-8xl leading-none text-chungking-white font-bold tabular-nums helper-alternate-digits"
timeFormat={format}
/>
</div>
);
}

return null;
}

return null;
};

{isProgressLoading ? (
<>
<div className="flex items-center justify-center h-[16px] bg-black/90 rounded-lg gap-6" />
<div className="flex items-center justify-between h-[56px] bg-black/90 rounded-lg gap-6" />
</>
) : progress ? (
<>
<div className="flex items-center justify-center h-[16px] bg-black/90 rounded-lg gap-6" />
<div className="flex items-center justify-between bg-black/90 rounded-lg gap-6 p-1">
<div className="flex items-center justify-center w-[64px] h-[48px] rounded-md bg-blue-600">
<span className="text-white text-xl font-bold">{progress.rank}</span>
</div>
<div className="flex items-center justify-start flex-1 pr-3">
<span className="text-white text-2xl font-bold">{progress.name}</span>
</div>
<div className="flex items-center justify-center px-2 w-[128px] h-[48px] rounded-md bg-white">
<span className="text-black text-2xl font-bold tabular-nums">
{progress.height.toFixed(1)}m
</span>
</div>
const renderDateTime = () => {
if (isClientReady) {
return (
<div className="flex items-center justify-center space-x-2 w-full p-4 rounded-md bg-chungking-white">
<PrestreamDate
className="text-4xl leading-none text-chungking-black font-bold"
dateFormat="EEEE"
/>
<PrestreamDate className="text-4xl leading-none text-chungking-black" />
</div>
);
}

return null;
};

const getColorClassName = () => {
switch (variant) {
case 'pre-stream':
case 'pre-stream-cerveza': {
return 'bg-chungking-blue-500';
}
case 'brb': {
return 'bg-chungking-green-500';
}
case 'tech-issues': {
return 'bg-chungking-magenta-500';
}
case 'end': {
return 'bg-chungking-orange-500';
}
default: {
return 'bg-chungking-blue-500';
}
}
};

const renderWipeUpperLayer = () => {
if (isClientReady) {
return (
<PreStreamWipeUpperLayer
isVisible={isAnimationActive}
cerveza={variant === 'pre-stream-cerveza'}
/>
);
}
};

const renderWipeLowerLayer = () => {
if (isClientReady) {
return (
<PreStreamWipeLowerLayer className={getColorClassName()} isVisible={isAnimationActive} />
);
}
};

return (
<SceneWrapper>
<div className="grid grid-rows-scene-wrapper grid-cols-1 flex-1">
<div className="grid w-full relative">
<div className="absolute top-0 left-0 w-full h-full z-30">{renderWipeUpperLayer()}</div>
<div className="grid grid-cols-12 gap-3 pt-[96px] pb-[24px] px-[128px] z-20">
<div className="flex flex-col items-start justify-between col-span-4 p-6 bg-chungking-black/90 rounded-lg">
<div className="flex flex-col space-y-2">
<span className="text-4xl leading-none text-chungking-white font-bold">
Deep Dip 2
</span>
<span className="text-4xl leading-none text-chungking-white">{headerText}</span>
</div>
</>
) : null}
<div className="flex flex-col space-y-3 w-full">
{renderCountdown('mm:ss')}
{renderDateTime()}
</div>
</div>
<DeepDip2Leaderboard className="col-span-8" />
</div>
<div className="absolute top-0 left-0 w-full h-full z-10">{renderWipeLowerLayer()}</div>
</div>
</div>
</SceneWrapper>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createNextPage } from '~/lib/create-next-page';
import { PreStreamDeepDipScene } from '~/modules/pre-stream/pre-stream-deep-dip';

const DeepDipBRBScenePage: NextPage = () => {
return <PreStreamDeepDipScene />;
return <PreStreamDeepDipScene headerText="Be right back." variant="brb" />;
};

export default createNextPage(DeepDipBRBScenePage, {
Expand Down
14 changes: 14 additions & 0 deletions pages/scenes/deep-dip/end.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import { NextPage } from 'next';

import { OverlayLayout } from '~/layouts/overlay-layout';
import { createNextPage } from '~/lib/create-next-page';
import { PreStreamDeepDipScene } from '~/modules/pre-stream/pre-stream-deep-dip';

const DeepDipEndScenePage: NextPage = () => {
return <PreStreamDeepDipScene headerText="Thanks for watching!" variant="end" />;
};

export default createNextPage(DeepDipEndScenePage, {
layout: OverlayLayout,
});
14 changes: 14 additions & 0 deletions pages/scenes/deep-dip/pre-stream.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import { NextPage } from 'next';

import { OverlayLayout } from '~/layouts/overlay-layout';
import { createNextPage } from '~/lib/create-next-page';
import { PreStreamDeepDipScene } from '~/modules/pre-stream/pre-stream-deep-dip';

const DeepDipPreStreamScenePage: NextPage = () => {
return <PreStreamDeepDipScene headerText="Starting soon." variant="pre-stream" />;
};

export default createNextPage(DeepDipPreStreamScenePage, {
layout: OverlayLayout,
});
6 changes: 3 additions & 3 deletions server/modules/deepdip/get-global-leaderboard.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import fetch from 'isomorphic-unfetch';

export interface Leaderboard {
export interface LeaderboardResult {
rank: number;
wsid: string;
height: number;
Expand All @@ -10,14 +10,14 @@ export interface Leaderboard {

export async function getGlobalLeaderboard() {
const response = await fetch('https://dips-plus-plus.xk.io/leaderboard/global');
const data: Leaderboard[] = await response.json();
const data: LeaderboardResult[] = await response.json();

return data;
}

export async function getCurrentProgress(accountId = '15d23e07-07ac-4093-bbfd-28d393daf0c0') {
const response = await fetch(`https://dips-plus-plus.xk.io/leaderboard/${accountId}`);
const data: Leaderboard = await response.json();
const data: LeaderboardResult = await response.json();

return data;
}
Loading