diff --git a/src/components/data-table/index.js b/src/components/data-table/index.js
index 8ddf7766d..ff12fda38 100644
--- a/src/components/data-table/index.js
+++ b/src/components/data-table/index.js
@@ -107,18 +107,23 @@ function DataTable({
return rowContainer.map((row, i) => {
prepareRow(row);
- const tableProps = row.getRowProps();
+ const tableProps = {...row.getRowProps()};
tableProps.className = `${
row.depth >= 1 ? 'expanded' : ''
}`;
+ delete tableProps.key;
return (
-
- {row.cells.map((cell) => {
+
+ {row.cells.map((cell, i) => {
+ const cellProps = {...cell.getCellProps()};
+ const cellKey = cellProps.key;
+ delete cellProps.key;
return (
{cell.render('Cell')}
|
@@ -135,9 +140,19 @@ function DataTable({
{headerGroups.map((headerGroup) => (
-
+
{
+ if (propName !== 'key') {
+ props[propName] = headerGroup.getHeaderGroupProps()[propName];
+ }
+ return props;
+ }, {})}>
{headerGroup.headers.map((column) => (
-
+ | {
+ if (propName !== 'key') {
+ props[propName] = column.getHeaderProps(column.getSortByToggleProps({ title: undefined }))[propName];
+ }
+ return props;
+ }, {})}>
{column.render('Header')}
@@ -176,7 +191,7 @@ function DataTable({
|
)}
-
+
{sumColumns && rows.length > 1 && (
diff --git a/src/features/achievements/index.js b/src/features/achievements/index.js
index 34b468143..4f1640005 100644
--- a/src/features/achievements/index.js
+++ b/src/features/achievements/index.js
@@ -4,7 +4,7 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import equal from 'fast-deep-equal';
import doFetchAchievements from './do-fetch-achievements.mjs';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
const initialState = {
data: [],
@@ -40,17 +40,24 @@ const achievementsSlice = createSlice({
export const achievementsReducer = achievementsSlice.reducer;
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useAchievementsData() {
const dispatch = useDispatch();
const { data, status, error } = useSelector((state) => state.achievements);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchAchievements());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -58,10 +65,9 @@ export default function useAchievementsData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/barters/index.js b/src/features/barters/index.js
index 2bec55558..285ec2881 100644
--- a/src/features/barters/index.js
+++ b/src/features/barters/index.js
@@ -122,7 +122,7 @@ export const selectAllBarters = createSelector([selectBarters, selectQuests, sel
return {
...barter,
requiredItems: barter.requiredItems.reduce((requirements, req) => {
- let matchedItem = items.find(it => it.id === req.item.id);
+ let matchedItem = items?.find(it => it.id === req.item.id);
if (matchedItem) {
requirements.push({
...req,
@@ -132,7 +132,7 @@ export const selectAllBarters = createSelector([selectBarters, selectQuests, sel
return requirements;
}, []),
rewardItems: barter.rewardItems.reduce((requirements, req) => {
- const matchedItem = items.find(it => it.id === req.item.id);
+ const matchedItem = items?.find(it => it.id === req.item.id);
if (matchedItem) {
requirements.push({
...req,
@@ -149,6 +149,11 @@ export const selectAllBarters = createSelector([selectBarters, selectQuests, sel
let fetchedData = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useBartersData() {
const dispatch = useDispatch();
const { status, error } = useSelector((state) => state.barters);
@@ -160,6 +165,7 @@ export default function useBartersData() {
if (!fetchedData) {
fetchedData = true;
dispatch(fetchBarters());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -167,8 +173,7 @@ export default function useBartersData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
}, [dispatch]);
diff --git a/src/features/bosses/index.js b/src/features/bosses/index.js
index 6bef322b6..5fec51bc4 100644
--- a/src/features/bosses/index.js
+++ b/src/features/bosses/index.js
@@ -4,7 +4,7 @@ import { createSlice, createAsyncThunk, createSelector } from '@reduxjs/toolkit'
import equal from 'fast-deep-equal';
import doFetchBosses from './do-fetch-bosses.mjs';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
import { placeholderBosses } from '../../modules/placeholder-data.js';
import rawBossData from '../../data/boss.json';
import useMapsData from '../maps/index.js';
@@ -89,27 +89,36 @@ export const selectAllBosses = createSelector([selectBosses, selectMaps], (bosse
return bosses;
});
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useBossesData() {
const dispatch = useDispatch();
const { status, error } = useSelector((state) => state.bosses);
const data = useSelector(selectAllBosses);
useMapsData();
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchBosses());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
dispatch(fetchBosses());
}, 600000);
}
- return () => clearInterval(refreshInterval);
- }, [dispatch]);
+ return () => {
+ clearRefreshInterval();
+ };
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/crafts/index.js b/src/features/crafts/index.js
index 6de1f8117..bed2fb261 100644
--- a/src/features/crafts/index.js
+++ b/src/features/crafts/index.js
@@ -161,6 +161,11 @@ export const selectAllCrafts = createSelector([selectCrafts, selectQuests, selec
let fetchedData = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useCraftsData() {
const dispatch = useDispatch();
const { status, error } = useSelector((state) => state.crafts);
@@ -172,6 +177,7 @@ export default function useCraftsData() {
if (!fetchedData) {
fetchedData = true;
dispatch(fetchCrafts());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -179,8 +185,7 @@ export default function useCraftsData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
}, [dispatch]);
diff --git a/src/features/hideout/index.js b/src/features/hideout/index.js
index 1b6fa7e1b..61679ab85 100644
--- a/src/features/hideout/index.js
+++ b/src/features/hideout/index.js
@@ -5,7 +5,7 @@ import equal from 'fast-deep-equal';
import doFetchHideout from './do-fetch-hideout.mjs';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
import { placeholderHideout } from '../../modules/placeholder-data.js';
const initialState = {
@@ -46,17 +46,24 @@ export const hideoutReducer = hideoutSlice.reducer;
export const selectAllHideoutModules = (state) => state.hideout.data;
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useHideoutData() {
const dispatch = useDispatch();
const { data, status, error } = useSelector((state) => state.hideout);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchHideout());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -64,10 +71,9 @@ export default function useHideoutData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/items/index.js b/src/features/items/index.js
index 53a246cff..ef1131bdf 100644
--- a/src/features/items/index.js
+++ b/src/features/items/index.js
@@ -5,7 +5,7 @@ import equal from 'fast-deep-equal';
import doFetchItems from './do-fetch-items.mjs';
import { placeholderItems } from '../../modules/placeholder-data.js';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
const initialState = {
data: placeholderItems(langCode()),
@@ -52,17 +52,24 @@ export const itemsReducer = itemsSlice.reducer;
export const selectAllItems = (state) => state.items.data;
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useItemsData() {
const dispatch = useDispatch();
const { data, status, error } = useSelector((state) => state.items);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchItems());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -70,10 +77,9 @@ export default function useItemsData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/maps/index.js b/src/features/maps/index.js
index d4d4f2cc7..5c856377f 100644
--- a/src/features/maps/index.js
+++ b/src/features/maps/index.js
@@ -17,7 +17,7 @@ import {
} from '@mdi/js';
import doFetchMaps from './do-fetch-maps.mjs';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
import { placeholderMaps } from '../../modules/placeholder-data.js';
import i18n from '../../i18n.js';
@@ -59,17 +59,24 @@ export const mapsReducer = mapsSlice.reducer;
export const selectMaps = (state) => state.maps.data;
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useMapsData() {
const dispatch = useDispatch();
const { data, status, error } = useSelector((state) => state.maps);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchMaps());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -77,10 +84,9 @@ export default function useMapsData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/meta/index.js b/src/features/meta/index.js
index 7d6482284..0950e327e 100644
--- a/src/features/meta/index.js
+++ b/src/features/meta/index.js
@@ -4,7 +4,7 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import equal from 'fast-deep-equal';
import doFetchMeta from './do-fetch-meta.mjs';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
import { placeholderMeta } from '../../modules/placeholder-data.js';
const initialState = {
@@ -43,17 +43,24 @@ export const metaReducer = metaSlice.reducer;
export const selectMeta = (state) => state.meta.data;
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useMetaData() {
const dispatch = useDispatch();
const { data, status, error } = useSelector((state) => state.meta);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchMeta());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -61,10 +68,9 @@ export default function useMetaData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/quests/index.js b/src/features/quests/index.js
index e6d07a4b4..15dbae296 100644
--- a/src/features/quests/index.js
+++ b/src/features/quests/index.js
@@ -4,7 +4,7 @@ import { createSlice, createAsyncThunk, createSelector } from '@reduxjs/toolkit'
import equal from 'fast-deep-equal';
import doFetchQuests from './do-fetch-quests.mjs';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
import { placeholderTasks } from '../../modules/placeholder-data.js';
const initialState = {
@@ -108,18 +108,25 @@ export const selectQuestsWithActive = createSelector([selectQuests, selectTrader
});
});
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useQuestsData() {
const dispatch = useDispatch();
const { status, error } = useSelector((state) => state.quests);
const data = useSelector(selectQuestsWithActive);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchQuests());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -127,10 +134,9 @@ export default function useQuestsData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang]);
return { data, status, error };
};
diff --git a/src/features/traders/index.js b/src/features/traders/index.js
index c66a2911b..8209c01e9 100644
--- a/src/features/traders/index.js
+++ b/src/features/traders/index.js
@@ -3,7 +3,7 @@ import { useSelector, useDispatch } from 'react-redux';
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import equal from 'fast-deep-equal';
-import { langCode } from '../../modules/lang-helpers.js';
+import { langCode, useLangCode } from '../../modules/lang-helpers.js';
import doFetchTraders from './do-fetch-traders.mjs';
import { placeholderTraders } from '../../modules/placeholder-data.js';
@@ -44,17 +44,24 @@ export const tradersReducer = tradersSlice.reducer;
export const selectAllTraders = (state) => state.traders.data;
-let fetchedData = false;
+let fetchedLang = false;
let refreshInterval = false;
+const clearRefreshInterval = () => {
+ clearInterval(refreshInterval);
+ refreshInterval = false;
+};
+
export default function useTradersData() {
const dispatch = useDispatch();
const { data, status, error } = useSelector((state) => state.traders);
+ const lang = useLangCode();
useEffect(() => {
- if (!fetchedData) {
- fetchedData = true;
+ if (fetchedLang !== lang) {
+ fetchedLang = lang;
dispatch(fetchTraders());
+ clearRefreshInterval();
}
if (!refreshInterval) {
refreshInterval = setInterval(() => {
@@ -62,10 +69,9 @@ export default function useTradersData() {
}, 600000);
}
return () => {
- clearInterval(refreshInterval);
- refreshInterval = false;
+ clearRefreshInterval();
};
- }, [dispatch]);
+ }, [dispatch, lang,]);
return { data, status, error };
};
diff --git a/src/modules/lang-helpers.js b/src/modules/lang-helpers.js
index c35ec957e..3b2d4563c 100644
--- a/src/modules/lang-helpers.js
+++ b/src/modules/lang-helpers.js
@@ -1,7 +1,22 @@
// Helper function to convert an i18n language to a two digit language code
+import { useEffect, useCallback, useState } from 'react';
+
import i18n from '../i18n.js';
import languages from '../data/supported-languages.json';
+function validateLangCode(lng) {
+ // Convert to two character language code
+ const langFmt = lng.replace(/-[a-zA-Z]{2}/, "");
+
+ // Check if the language is supported
+ if (languages.includes(langFmt)) {
+ return langFmt;
+ } else {
+ // If the language is not supported, fall back to en
+ return 'en';
+ }
+}
+
export function langCode() {
if (!i18n.isInitialized) {
//console.log('i18n still not ready');
@@ -19,3 +34,22 @@ export function langCode() {
return 'en';
}
};
+
+export const on = i18n.on;
+
+export const off = i18n.off;
+
+export function useLangCode() {
+ const [lang, setLang] = useState(langCode());
+
+ const eventListener = useCallback((lng) => {
+ setLang(validateLangCode(lng));
+ }, [setLang]);
+
+ useEffect(() => {
+ i18n.on('languageChanged', eventListener);
+ return () => i18n.off('languageChanged', eventListener);
+ }, [eventListener]);
+
+ return lang;
+}