mirror of
https://github.com/duckietm/Nitro-V3.git
synced 2026-06-20 07:26:19 +00:00
🆙 Init V3
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
import { AchievementData } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { AchievementUtilities } from '../../api';
|
||||
import { BaseProps, LayoutBadgeImageView } from '../../common';
|
||||
|
||||
interface AchievementBadgeViewProps extends BaseProps<HTMLDivElement>
|
||||
{
|
||||
achievement: AchievementData;
|
||||
scale?: number;
|
||||
}
|
||||
|
||||
export const AchievementBadgeView: FC<AchievementBadgeViewProps> = props =>
|
||||
{
|
||||
const { achievement = null, scale = 1, ...rest } = props;
|
||||
|
||||
if(!achievement) return null;
|
||||
|
||||
return <LayoutBadgeImageView badgeCode={ AchievementUtilities.getAchievementBadgeCode(achievement) } isGrayscale={ !AchievementUtilities.getAchievementHasStarted(achievement) } scale={ scale } { ...rest } />;
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
import { FC, useEffect } from 'react';
|
||||
import { AchievementCategory } from '../../api';
|
||||
import { Column } from '../../common';
|
||||
import { useAchievements } from '../../hooks';
|
||||
import { AchievementDetailsView } from './AchievementDetailsView';
|
||||
import { AchievementListView } from './achievement-list';
|
||||
|
||||
interface AchievementCategoryViewProps {
|
||||
category: AchievementCategory;
|
||||
}
|
||||
|
||||
export const AchievementCategoryView: FC<AchievementCategoryViewProps> = (
|
||||
props,
|
||||
) =>
|
||||
{
|
||||
const { category = null } = props;
|
||||
const { selectedAchievement = null, setSelectedAchievementId = null } =
|
||||
useAchievements();
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
if(!category) return;
|
||||
|
||||
if(!selectedAchievement)
|
||||
{
|
||||
setSelectedAchievementId(
|
||||
category?.achievements?.[0]?.achievementId,
|
||||
);
|
||||
}
|
||||
}, [category, selectedAchievement, setSelectedAchievementId]);
|
||||
|
||||
if(!category) return null;
|
||||
|
||||
return (
|
||||
<Column fullHeight justifyContent="between">
|
||||
<AchievementListView achievements={category.achievements} />
|
||||
{!!selectedAchievement && (
|
||||
<AchievementDetailsView achievement={selectedAchievement} />
|
||||
)}
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import { AchievementData } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { AchievementUtilities, LocalizeBadgeDescription, LocalizeBadgeName, LocalizeText } from '../../api';
|
||||
import { Column, Flex, LayoutCurrencyIcon, LayoutProgressBar, Text } from '../../common';
|
||||
import { AchievementBadgeView } from './AchievementBadgeView';
|
||||
|
||||
interface AchievementDetailsViewProps
|
||||
{
|
||||
achievement: AchievementData;
|
||||
}
|
||||
|
||||
export const AchievementDetailsView: FC<AchievementDetailsViewProps> = props =>
|
||||
{
|
||||
const { achievement = null } = props;
|
||||
|
||||
if(!achievement) return null;
|
||||
|
||||
return (
|
||||
<Flex shrink className="bg-muted rounded p-2 text-black" gap={ 2 } overflow="hidden">
|
||||
<Column center gap={ 1 }>
|
||||
<AchievementBadgeView achievement={ achievement } className="nitro-achievements-relative w-[40px] h-[40px] bg-no-repeat bg-center" scale={ 2 } />
|
||||
<Text fontWeight="bold">
|
||||
{ LocalizeText('achievements.details.level', [ 'level', 'limit' ], [ AchievementUtilities.getAchievementLevel(achievement).toString(), achievement.levelCount.toString() ]) }
|
||||
</Text>
|
||||
</Column>
|
||||
<Column fullWidth justifyContent="center" overflow="hidden">
|
||||
<div className="flex flex-col gap-1">
|
||||
<Text truncate fontWeight="bold">
|
||||
{ LocalizeBadgeName(AchievementUtilities.getAchievementBadgeCode(achievement)) }
|
||||
</Text>
|
||||
<Text textBreak>
|
||||
{ LocalizeBadgeDescription(AchievementUtilities.getAchievementBadgeCode(achievement)) }
|
||||
</Text>
|
||||
</div>
|
||||
{ ((achievement.levelRewardPoints > 0) || (achievement.scoreLimit > 0)) &&
|
||||
<div className="flex flex-col gap-1">
|
||||
{ (achievement.levelRewardPoints > 0) &&
|
||||
<div className="flex items-center gap-1">
|
||||
<Text truncate className="small">
|
||||
{ LocalizeText('achievements.details.reward') }
|
||||
</Text>
|
||||
<Flex center className="font-bold small" gap={ 1 }>
|
||||
{ achievement.levelRewardPoints }
|
||||
<LayoutCurrencyIcon type={ achievement.levelRewardPointType } />
|
||||
</Flex>
|
||||
</div> }
|
||||
{ (achievement.scoreLimit > 0) &&
|
||||
<LayoutProgressBar maxProgress={ (achievement.scoreLimit + achievement.scoreAtStartOfLevel) } progress={ (achievement.currentPoints + achievement.scoreAtStartOfLevel) } text={ LocalizeText('achievements.details.progress', [ 'progress', 'limit' ], [ (achievement.currentPoints + achievement.scoreAtStartOfLevel).toString(), (achievement.scoreLimit + achievement.scoreAtStartOfLevel).toString() ]) } /> }
|
||||
</div> }
|
||||
</Column>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,143 @@
|
||||
import
|
||||
{
|
||||
AddLinkEventTracker,
|
||||
ILinkEventTracker,
|
||||
RemoveLinkEventTracker,
|
||||
} from '@nitrots/nitro-renderer';
|
||||
import { FC, useEffect, useState } from 'react';
|
||||
import { AchievementUtilities, LocalizeText } from '../../api';
|
||||
import { Column, LayoutImage, LayoutProgressBar, Text } from '../../common';
|
||||
import { useAchievements } from '../../hooks';
|
||||
import { NitroCard } from '../../layout';
|
||||
import { AchievementCategoryView } from './AchievementCategoryView';
|
||||
import { AchievementsCategoryListView } from './category-list';
|
||||
|
||||
export const AchievementsView: FC<{}> = (props) =>
|
||||
{
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
const {
|
||||
achievementCategories = [],
|
||||
selectedCategoryCode = null,
|
||||
setSelectedCategoryCode = null,
|
||||
achievementScore = 0,
|
||||
getProgress = 0,
|
||||
getMaxProgress = 0,
|
||||
selectedCategory = null,
|
||||
} = useAchievements();
|
||||
|
||||
useEffect(() =>
|
||||
{
|
||||
const linkTracker: ILinkEventTracker = {
|
||||
linkReceived: (url: string) =>
|
||||
{
|
||||
const parts = url.split('/');
|
||||
|
||||
if(parts.length < 2) return;
|
||||
|
||||
switch(parts[1])
|
||||
{
|
||||
case 'show':
|
||||
setIsVisible(true);
|
||||
return;
|
||||
case 'hide':
|
||||
setIsVisible(false);
|
||||
return;
|
||||
case 'toggle':
|
||||
setIsVisible((prevValue) => !prevValue);
|
||||
return;
|
||||
}
|
||||
},
|
||||
eventUrlPrefix: 'achievements/',
|
||||
};
|
||||
|
||||
AddLinkEventTracker(linkTracker);
|
||||
|
||||
return () => RemoveLinkEventTracker(linkTracker);
|
||||
}, []);
|
||||
|
||||
if(!isVisible) return null;
|
||||
|
||||
return (
|
||||
<NitroCard className="w-[375px] h-[405px]" uniqueKey="achievements">
|
||||
<NitroCard.Header
|
||||
headerText={LocalizeText('inventory.achievements')}
|
||||
onCloseClick={(event) => setIsVisible(false)}
|
||||
/>
|
||||
{selectedCategory && (
|
||||
<div className="relative flex items-center justify-center gap-3 p-1 cursor-pointer container-fluid bg-muted">
|
||||
<div
|
||||
className="bg-[url('@/assets/images/achievements/back-arrow.png')] bg-center no-repeat w-[33px] h-[34px]"
|
||||
onClick={(event) => setSelectedCategoryCode(null)}
|
||||
/>
|
||||
<Column className="!flex-grow" gap={0}>
|
||||
<Text
|
||||
className="text-small"
|
||||
fontSize={4}
|
||||
fontWeight="bold"
|
||||
>
|
||||
{LocalizeText(
|
||||
`quests.${selectedCategory.code}.name`
|
||||
)}
|
||||
</Text>
|
||||
<Text>
|
||||
{LocalizeText(
|
||||
'achievements.details.categoryprogress',
|
||||
['progress', 'limit'],
|
||||
[
|
||||
selectedCategory.getProgress().toString(),
|
||||
selectedCategory
|
||||
.getMaxProgress()
|
||||
.toString(),
|
||||
]
|
||||
)}
|
||||
</Text>
|
||||
</Column>
|
||||
<LayoutImage
|
||||
imageUrl={AchievementUtilities.getAchievementCategoryImageUrl(
|
||||
selectedCategory,
|
||||
null,
|
||||
true
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<NitroCard.Content>
|
||||
{!selectedCategory && (
|
||||
<>
|
||||
<AchievementsCategoryListView
|
||||
categories={achievementCategories}
|
||||
selectedCategoryCode={selectedCategoryCode}
|
||||
setSelectedCategoryCode={setSelectedCategoryCode}
|
||||
/>
|
||||
<div
|
||||
className="flex flex-col justify-end flex-grow gap-1"
|
||||
>
|
||||
<Text center small>
|
||||
{LocalizeText(
|
||||
'achievements.categories.score',
|
||||
['score'],
|
||||
[achievementScore.toString()]
|
||||
)}
|
||||
</Text>
|
||||
<LayoutProgressBar
|
||||
maxProgress={getMaxProgress}
|
||||
progress={getProgress}
|
||||
text={LocalizeText(
|
||||
'achievements.categories.totalprogress',
|
||||
['progress', 'limit'],
|
||||
[
|
||||
getProgress.toString(),
|
||||
getMaxProgress.toString(),
|
||||
]
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{selectedCategory && (
|
||||
<AchievementCategoryView category={selectedCategory} />
|
||||
)}
|
||||
</NitroCard.Content>
|
||||
</NitroCard>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
import { AchievementData } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { LayoutGridItem } from '../../../common';
|
||||
import { useAchievements } from '../../../hooks';
|
||||
import { AchievementBadgeView } from '../AchievementBadgeView';
|
||||
|
||||
interface AchievementListItemViewProps
|
||||
{
|
||||
achievement: AchievementData;
|
||||
}
|
||||
|
||||
export const AchievementListItemView: FC<AchievementListItemViewProps> = props =>
|
||||
{
|
||||
const { achievement = null } = props;
|
||||
const { selectedAchievement = null, setSelectedAchievementId = null } = useAchievements();
|
||||
|
||||
if(!achievement) return null;
|
||||
|
||||
return (
|
||||
<LayoutGridItem itemActive={ (selectedAchievement === achievement) } itemUnseen={ (achievement.unseen > 0) } onClick={ event => setSelectedAchievementId(achievement.achievementId) }>
|
||||
<AchievementBadgeView achievement={ achievement } />
|
||||
</LayoutGridItem>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import { AchievementData } from '@nitrots/nitro-renderer';
|
||||
import { FC } from 'react';
|
||||
import { AutoGrid } from '../../../common';
|
||||
import { AchievementListItemView } from './AchievementListItemView';
|
||||
|
||||
interface AchievementListViewProps
|
||||
{
|
||||
achievements: AchievementData[];
|
||||
}
|
||||
|
||||
export const AchievementListView: FC<AchievementListViewProps> = props =>
|
||||
{
|
||||
const { achievements = null } = props;
|
||||
|
||||
return (
|
||||
<AutoGrid columnCount={ 6 } columnMinHeight={ 50 } columnMinWidth={ 50 }>
|
||||
{ achievements && (achievements.length > 0) && achievements.map((achievement, index) => <AchievementListItemView key={ index } achievement={ achievement } />) }
|
||||
</AutoGrid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './AchievementListItemView';
|
||||
export * from './AchievementListView';
|
||||
@@ -0,0 +1,31 @@
|
||||
import { Dispatch, FC, SetStateAction } from 'react';
|
||||
import { AchievementUtilities, IAchievementCategory, LocalizeText } from '../../../api';
|
||||
import { LayoutBackgroundImage, LayoutGridItem, Text } from '../../../common';
|
||||
|
||||
interface AchievementCategoryListItemViewProps
|
||||
{
|
||||
category: IAchievementCategory;
|
||||
selectedCategoryCode: string;
|
||||
setSelectedCategoryCode: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export const AchievementsCategoryListItemView: FC<AchievementCategoryListItemViewProps> = props =>
|
||||
{
|
||||
const { category = null, selectedCategoryCode = null, setSelectedCategoryCode = null } = props;
|
||||
|
||||
if(!category) return null;
|
||||
|
||||
const progress = AchievementUtilities.getAchievementCategoryProgress(category);
|
||||
const maxProgress = AchievementUtilities.getAchievementCategoryMaxProgress(category);
|
||||
const getCategoryImage = AchievementUtilities.getAchievementCategoryImageUrl(category, progress);
|
||||
const getTotalUnseen = AchievementUtilities.getAchievementCategoryTotalUnseen(category);
|
||||
|
||||
return (
|
||||
<LayoutGridItem gap={ 1 } itemActive={ (selectedCategoryCode === category.code) } itemCount={ getTotalUnseen } itemCountMinimum={ 0 } onClick={ event => setSelectedCategoryCode(category.code) }>
|
||||
<Text center fullWidth small className="pt-1">{ LocalizeText(`quests.${ category.code }.name`) }</Text>
|
||||
<LayoutBackgroundImage imageUrl={ getCategoryImage } position="relative">
|
||||
<Text center fullWidth position="absolute" style={ { fontSize: 12, bottom: 9 } } variant="white">{ progress } / { maxProgress }</Text>
|
||||
</LayoutBackgroundImage>
|
||||
</LayoutGridItem>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Dispatch, FC, SetStateAction } from 'react';
|
||||
import { IAchievementCategory } from '../../../api';
|
||||
import { AutoGrid } from '../../../common';
|
||||
import { AchievementsCategoryListItemView } from './AchievementsCategoryListItemView';
|
||||
|
||||
interface AchievementsCategoryListViewProps
|
||||
{
|
||||
categories: IAchievementCategory[];
|
||||
selectedCategoryCode: string;
|
||||
setSelectedCategoryCode: Dispatch<SetStateAction<string>>;
|
||||
}
|
||||
|
||||
export const AchievementsCategoryListView: FC<AchievementsCategoryListViewProps> = props =>
|
||||
{
|
||||
const { categories = null, selectedCategoryCode = null, setSelectedCategoryCode = null } = props;
|
||||
|
||||
return (
|
||||
<AutoGrid columnCount={ 3 } columnMinHeight={ 100 } columnMinWidth={ 90 }>
|
||||
{ categories && (categories.length > 0) && categories.map((category, index) => <AchievementsCategoryListItemView key={ index } category={ category } selectedCategoryCode={ selectedCategoryCode } setSelectedCategoryCode={ setSelectedCategoryCode } />) }
|
||||
</AutoGrid>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './AchievementsCategoryListItemView';
|
||||
export * from './AchievementsCategoryListView';
|
||||
@@ -0,0 +1,6 @@
|
||||
export * from './AchievementBadgeView';
|
||||
export * from './AchievementCategoryView';
|
||||
export * from './AchievementDetailsView';
|
||||
export * from './AchievementsView';
|
||||
export * from './achievement-list';
|
||||
export * from './category-list';
|
||||
Reference in New Issue
Block a user