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

Winner page rank wave #611

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion components/auth/Auth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ type AuthContextType = {
readonly title: string;
};

export const WAVES_MIN_ACCESS_LEVEL = 10;
// TODO: change it back to 10
export const WAVES_MIN_ACCESS_LEVEL = 0;
const DEFAULT_TITLE = "6529 SEIZE";


Expand Down
6 changes: 2 additions & 4 deletions components/brain/BrainMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import BrainMobileAbout from "./mobile/BrainMobileAbout";
import { ExtendedDrop } from "../../helpers/waves/drop.helpers";
import BrainMobileLeaderboard from "./mobile/BrainMobileLeaderboard";
import { useWaveData } from "../../hooks/useWaveData";
import BrainMobileLeaderboardWrapper from "./mobile/BrainMobileLeaderboardWrapper";

export enum BrainView {
DEFAULT = "DEFAULT",
Expand Down Expand Up @@ -76,10 +77,7 @@ const BrainMobile: React.FC<Props> = ({ children }) => {
[BrainView.DEFAULT]: children,
[BrainView.LEADERBOARD]:
isRankWave && !!wave ? (
<BrainMobileLeaderboard
wave={wave}
onDropClick={onDropClick}
/>
<BrainMobileLeaderboardWrapper wave={wave} onDropClick={onDropClick} />
) : null,
};

Expand Down
23 changes: 23 additions & 0 deletions components/brain/mobile/BrainMobileLeaderboardWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import { ApiWave } from "../../../generated/models/ApiWave";
import { ExtendedDrop } from "../../../helpers/waves/drop.helpers";
import BrainMobileLeaderboard from "./BrainMobileLeaderboard";
import { useWaveState, WaveVotingState } from "../../../hooks/useWaveState";
import { WaveWinners } from "../../waves/detailed/winners/WaveWinners";

interface BrainMobileLeaderboardWrapperProps {
readonly wave: ApiWave;
readonly onDropClick: (drop: ExtendedDrop) => void;
}

const BrainMobileLeaderboardWrapper: React.FC<
BrainMobileLeaderboardWrapperProps
> = ({ wave, onDropClick }) => {
const { votingState } = useWaveState(wave);
if (votingState === WaveVotingState.ENDED) {
return <WaveWinners wave={wave} onDropClick={onDropClick} />;
}
return <BrainMobileLeaderboard wave={wave} onDropClick={onDropClick} />;
};

export default BrainMobileLeaderboardWrapper;
31 changes: 12 additions & 19 deletions components/brain/mobile/BrainMobileTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useUnreadNotifications } from "../../../hooks/useUnreadNotifications";
import { BrainView } from "../BrainMobile";
import { ApiWaveType } from "../../../generated/models/ApiWaveType";
import { ApiWave } from "../../../generated/models/ApiWave";
import MyStreamWaveTabsLeaderboard from "../my-stream/MyStreamWaveTabsLeaderboard";

interface BrainMobileTabsProps {
readonly activeView: BrainView;
Expand Down Expand Up @@ -39,8 +40,11 @@ const BrainMobileTabs: React.FC<BrainMobileTabsProps> = ({
};
}, [router.events, onViewChange]);

const isLinkActive = router.pathname === "/my-stream" && activeView === BrainView.DEFAULT;
const isNotificationsActive = router.pathname === "/my-stream/notifications" && activeView === BrainView.DEFAULT;
const isLinkActive =
router.pathname === "/my-stream" && activeView === BrainView.DEFAULT;
const isNotificationsActive =
router.pathname === "/my-stream/notifications" &&
activeView === BrainView.DEFAULT;

const wavesButtonClasses = `tw-border-none tw-no-underline tw-flex tw-justify-center tw-items-center tw-px-3 tw-py-2 tw-gap-2 tw-flex-1 tw-h-9 tw-rounded-lg ${
activeView === BrainView.WAVES ? "tw-bg-iron-800" : "tw-bg-iron-950"
Expand All @@ -58,14 +62,6 @@ const BrainMobileTabs: React.FC<BrainMobileTabsProps> = ({
activeView === BrainView.ABOUT ? "tw-text-iron-300" : "tw-text-iron-400"
}`;

