Skip to content
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
87 changes: 30 additions & 57 deletions components/waves/drop/MemesSingleWaveDropInfoPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,57 +18,32 @@ import WaveDropDeleteButton from "@/components/utils/button/WaveDropDeleteButton
import { ImageScale } from "@/helpers/image.helpers";
import Download from "@/components/download/Download";
import { getFileInfoFromUrl } from "@/helpers/file.helpers";
import { ApiWaveOutcomeCredit } from "@/generated/models/ApiWaveOutcomeCredit";
import { ApiWaveOutcomeType } from "@/generated/models/ApiWaveOutcomeType";
import { VotingModal, MobileVotingModal } from "@/components/voting";
import useIsMobileScreen from "@/hooks/isMobileScreen";
import { WaveDropVoteSummary } from "./WaveDropVoteSummary";
import { WaveDropMetaRow } from "./WaveDropMetaRow";
import { useWaveRankReward } from "@/hooks/waves/useWaveRankReward";

interface MemesSingleWaveDropInfoPanelProps {
readonly drop: ExtendedDrop;
readonly wave: ApiWave | null;
}

const calculateOutcomes = (drop: ExtendedDrop, wave: ApiWave | null) => {
if (!wave || !drop.rank)
return { nicTotal: 0, repTotal: 0, manualOutcomes: [] as string[] };

const rank = drop.rank;
const outcomes = wave.outcomes;

const nicTotal = outcomes
.filter((o) => o.credit === ApiWaveOutcomeCredit.Cic)
.reduce((acc, o) => acc + (o.distribution?.[rank - 1]?.amount ?? 0), 0);

const repTotal = outcomes
.filter((o) => o.credit === ApiWaveOutcomeCredit.Rep)
.reduce((acc, o) => acc + (o.distribution?.[rank - 1]?.amount ?? 0), 0);

const manualOutcomes = outcomes
.filter(
(o) =>
o.type === ApiWaveOutcomeType.Manual &&
o.distribution?.[rank - 1]?.amount
)
.map((o) => o.distribution?.[rank - 1]?.description ?? "");

return { nicTotal, repTotal, manualOutcomes };
};

