feat: use new db site, cache requests to avoid repeated unneeded fetch calls
This commit is contained in:
@@ -4,6 +4,7 @@ import { useState, useEffect, useMemo } from 'react';
|
||||
import { useInventoryStore } from '@/store/useInventoryStore';
|
||||
|
||||
import { isKiller } from '../../lib/utils';
|
||||
import { DB_BASE_URL, fetchCharacters } from '../../lib/db';
|
||||
|
||||
import shared from '../../styles/shared.module.css';
|
||||
import styles from '../../styles/Characters.module.css';
|
||||
@@ -16,7 +17,7 @@ type Character = {
|
||||
|
||||
const getIconUrl = (iconFilePath: string) => {
|
||||
const fileName = iconFilePath.split('/').pop()?.split('.')[0];
|
||||
return `/icons/character-icons/${fileName}.png`;
|
||||
return `${DB_BASE_URL}/icons/character-icons/${fileName}.png`;
|
||||
};
|
||||
|
||||
type RoleFilter = 'all' | 'survivors' | 'killers';
|
||||
@@ -29,10 +30,7 @@ export default function CharactersPage() {
|
||||
const [role, setRole] = useState<RoleFilter>('all');
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/data/characters.json')
|
||||
.then(r => r.json())
|
||||
.then(setCharacters)
|
||||
.catch(() => []);
|
||||
fetchCharacters().then(setCharacters);
|
||||
}, []);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import shared from '../../styles/shared.module.css';
|
||||
import styles from '../../styles/Customizations.module.css';
|
||||
|
||||
import { getFileName, cleanFolderName, isKiller } from '../../lib/utils';
|
||||
import { fetchCharacters, fetchCustomizations } from '../../lib/db';
|
||||
import { Character, CustomizationItem, RoleFilter, Tab, TAB_CATEGORIES, CATEGORY_ORDER } from './types';
|
||||
import CharacterPicker from './CharacterPicker';
|
||||
import CharacterCosmetics from './CharacterCosmetics';
|
||||
@@ -31,13 +32,11 @@ export default function CustomizationsPage() {
|
||||
const [page, setPage] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
fetch('/data/customization_items.json').then(r => r.json()).catch(() => []),
|
||||
fetch('/data/characters.json').then(r => r.json()).catch(() => []),
|
||||
]).then(([items, chars]) => {
|
||||
setAllItems(items);
|
||||
setCharacters(chars);
|
||||
});
|
||||
Promise.all([fetchCustomizations(), fetchCharacters()])
|
||||
.then(([items, chars]) => {
|
||||
setAllItems(items);
|
||||
setCharacters(chars);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => { setPage(1); }, [tab, search]);
|
||||
|
||||
@@ -26,17 +26,20 @@ export const TAB_CATEGORIES: Partial<Record<Tab, number>> = {
|
||||
charms: 8, badges: 9, banners: 10, portraits: 11,
|
||||
};
|
||||
|
||||
import { DB_BASE_URL } from '../../lib/db';
|
||||
|
||||
export const getCosmeticIconUrl = (
|
||||
item: CustomizationItem,
|
||||
characterMap: Map<number, string>
|
||||
): string => {
|
||||
const file = (item.iconFilePath.split('/').pop() ?? '').split('.')[0];
|
||||
const base = DB_BASE_URL;
|
||||
|
||||
switch (item.category) {
|
||||
case 8: return `/icons/customization/charms/${file}.png`;
|
||||
case 9: return `/icons/customization/badges/${file}.png`;
|
||||
case 10: return `/icons/customization/banners/${file}.png`;
|
||||
case 11: return `/icons/customization/portrait-backgrounds/${file}.png`;
|
||||
case 8: return `${base}/icons/customization/charms/${file}.png`;
|
||||
case 9: return `${base}/icons/customization/badges/${file}.png`;
|
||||
case 10: return `${base}/icons/customization/banners/${file}.png`;
|
||||
case 11: return `${base}/icons/customization/portrait-backgrounds/${file}.png`;
|
||||
}
|
||||
|
||||
const subfolder =
|
||||
@@ -50,5 +53,5 @@ export const getCosmeticIconUrl = (
|
||||
const charFolder = (charName ?? item.associatedCharacter.toString())
|
||||
.replace(/[\\/:*?"<>|]/g, '_');
|
||||
|
||||
return `/icons/customization/characters/${charFolder}/${subfolder}/${file}.png`;
|
||||
return `${base}/icons/customization/characters/${charFolder}/${subfolder}/${file}.png`;
|
||||
};
|
||||
+3
-4
@@ -6,6 +6,7 @@ import shared from '../../styles/shared.module.css';
|
||||
import styles from '../../styles/Dlcs.module.css';
|
||||
import { PlatformFilter, isOnSteam, isOnEpic, isOnXbox, matchesPlatform, } from './types';
|
||||
import { DLC, isNamedDLC } from '@/lib/utils';
|
||||
import { fetchDLCs } from '@/lib/db';
|
||||
|
||||
const PLATFORM_FILTER_LABELS: Record<PlatformFilter, string> = { all: 'All', steam: 'Steam', epic: 'Epic', xbox: 'Xbox' };
|
||||
|
||||
@@ -18,10 +19,8 @@ export default function DlcsPage() {
|
||||
const [statusFilter, setStatusFilter] = useState<'all' | 'unlocked' | 'locked'>('all');
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/data/dlcs.json')
|
||||
.then(r => r.json())
|
||||
.then((data: DLC[]) => setAllDlcs(data.filter(isNamedDLC)))
|
||||
.catch(() => []);
|
||||
fetchDLCs()
|
||||
.then((data: DLC[]) => setAllDlcs(data.filter(isNamedDLC)));
|
||||
}, []);
|
||||
|
||||
const filtered = useMemo(() => {
|
||||
|
||||
+6
-7
@@ -7,6 +7,7 @@ import shared from '../../styles/shared.module.css';
|
||||
import styles from '../../styles/Items.module.css';
|
||||
|
||||
import { Item, Offering } from './types';
|
||||
import { fetchItems, fetchOfferings } from '../../lib/db';
|
||||
import ItemGrid from './ItemGrid';
|
||||
import OfferingGrid from './OfferingGrid';
|
||||
|
||||
@@ -23,13 +24,11 @@ export default function ItemsPage() {
|
||||
const [randMax, setRandMax] = useState(200);
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
fetch('/data/items.json').then(r => r.json()).catch(() => []),
|
||||
fetch('/data/offerings.json').then(r => r.json()).catch(() => []),
|
||||
]).then(([i, o]) => {
|
||||
setItems(i);
|
||||
setOfferings(o);
|
||||
});
|
||||
Promise.all([fetchItems(), fetchOfferings()])
|
||||
.then(([i, o]) => {
|
||||
setItems(i);
|
||||
setOfferings(o);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleClearAll = () => {
|
||||
|
||||
+4
-2
@@ -1,3 +1,5 @@
|
||||
import { DB_BASE_URL } from '../../lib/db';
|
||||
|
||||
export type Item = {
|
||||
id: string;
|
||||
name: string;
|
||||
@@ -31,12 +33,12 @@ export const getItemType = (id: string): ItemType => {
|
||||
|
||||
export const getItemIconUrl = (iconFilePath: string) => {
|
||||
const file = (iconFilePath.split('/').pop() ?? '').split('.')[0];
|
||||
return `/icons/item-icons/${file}.png`;
|
||||
return `${DB_BASE_URL}/icons/item-icons/${file}.png`;
|
||||
};
|
||||
|
||||
export const getOfferingIconUrl = (iconFilePath: string) => {
|
||||
const file = (iconFilePath.split('/').pop() ?? '').split('.')[0];
|
||||
return `/icons/offering-icons/${file}.png`;
|
||||
return `${DB_BASE_URL}/icons/offering-icons/${file}.png`;
|
||||
};
|
||||
|
||||
export const randInRange = (min: number, max: number) => {
|
||||
|
||||
+6
-5
@@ -4,6 +4,7 @@ import { useState, useEffect, useMemo } from 'react';
|
||||
import { useInventoryStore } from '@/store/useInventoryStore';
|
||||
import styles from '../styles/Home.module.css';
|
||||
import { isNamedDLC } from '@/lib/utils';
|
||||
import { fetchCharacters, fetchItems, fetchOfferings, fetchCustomizations, fetchDLCs } from '@/lib/db';
|
||||
|
||||
export default function Home() {
|
||||
const store = useInventoryStore();
|
||||
@@ -18,11 +19,11 @@ export default function Home() {
|
||||
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
fetch('/data/characters.json').then(r => r.json()).catch(() => []),
|
||||
fetch('/data/items.json').then(r => r.json()).catch(() => []),
|
||||
fetch('/data/offerings.json').then(r => r.json()).catch(() => []),
|
||||
fetch('/data/customization_items.json').then(r => r.json()).catch(() => []),
|
||||
fetch('/data/dlcs.json').then(r => r.json()).catch(() => [])
|
||||
fetchCharacters(),
|
||||
fetchItems(),
|
||||
fetchOfferings(),
|
||||
fetchCustomizations(),
|
||||
fetchDLCs()
|
||||
]).then(([chars, items, offerings, customizations, dlcs]) => {
|
||||
setCharCount(chars.length);
|
||||
setItemsCount(items.length);
|
||||
|
||||
Reference in New Issue
Block a user