const leaderboardButtonClasses = `tw-border-none tw-no-underline tw-flex tw-justify-center tw-items-center tw-px-3 tw-py-2 tw-gap-2 tw-flex-1 tw-h-9 tw-rounded-lg ${
activeView === BrainView.LEADERBOARD ? "tw-bg-iron-800" : "tw-bg-iron-950"
}`;

const leaderboardButtonTextClasses = `tw-font-semibold tw-text-xs sm:tw-text-sm tw-whitespace-nowrap ${
activeView === BrainView.LEADERBOARD ? "tw-text-iron-300" : "tw-text-iron-400"
}`;

const myStreamLinkClasses = `tw-no-underline tw-flex tw-justify-center tw-items-center tw-px-3 tw-py-2 tw-gap-2 tw-flex-1 tw-h-9 tw-rounded-md ${
isLinkActive ? "tw-bg-iron-800" : "tw-bg-iron-950"
}`;
Expand Down Expand Up @@ -130,21 +126,18 @@ const BrainMobileTabs: React.FC<BrainMobileTabsProps> = ({
<span className={myStreamTextClasses}>My Stream</span>
</Link>
{isWave() && isRankWave && (
<button
onClick={() => onViewChange(BrainView.LEADERBOARD)}
className={leaderboardButtonClasses}
>
<span className={leaderboardButtonTextClasses}>Leaderboard</span>
</button>
<MyStreamWaveTabsLeaderboard
wave={wave}
activeView={activeView}
onViewChange={onViewChange}
/>
)}
<Link
href="/my-stream/notifications"
onClick={onNotificationsClick}
className={notificationsLinkClasses}
>
<span className={notificationsTextClasses}>
Notifications
</span>
<span className={notificationsTextClasses}>Notifications</span>
{haveUnreadNotifications && (
<span className="tw-size-2 -tw-mt-2 -tw-ml-0.5 tw-bg-red tw-rounded-full"></span>
)}
Expand Down
120 changes: 33 additions & 87 deletions components/brain/my-stream/MyStreamWave.tsx
Original file line number Diff line number Diff line change
@@ -1,98 +1,44 @@
import React, { useMemo, useState } from "react";
import WaveDropsAll from "../../waves/detailed/drops/WaveDropsAll";
import { CreateDropWaveWrapper } from "../../waves/detailed/CreateDropWaveWrapper";
import PrivilegedDropCreator, {
DropMode,
} from "../../waves/detailed/PrivilegedDropCreator";
import { useWaveData } from "../../../hooks/useWaveData";
import useCapacitor from "../../../hooks/useCapacitor";
import { ActiveDropAction, ActiveDropState } from "../../waves/detailed/chat/WaveChat";
import { ApiDrop } from "../../../generated/models/ObjectSerializer";
import React, { useState } from "react";
import { ExtendedDrop } from "../../../helpers/waves/drop.helpers";
import MyStreamWaveChat from "./MyStreamWaveChat";
import MyStreamWaveTabs, { MyStreamWaveTab } from "./MyStreamWaveTabs";
import { useWaveData } from "../../../hooks/useWaveData";
import MyStreamWaveViews from "./MyStreamWaveViews";
import { useWaveState } from "../../../hooks/useWaveState";
import { ApiWaveType } from "../../../generated/models/ObjectSerializer";

interface MyStreamWaveProps {
readonly waveId: string;
readonly onDropClick: (drop: ExtendedDrop) => void;
}

const calculateHeight = (isCapacitor: boolean) => {
if (isCapacitor) {
return "tw-h-[calc(100vh-18.75rem)]";
}
return `tw-h-[calc(100vh-13rem)] lg:tw-h-[calc(100vh-10rem)]`;
};

const MyStreamWave: React.FC<MyStreamWaveProps> = ({ waveId, onDropClick }) => {
const { data: wave } = useWaveData(waveId);
const capacitor = useCapacitor();

const containerClassName = useMemo(() => {
return `tw-w-full tw-flex tw-flex-col tw-rounded-t-xl tw-overflow-hidden ${calculateHeight(
capacitor.isCapacitor
)}`;
}, [capacitor.isCapacitor]);

const [activeDrop, setActiveDrop] = useState<ActiveDropState | null>(null);
const onReply = (drop: ApiDrop, partId: number) => {
setActiveDrop({
action: ActiveDropAction.REPLY,
drop,
partId,
});
};

const onQuote = (drop: ApiDrop, partId: number) => {
setActiveDrop({
action: ActiveDropAction.QUOTE,
drop,
partId,
});
};

const handleReply = ({ drop, partId }: { drop: ApiDrop; partId: number }) => {
onReply(drop, partId);
};

const handleQuote = ({ drop, partId }: { drop: ApiDrop; partId: number }) => {
onQuote(drop, partId);
};

const onCancelReplyQuote = () => {
setActiveDrop(null);
};

if (!wave) {
return null;
}
return (
<div className="tw-relative tw-h-full">
<div className="tw-w-full tw-flex tw-items-stretch lg:tw-divide-x-4 lg:tw-divide-iron-600 lg:tw-divide-solid lg:tw-divide-y-0">
<div className={containerClassName}>
<WaveDropsAll
waveId={waveId}
onReply={handleReply}
onQuote={handleQuote}
activeDrop={activeDrop}
initialDrop={null}
dropId={null}
onDropClick={onDropClick}
/>
<div className="tw-mt-auto">
<CreateDropWaveWrapper>
<PrivilegedDropCreator
activeDrop={activeDrop}
onCancelReplyQuote={onCancelReplyQuote}
onDropAddedToQueue={onCancelReplyQuote}
wave={wave}
dropId={null}
fixedDropMode={DropMode.BOTH}
/>
</CreateDropWaveWrapper>
</div>
</div>
</div>
</div>
);
return <MyStreamWaveChat waveId={waveId} onDropClick={onDropClick} />;
// const [activeTab, setActiveTab] = useState<MyStreamWaveTab>(
// MyStreamWaveTab.CHAT
// );
// const { data: wave } = useWaveData(waveId);
// const isDropsWave = wave?.wave.type !== ApiWaveType.Chat;
// if (!wave) {
// return null;
// }

// return (
// <div>
// {isDropsWave && (
// <MyStreamWaveTabs
// wave={wave}
// activeTab={activeTab}
// setActiveTab={setActiveTab}
// />
// )}
// <MyStreamWaveViews
// wave={wave}
// activeTab={activeTab}
// onDropClick={onDropClick}
// />
// </div>
// );
};

export default MyStreamWave;
104 changes: 104 additions & 0 deletions components/brain/my-stream/MyStreamWaveChat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React, { useMemo, useState } from "react";
import { ExtendedDrop } from "../../../helpers/waves/drop.helpers";
import { useWaveData } from "../../../hooks/useWaveData";
import useCapacitor from "../../../hooks/useCapacitor";
import {
ActiveDropAction,
ActiveDropState,
} from "../../waves/detailed/chat/WaveChat";
import { ApiDrop } from "../../../generated/models/ApiDrop";
import WaveDropsAll from "../../waves/detailed/drops/WaveDropsAll";
import { CreateDropWaveWrapper } from "../../waves/detailed/CreateDropWaveWrapper";
import PrivilegedDropCreator, {
DropMode,
} from "../../waves/detailed/PrivilegedDropCreator";

interface MyStreamWaveChatProps {
readonly waveId: string;
readonly onDropClick: (drop: ExtendedDrop) => void;
}

const calculateHeight = (isCapacitor: boolean) => {
if (isCapacitor) {
return "tw-h-[calc(100vh-18.75rem)]";
}
return `tw-h-[calc(100vh-13rem)] lg:tw-h-[calc(100vh-10rem)]`;
};

const MyStreamWaveChat: React.FC<MyStreamWaveChatProps> = ({
waveId,
onDropClick,
}) => {
const { data: wave } = useWaveData(waveId);
const capacitor = useCapacitor();

const containerClassName = useMemo(() => {
return `tw-w-full tw-flex tw-flex-col tw-rounded-t-xl tw-overflow-hidden ${calculateHeight(
capacitor.isCapacitor
)}`;
}, [capacitor.isCapacitor]);

const [activeDrop, setActiveDrop] = useState<ActiveDropState | null>(null);
const onReply = (drop: ApiDrop, partId: number) => {
setActiveDrop({
action: ActiveDropAction.REPLY,
drop,
partId,
});
};

const onQuote = (drop: ApiDrop, partId: number) => {
setActiveDrop({
action: ActiveDropAction.QUOTE,
drop,
partId,
});
};

const handleReply = ({ drop, partId }: { drop: ApiDrop; partId: number }) => {
onReply(drop, partId);
};

const handleQuote = ({ drop, partId }: { drop: ApiDrop; partId: number }) => {
onQuote(drop, partId);
};

const onCancelReplyQuote = () => {
setActiveDrop(null);
};

if (!wave) {
return null;
}
return (
<div className="tw-relative tw-h-full">
<div className="tw-w-full tw-flex tw-items-stretch lg:tw-divide-x-4 lg:tw-divide-iron-600 lg:tw-divide-solid lg:tw-divide-y-0">
<div className={containerClassName}>
<WaveDropsAll
waveId={waveId}
onReply={handleReply}
onQuote={handleQuote}
activeDrop={activeDrop}
initialDrop={null}
dropId={null}
onDropClick={onDropClick}
/>
<div className="tw-mt-auto">
<CreateDropWaveWrapper>
<PrivilegedDropCreator
activeDrop={activeDrop}
onCancelReplyQuote={onCancelReplyQuote}
onDropAddedToQueue={onCancelReplyQuote}
wave={wave}
dropId={null}
fixedDropMode={DropMode.BOTH}
/>
</CreateDropWaveWrapper>
</div>
</div>
</div>
</div>
);
};

export default MyStreamWaveChat;
43 changes: 43 additions & 0 deletions components/brain/my-stream/MyStreamWaveTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from "react";
import { ApiWave } from "../../../generated/models/ApiWave";
import { useWaveState, WaveVotingState } from "../../../hooks/useWaveState";
import { TabToggle } from "../../common/TabToggle";

interface MyStreamWaveTabsProps {
readonly wave: ApiWave;
readonly activeTab: MyStreamWaveTab;
readonly setActiveTab: (tab: MyStreamWaveTab) => void;
}

export enum MyStreamWaveTab {
CHAT = "CHAT",
LEADERBOARD = "LEADERBOARD",
OUTCOME = "OUTCOME",
}

export const MyStreamWaveTabs: React.FC<MyStreamWaveTabsProps> = ({
activeTab,
setActiveTab,
wave,
}) => {
const { votingState } = useWaveState(wave);
const options = [
{ key: MyStreamWaveTab.CHAT, label: "Chat" },
{
key: MyStreamWaveTab.LEADERBOARD,
label: votingState === WaveVotingState.ENDED ? "Winners" : "Leaderboard",
},
{ key: MyStreamWaveTab.OUTCOME, label: "Outcome" },
] as const;
return (
<div className="tw-flex tw-items-center tw-gap-4 tw-justify-between tw-w-full">
<TabToggle
options={options}
activeKey={activeTab}
onSelect={(key) => setActiveTab(key as MyStreamWaveTab)}
/>
</div>
);
};

export default MyStreamWaveTabs;
Loading
Loading