export const MemesSingleWaveDropInfoPanel = ({
drop,
wave,
}: MemesSingleWaveDropInfoPanelProps) => {
const [isFullscreen, setIsFullscreen] = useState(false);
const [isVotingOpen, setIsVotingOpen] = useState(false);
const isMobileScreen = useIsMobileScreen();
const { isWinner, canDelete, canShowVote, isVotingEnded } = useDropInteractionRules(drop);
const { isWinner, canDelete, canShowVote, isVotingEnded } =
useDropInteractionRules(drop);

const { nicTotal, repTotal, manualOutcomes } = useMemo(
() => calculateOutcomes(drop, wave),
[drop, wave]
);
const { nicTotal, repTotal, manualOutcomes } = useWaveRankReward({
waveId: drop.wave.id,
rank: drop.rank,
enabled: true,
});

const title = useMemo(
() =>
Expand Down Expand Up @@ -115,11 +90,11 @@ export const MemesSingleWaveDropInfoPanel = ({
return (
<>
<div className="tw-w-full">
<div className="tw-w-full tw-min-h-screen tw-flex tw-flex-col">
<div className="tw-flex-1 tw-flex tw-items-center tw-justify-center tw-px-4 sm:tw-px-6 xl:tw-px-20 tw-py-6 lg:tw-py-8">
<div className="tw-flex tw-min-h-screen tw-w-full tw-flex-col">
<div className="tw-flex tw-flex-1 tw-items-center tw-justify-center tw-px-4 tw-py-6 sm:tw-px-6 lg:tw-py-8 xl:tw-px-20">
{artworkMedia && (
<div className="tw-w-full md:tw-max-w-4xl tw-mx-auto tw-flex tw-items-center tw-justify-center">
<div className="tw-relative tw-w-full tw-h-[60vh] md:tw-h-[80vh] lg:tw-h-[95vh]">
<div className="tw-mx-auto tw-flex tw-w-full tw-items-center tw-justify-center md:tw-max-w-4xl">
<div className="tw-relative tw-h-[60vh] tw-w-full md:tw-h-[80vh] lg:tw-h-[95vh]">
<DropListItemContentMedia
media_mime_type={artworkMedia.mime_type}
media_url={artworkMedia.url}
Expand All @@ -131,9 +106,9 @@ export const MemesSingleWaveDropInfoPanel = ({
)}
</div>

<div className="tw-px-4 sm:tw-px-6 xl:tw-px-20 tw-mt-4 md:tw-mt-6">
<div className="tw-max-w-3xl tw-mx-auto tw-w-full">
<div className="tw-flex tw-justify-center tw-mb-8">
<div className="tw-mt-4 tw-px-4 sm:tw-px-6 md:tw-mt-6 xl:tw-px-20">
<div className="tw-mx-auto tw-w-full tw-max-w-3xl">
<div className="tw-mb-8 tw-flex tw-justify-center">
<WaveDropVoteSummary
drop={drop}
isWinner={isWinner}
Expand All @@ -145,11 +120,11 @@ export const MemesSingleWaveDropInfoPanel = ({
</div>

<div className="tw-mb-6">
<h1 className="tw-text-lg sm:tw-text-2xl tw-font-bold tw-text-white tw-mb-4 tw-tracking-tight">
<h1 className="tw-mb-4 tw-text-lg tw-font-bold tw-tracking-tight tw-text-white sm:tw-text-2xl">
{title}
</h1>
{description && (
<p className="tw-text-sm lg:tw-text-md tw-text-white/60 tw-mb-0">
<p className="tw-mb-0 tw-text-sm tw-text-white/60 lg:tw-text-md">
{description}
</p>
)}
Expand All @@ -174,7 +149,7 @@ export const MemesSingleWaveDropInfoPanel = ({
<span className="tw-text-white/40">·</span>
<FontAwesomeIcon
icon={faAddressCard}
className="tw-w-4 tw-h-4 tw-text-white/40"
className="tw-h-4 tw-w-4 tw-text-white/40"
/>
<span className="tw-text-sm tw-text-white/60">
{nicTotal} NIC
Expand All @@ -186,7 +161,7 @@ export const MemesSingleWaveDropInfoPanel = ({
<span className="tw-text-white/40">·</span>
<FontAwesomeIcon
icon={faStar}
className="tw-w-4 tw-h-4 tw-text-white/40"
className="tw-h-4 tw-w-4 tw-text-white/40"
/>
<span className="tw-text-sm tw-text-white/60">
{repTotal} Rep
Expand All @@ -198,16 +173,16 @@ export const MemesSingleWaveDropInfoPanel = ({
</div>
</div>

<div className="tw-w-full tw-h-px tw-bg-white/10 tw-my-8 md:tw-my-10"></div>
<div className="tw-my-8 tw-h-px tw-w-full tw-bg-white/10 md:tw-my-10"></div>

<div className="tw-px-4 sm:tw-px-6 xl:tw-px-20 tw-pb-8 md:tw-pb-10">
<div className="tw-max-w-3xl tw-mx-auto tw-space-y-8">
<div className="tw-px-4 tw-pb-8 sm:tw-px-6 md:tw-pb-10 xl:tw-px-20">
<div className="tw-mx-auto tw-max-w-3xl tw-space-y-8">
<SingleWaveDropTraits drop={drop} />

<SingleWaveDropInfoDetails drop={drop} />

{artworkMedia && fileInfo && (
<div className="tw-flex tw-gap-x-3 tw-items-center">
<div className="tw-flex tw-items-center tw-gap-x-3">
<span className="tw-text-xs tw-font-medium tw-text-iron-600">
Media Type:{" "}
<span className="tw-text-iron-400">
Expand Down Expand Up @@ -238,9 +213,9 @@ export const MemesSingleWaveDropInfoPanel = ({
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.3 }}
className="tw-fixed tw-inset-0 tw-z-50 tw-bg-iron-950/90 tw-flex tw-flex-col tw-items-center tw-justify-center tw-p-4"
className="tw-fixed tw-inset-0 tw-z-50 tw-flex tw-flex-col tw-items-center tw-justify-center tw-bg-iron-950/90 tw-p-4"
>
<div className="tw-w-full tw-max-w-5xl tw-flex tw-justify-between tw-items-center tw-mb-4">
<div className="tw-mb-4 tw-flex tw-w-full tw-max-w-5xl tw-items-center tw-justify-between">
<div className="tw-flex tw-flex-col">
<div className="tw-flex tw-items-center tw-gap-x-3">
<SingleWaveDropPosition rank={drop.rank ?? 1} drop={drop} />
Expand All @@ -249,7 +224,7 @@ export const MemesSingleWaveDropInfoPanel = ({
</h3>
</div>
{description && (
<p className="tw-text-iron-400 tw-text-md tw-mt-1 tw-ml-10">
<p className="tw-ml-10 tw-mt-1 tw-text-md tw-text-iron-400">
{description}
</p>
)}
Expand All @@ -261,20 +236,18 @@ export const MemesSingleWaveDropInfoPanel = ({

<button
onClick={toggleFullscreen}
className="tw-bg-iron-900/80 tw-text-iron-100 tw-p-3 tw-rounded-lg
tw-transition-colors tw-duration-200 hover:tw-bg-iron-800
focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-primary-400"
className="tw-rounded-lg tw-bg-iron-900/80 tw-p-3 tw-text-iron-100 tw-transition-colors tw-duration-200 hover:tw-bg-iron-800 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-primary-400"
aria-label="Exit fullscreen view"
>
<FontAwesomeIcon icon={faCompress} className="tw-w-5 tw-h-5" />
<FontAwesomeIcon icon={faCompress} className="tw-h-5 tw-w-5" />
</button>
</div>

<div className="tw-w-full tw-h-full tw-flex tw-items-center tw-justify-center">
<div className="tw-flex tw-h-full tw-w-full tw-items-center tw-justify-center">
<img
src={artworkMedia.url}
alt={title}
className="tw-max-w-full tw-max-h-full tw-object-contain"
className="tw-max-h-full tw-max-w-full tw-object-contain"
/>
</div>
</motion.div>
Expand Down
34 changes: 16 additions & 18 deletions components/waves/winners/DefaultWaveWinnerDropSmall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import { memo, useCallback } from "react";
import { ExtendedDrop } from "@/helpers/waves/drop.helpers";
import { ApiWave } from "@/generated/models/ApiWave";
import Link from "next/link";
import { formatNumberWithCommas } from "@/helpers/Helpers";
import { getScaledImageUri, ImageScale } from "@/helpers/image.helpers";
Expand All @@ -17,12 +16,11 @@ import { ApiWaveCreditType } from "@/generated/models/ApiWaveCreditType";
interface DefaultWaveWinnerDropSmallProps {
readonly drop: ExtendedDrop;
readonly onDropClick: (drop: ExtendedDrop) => void;
readonly wave: ApiWave;
readonly rank?: number | undefined; // For explicitly setting rank from decision winners
}

export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(
({ drop, onDropClick, wave, rank }) => {
({ drop, onDropClick, rank }) => {
// Use provided rank or fall back to drop.rank
const effectiveRank = rank ?? drop.rank;

Expand Down Expand Up @@ -63,10 +61,10 @@ export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(
return (
<div
onClick={handleDropClick}
className="tw-w-full tw-text-left tw-cursor-pointer tw-group tw-rounded-xl tw-overflow-hidden"
className="tw-group tw-w-full tw-cursor-pointer tw-overflow-hidden tw-rounded-xl tw-text-left"
>
<div className="tw-rounded-xl tw-bg-iron-900 tw-p-4 tw-relative desktop-hover:hover:tw-bg-iron-800/80 tw-transition-all tw-duration-300 tw-ease-out">
<div className="tw-flex tw-flex-col tw-relative">
<div className="tw-relative tw-rounded-xl tw-bg-iron-900 tw-p-4 tw-transition-all tw-duration-300 tw-ease-out desktop-hover:hover:tw-bg-iron-800/80">
<div className="tw-relative tw-flex tw-flex-col">
<div className="tw-flex tw-items-start tw-justify-between tw-gap-x-4">
<div className="tw-flex tw-items-center tw-gap-x-3">
{effectiveRank && (
Expand All @@ -80,7 +78,7 @@ export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(
)}
</div>

<div className="tw-flex tw-justify-end tw-items-center tw-gap-x-3 tw-flex-wrap">
<div className="tw-flex tw-flex-wrap tw-items-center tw-justify-end tw-gap-x-3">
<div className="tw-flex tw-items-center tw-gap-x-1.5">
<span
className={`tw-text-sm tw-font-semibold ${ratingStyle}`}
Expand All @@ -102,7 +100,7 @@ export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(

{hasUserVoted && (
<div className="tw-flex tw-items-center tw-gap-x-1.5 tw-whitespace-nowrap">
<span className="tw-text-iron-400 tw-text-sm">You:</span>
<span className="tw-text-sm tw-text-iron-400">You:</span>
<span
className={`tw-text-sm tw-font-medium ${userVoteStyle}`}
>
Expand All @@ -114,11 +112,11 @@ export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(
</div>
</div>

<div className="tw-flex tw-items-center tw-gap-x-3 tw-mt-4">
<div className="tw-mt-4 tw-flex tw-items-center tw-gap-x-3">
<Link
href={`/${drop.author.handle}`}
onClick={(e) => e.stopPropagation()}
className="tw-block tw-flex-shrink-0 desktop-hover:group-hover:tw-opacity-90 tw-transition-opacity"
className="tw-block tw-flex-shrink-0 tw-transition-opacity desktop-hover:group-hover:tw-opacity-90"
>
{drop.author.pfp ? (
<img
Expand All @@ -127,10 +125,10 @@ export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(
ImageScale.W_AUTO_H_50
)}
alt={`${drop.author.handle}'s profile`}
className="tw-size-7 tw-rounded-lg tw-ring-1 tw-ring-white/10 tw-object-cover"
className="tw-size-7 tw-rounded-lg tw-object-cover tw-ring-1 tw-ring-white/10"
/>
) : (
<div className="tw-size-7 tw-rounded-lg tw-ring-1 tw-ring-white/10 tw-bg-iron-800" />
<div className="tw-size-7 tw-rounded-lg tw-bg-iron-800 tw-ring-1 tw-ring-white/10" />
)}
</Link>

Expand All @@ -141,24 +139,24 @@ export const DefaultWaveWinnerDropSmall = memo<DefaultWaveWinnerDropSmallProps>(
<Link
href={`/${drop.author.handle}`}
onClick={(e) => e.stopPropagation()}
className="tw-no-underline tw-truncate desktop-hover:hover:tw-underline"
className="tw-truncate tw-no-underline desktop-hover:hover:tw-underline"
>
<span className="tw-text-sm tw-font-semibold tw-text-iron-200 desktop-hover:hover:tw-text-iron-100 tw-transition-colors">
<span className="tw-text-sm tw-font-semibold tw-text-iron-200 tw-transition-colors desktop-hover:hover:tw-text-iron-100">
{drop.author.handle}
</span>
</Link>
</UserProfileTooltipWrapper>
<span className="tw-size-[3px] tw-bg-iron-600 tw-rounded-full tw-flex-shrink-0"></span>
<span className="tw-text-xs tw-text-iron-400 tw-flex-shrink-0">
<span className="tw-size-[3px] tw-flex-shrink-0 tw-rounded-full tw-bg-iron-600"></span>
<span className="tw-flex-shrink-0 tw-text-xs tw-text-iron-400">
{Time.millis(drop.created_at).toLocaleDropDateAndTimeString()}
</span>
</div>
</div>

<div className="tw-ml-10">
<DropContentSmall drop={drop} onDropClick={onDropClick} />
<div className="tw-mt-2 tw-relative">
<WaveWinnersSmallOutcome drop={drop} wave={wave} />
<div className="tw-relative tw-mt-2">
<WaveWinnersSmallOutcome drop={drop} />
</div>
</div>
</div>
Expand Down
Loading