Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const defaultProfileAchievementsHook = {
achievements: [mockTrackedAchievement],
unlockedCount: 0,
totalCount: 1,
totalPoints: 0,
totalRewardValue: 0,
isPending: false,
isError: false,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import {
} from '../typography/Typography';
import { Checkbox } from '../fields/Checkbox';
import { getTargetCount } from '../../graphql/user/achievements';
import { formatAchievementReward } from '../../lib/achievements';
import { useAchievementRewardDisplay } from '../../hooks/useAchievementRewardDisplay';
import { sortLockedAchievements } from './achievement/sortAchievements';

const SPARKLE_DURATION_MS = 4500;
Expand Down Expand Up @@ -54,6 +56,7 @@ export const AchievementCompletionModal = ({
const { trackedAchievement, trackAchievement } = useTrackedAchievement(
user?.id,
);
const { showAchievementXp } = useAchievementRewardDisplay();

const isOptedOut = checkHasCompleted(ActionType.DisableAchievementCompletion);

Expand All @@ -80,8 +83,10 @@ export const AchievementCompletionModal = ({
);

const lockedAchievements = useMemo(() => {
return achievements ? sortLockedAchievements(achievements) : [];
}, [achievements]);
return achievements
? sortLockedAchievements(achievements, showAchievementXp)
: [];
}, [achievements, showAchievementXp]);

useEffect(() => {
if (!showSparkles) {
Expand Down Expand Up @@ -209,7 +214,10 @@ export const AchievementCompletionModal = ({
{unlockedAchievement.achievement.description}
</Typography>
<div className="text-text-invert rounded-14 bg-accent-cabbage-default px-3 py-1 font-bold typo-subhead">
+{unlockedAchievement.achievement.points} points
{formatAchievementReward(unlockedAchievement.achievement, {
showAchievementXp,
signed: true,
})}
</div>
</div>

Expand Down Expand Up @@ -353,7 +361,13 @@ export const AchievementCompletionModal = ({
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
{userAchievement.achievement.points} pts
{formatAchievementReward(
userAchievement.achievement,
{
showAchievementXp,
short: !showAchievementXp,
},
)}
</Typography>
</div>
<div className="rounded-sm mt-1 h-1.5 w-full overflow-hidden bg-accent-pepper-subtler">
Expand Down
12 changes: 9 additions & 3 deletions packages/shared/src/components/modals/AchievementPickerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ import type { UserAchievement } from '../../graphql/user/achievements';
import { getTargetCount } from '../../graphql/user/achievements';
import { sortLockedAchievements } from './achievement/sortAchievements';
import { useLogContext } from '../../contexts/LogContext';
import { formatAchievementReward } from '../../lib/achievements';
import { LogEvent, TargetType } from '../../lib/log';
import { useAchievementRewardDisplay } from '../../hooks/useAchievementRewardDisplay';

export interface AchievementPickerModalProps extends ModalProps {
achievements: UserAchievement[];
Expand All @@ -36,10 +38,11 @@ export const AchievementPickerModal = ({
const [isTracking, setIsTracking] = useState(false);
const [isUntracking, setIsUntracking] = useState(false);
const { logEvent } = useLogContext();
const { showAchievementXp } = useAchievementRewardDisplay();

const lockedAchievements = useMemo(() => {
return sortLockedAchievements(achievements);
}, [achievements]);
return sortLockedAchievements(achievements, showAchievementXp);
}, [achievements, showAchievementXp]);

const handleTrack = async (achievementId: string) => {
setIsTracking(true);
Expand Down Expand Up @@ -165,7 +168,10 @@ export const AchievementPickerModal = ({
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
{userAchievement.achievement.points} pts
{formatAchievementReward(userAchievement.achievement, {
showAchievementXp,
short: !showAchievementXp,
})}
</Typography>
</div>
<ProgressBar
Expand Down
18 changes: 15 additions & 3 deletions packages/shared/src/components/modals/AchievementShowcaseModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import type { PublicProfile } from '../../lib/user';
import { useShowcaseAchievements } from '../../hooks/profile/useShowcaseAchievements';
import { useProfileAchievements } from '../../hooks/profile/useProfileAchievements';
import { useToastNotification } from '../../hooks/useToastNotification';
import {
formatAchievementReward,
getAchievementRewardValue,
} from '../../lib/achievements';
import { useAchievementRewardDisplay } from '../../hooks/useAchievementRewardDisplay';

const MAX_SHOWCASE = 5;

Expand All @@ -33,6 +38,7 @@ export const AchievementShowcaseModal = ({
useShowcaseAchievements(user);
const { achievements } = useProfileAchievements(user);
const { displayToast } = useToastNotification();
const { showAchievementXp } = useAchievementRewardDisplay();

const initialSelectedIds = useMemo(
() => showcaseAchievements.map((sa) => sa.achievement.id),
Expand All @@ -54,9 +60,12 @@ export const AchievementShowcaseModal = ({
if (aSelected !== bSelected) {
return aSelected ? -1 : 1;
}
return b.achievement.points - a.achievement.points;
return (
getAchievementRewardValue(b.achievement, showAchievementXp) -
getAchievementRewardValue(a.achievement, showAchievementXp)
);
});
}, [unlockedAchievements, initialSelectedIds]);
}, [initialSelectedIds, showAchievementXp, unlockedAchievements]);

const toggleSelection = (achievementId: string) => {
setSelectedIds((prev) => {
Expand Down Expand Up @@ -168,7 +177,10 @@ export const AchievementShowcaseModal = ({
type={TypographyType.Footnote}
color={TypographyColor.Tertiary}
>
{userAchievement.achievement.points} pts
{formatAchievementReward(userAchievement.achievement, {
showAchievementXp,
short: !showAchievementXp,
})}
</Typography>
<div
className={classNames(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ import { useAuthContext } from '../../../contexts/AuthContext';
import { useProfileAchievements } from '../../../hooks/profile/useProfileAchievements';
import type { UserAchievement } from '../../../graphql/user/achievements';
import { getTargetCount } from '../../../graphql/user/achievements';
import {
formatAchievementReward,
getAchievementRewardValue,
} from '../../../lib/achievements';
import { formatDate, TimeFormatType } from '../../../lib/dateFormat';
import type { PublicProfile } from '../../../lib/user';
import { useAchievementRewardDisplay } from '../../../hooks/useAchievementRewardDisplay';

interface CompareAchievementsModalProps extends ModalProps {
profileUser: PublicProfile;
Expand All @@ -28,12 +33,13 @@ interface CompareAchievementsModalProps extends ModalProps {
/**
* Sorts achievements by the logged user's unlock status, matching AchievementsList:
* 1. Unlocked first
* 2. Among unlocked: rarest first, then highest points
* 2. Among unlocked: rarest first, then highest reward value
* 3. Among locked: highest progress ratio first
*/
const sortByMyStatus = (
achievements: UserAchievement[],
myMap: Map<string, UserAchievement>,
showAchievementXp: boolean,
): UserAchievement[] => {
return [...achievements].sort((a, b) => {
const myA = myMap.get(a.achievement.id);
Expand All @@ -54,7 +60,10 @@ const sortByMyStatus = (
if (rarityA !== rarityB) {
return rarityA - rarityB;
}
return b.achievement.points - a.achievement.points;
return (
getAchievementRewardValue(b.achievement, showAchievementXp) -
getAchievementRewardValue(a.achievement, showAchievementXp)
);
}

const targetA = getTargetCount(a.achievement);
Expand All @@ -75,6 +84,7 @@ export const CompareAchievementsModal = ({
const { user: loggedUser } = useAuthContext();
const { achievements: myAchievements, isPending } =
useProfileAchievements(loggedUser);
const { showAchievementXp } = useAchievementRewardDisplay();

const { sorted, myMap, theirMap } = useMemo(() => {
const empty = {
Expand Down Expand Up @@ -106,14 +116,17 @@ export const CompareAchievementsModal = ({
);

return {
sorted: sortByMyStatus(allAchievements, my),
sorted: sortByMyStatus(allAchievements, my, showAchievementXp),
myMap: my,
theirMap: theirs,
};
}, [myAchievements, profileAchievements]);
}, [myAchievements, profileAchievements, showAchievementXp]);

const handleClose = (event?: React.MouseEvent | React.KeyboardEvent): void =>
const handleClose = (
event: React.MouseEvent | React.KeyboardEvent,
): void => {
onRequestClose?.(event);
};

return (
<Modal
Expand All @@ -127,7 +140,10 @@ export const CompareAchievementsModal = ({
<Modal.Body className="flex flex-col gap-4">
<div className="flex items-center justify-between px-2">
<div className="flex flex-col items-center gap-1">
<ProfilePicture user={loggedUser} size={ProfileImageSize.Large} />
<ProfilePicture
user={loggedUser ?? { id: 'current-user', image: '' }}
size={ProfileImageSize.Large}
/>
<Typography
type={TypographyType.Callout}
bold
Expand Down Expand Up @@ -211,7 +227,10 @@ export const CompareAchievementsModal = ({
bold
className="shrink-0"
>
{ua.achievement.points} pts
{formatAchievementReward(ua.achievement, {
showAchievementXp,
short: !showAchievementXp,
})}
</Typography>
</div>
<Typography
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { UserAchievement } from '../../../graphql/user/achievements';
import { getTargetCount } from '../../../graphql/user/achievements';
import { getAchievementRewardValue } from '../../../lib/achievements';

const getProgressRatio = (achievement: UserAchievement): number => {
const targetCount = getTargetCount(achievement.achievement);
Expand All @@ -13,6 +14,7 @@ const getProgressRatio = (achievement: UserAchievement): number => {

export const sortLockedAchievements = (
achievements: UserAchievement[],
showAchievementXp = false,
): UserAchievement[] => {
return achievements
.filter((achievement) => !achievement.unlockedAt)
Expand All @@ -26,6 +28,9 @@ export const sortLockedAchievements = (
return b.progress - a.progress;
}

return b.achievement.points - a.achievement.points;
return (
getAchievementRewardValue(b.achievement, showAchievementXp) -
getAchievementRewardValue(a.achievement, showAchievementXp)
);
});
};
Loading
Loading