@@ -116,23 +106,23 @@ const Stats = () => {
{
title={variables.getMessage(`${STATS_SECTION}.sections.addons_installed`)}
value={stats.marketplace?.install?.length || 0}
/>
+
+
+
-
- {variables.getMessage(`${STATS_SECTION}.achievements`)}
-
-
- {variables.getMessage(`${STATS_SECTION}.unlocked`, {
- count: `${getUnlockedCount}/${achievements.length}`,
- })}
-
-
-
-
- {achievements.map((achievement, index) => {
- if (achievement.achieved) {
- return (
-
- );
- }
- })}
-
-
{variables.getMessage(`${STATS_SECTION}.locked`)}
-
-
- {achievements.map((achievement, index) => {
- if (!achievement.achieved) {
- return (
-
- );
- }
- })}
-
-
-
>
);
diff --git a/src/features/stats/options/sections/Achievements.jsx b/src/features/stats/options/sections/Achievements.jsx
new file mode 100644
index 00000000..93ac384d
--- /dev/null
+++ b/src/features/stats/options/sections/Achievements.jsx
@@ -0,0 +1,110 @@
+import React, { useState } from 'react';
+import { FaTrophy } from 'react-icons/fa';
+import { MdAccessTime, MdLock } from 'react-icons/md';
+import { PreferencesWrapper } from 'components/Layout/Settings';
+import { getLocalisedAchievementData } from 'features/stats/api/achievements';
+import { motion } from 'framer-motion';
+import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
+
+const AchievementElement = ({ achievementKey, id, achieved, timestamp }) => {
+ if (!id) {
+ return null; // Ensure id is not undefined
+ }
+
+ const { name, description } = getLocalisedAchievementData(id);
+
+ return (
+
+ {achieved ? (
+
+ ) : (
+
+ )}
+
+ {achieved && timestamp && (
+
+ {new Date(timestamp).toLocaleDateString()}
+
+ )}
+ {name}
+ {achieved ? description : '?????'}
+
+
+ );
+};
+
+const Achievements = ({ achievements, getUnlockedCount, STATS_SECTION, variables }) => {
+ const [showLocked, setShowLocked] = useState(false);
+
+ const toggleLocked = () => {
+ setShowLocked(!showLocked);
+ };
+
+ return (
+
+
+
+ {variables.getMessage(`${STATS_SECTION}.achievements`)}
+
+
+ {variables.getMessage(`${STATS_SECTION}.unlocked`, {
+ count: `${getUnlockedCount}/${achievements.length}`,
+ })}
+
+
+
+
+ {achievements.map((achievement, index) => {
+ if (achievement.achieved) {
+ return (
+
+ );
+ }
+ return null; // Ensure a value is returned
+ })}
+
+
+
+ {variables.getMessage(`${STATS_SECTION}.locked`)}
+
+
+ {showLocked ? : }
+
+
+
+
+ {achievements.map((achievement, index) => {
+ if (!achievement.achieved) {
+ return (
+
+ );
+ }
+ return null; // Ensure a value is returned
+ })}
+
+
+
+
+ );
+};
+
+export default Achievements;
diff --git a/src/features/stats/options/sections/StatsOverview.jsx b/src/features/stats/options/sections/StatsOverview.jsx
new file mode 100644
index 00000000..7d3d8ce2
--- /dev/null
+++ b/src/features/stats/options/sections/StatsOverview.jsx
@@ -0,0 +1,57 @@
+const StatsOverview = ({ stats }) => {
+ const xpPercentage = Math.floor((stats.xp / stats.nextLevelXp) * 100);
+
+ const ProgressCircle = ({ percentage }) => {
+ const circleRadius = 50;
+ const circleCircumference = 2 * Math.PI * circleRadius;
+ const progress = circleCircumference - (percentage / 100) * circleCircumference;
+
+ return (
+
+
+ {percentage}%
+
+ );
+ };
+
+ return (
+
+
+
+
+ Level {stats.level || 1}
+ {`${Math.round(stats.nextLevelXp - stats.xp) || 0} XP until next level`}
+
+
+
+
+ Streak
+ {`${stats.streak?.current || 0} ${stats.streak?.current === 1 ? 'day' : 'days'}`}
+
+
+
+ );
+};
+
+export { StatsOverview as default, StatsOverview };